在嵌套钩子中:如何知道它是否已经在当前组件(实例)中被调用并访问任何以前计算/保存的值?

最好不要让Component位作者/钩子用户知道这一点,也不需要做任何特殊的事情.

实例

举例说明这个问题:

const useNestedHook = () => {
    // Some heavy work with the same result for each component instance.
    // Is it possible to remember the result of this work when
    // this hook is used again in the same component instance?

    // So I would like to save a state which all uses of useNestedHook
    // could access as long as they are in the same component instance.
}

const useHookA = () => {
    useNestedHook();
};

const useHookB = () => {
    useNestedHook();
};

const Component = () => {
    useHookA();

    // Would like to avoid useNestedHook repeating its work since it's
    // used in the same component and would have this same result (per definition)
    // Preferably without the Component author having to know anything about this.
    useHookB();
};

想象的解决方案

类似于"命名"共享状态的东西,它将允许访问相同的共享状态(在相同的组件实例中),无论它在哪个钩子中使用.与往常一样,每个组件实例都有自己的独立状态.也许是这样的:

const [state, setState] = useSharedState("stateId", initialValue);

推荐答案

不,那是不可能的.每useState()个电话将始终与其他useState()个电话分开.

组件不能像您的示例中那样使用钩子,但组件作者不必关心实现细节.

解决方案将取决于用例.

一些细节:

一种状态是由useState()调用在代码中的写入位置定义的(参见explanation),它与实例没有直接关系.也就是说,两个useState()调用和两个实例是4个状态值.

您可以使用shared state,例如使用context,但状态也将由所有实例共享,而不仅仅是挂钩(您不想要).

所以useNestedHook()总是"独立的",但如果你可以使用共享状态,只关心"caching",并且可以接受useNestedHook()被调用两次(即,如果结果相同,跳过昂贵的操作),那么你可以使用useEffect().也就是说,调用将取决于value,而不是实例和钩子.

例如:

1.一个带选项的挂钩

例如,如果钩子AB可以 Select 计算两个不同的值,它们需要相同的useNestedHook()值,则可以创建一个带有选项的钩子,例如:

const useHookAB = ({ A, B }) => {
  const expensiveValue = useNestedHook();
  if( A ){ /* do what useHookA() was doing */ }
  if( B ){ /* do what useHookB() was doing */ }
};

const Component = () => {
    useHookAB({ A: true, B: true });
};

我现在想不出你为什么要这样叫钩子的另一个原因.

2."正常"方式

显而易见的解决方案是:

const useHookA = ( value ) => {
  // ...
};

const useHookB = ( value ) => {
  // ...
};

const Component = () => {
    const value = useNestedHook();
    useHookA( value );
    useHookB( value );
};

但我能想象为什么你不能(或不喜欢)那样做.

Javascript相关问答推荐

当我使用jQuery时,我的图标显示为[对象对象]

JavaScript代理不适用于打开的窗口对象

vue3类型脚本中可能未定义对象''

调用SEARCH函数后,程序不会结束

通过使用100%间隔时间来代表我们还剩多少时间来倒计时

在这种情况下,如何 for each 元素添加id?

数字时钟在JavaScript中不动态更新

阿波罗返回的数据错误,但在网络判断器中是正确的

在Three JS中看不到补间不透明度更改效果

我怎么才能得到Kotlin的密文?

单个HTML中的多个HTML文件

如何在Svelte中从一个codec函数中调用error()?

Use Location位置成员在HashRouter内为空

面对代码中的错误作为前端与后端的集成

在表单集中保存更改时删除';禁用';

JavaScript:如果字符串不是A或B,则

Next.js无法从外部本地主机获取图像

ReferenceError:无法在初始化之前访问setData

在ChartJS中使用spanGaps时,是否获取空值的坐标?

如何正确地在ComponentWillUnmount中卸载状态以避免内存泄漏?