如何避免在嵌套钩子中重复工作(或保持 common/shared 状态)?

How to avoiding repeating work (or to keep common/shared state) in nested hooks?

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

最好没有 Component author/the 钩子用户必须知道这一点并且不必做任何特殊的事情就可以工作。

例子

举例说明问题:

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),它与实例没有直接关系。 IE。两个 useState() 调用和两个实例是 4 个状态值。

您可以使用 共享状态 例如使用 context,但随后状态也会被所有实例共享,而不仅仅是钩子(你不想要的)。

所以 useNestedHook() 永远是“独立的”,但是如果你可以使用共享状态,并且你只关心 “缓存”,并且可以接受useNestedHook() 被调用了两次(即,如果结果相同,则跳过昂贵的操作),然后您可以使用 useEffect()。 IE。该调用将取决于 ,而不是实例而不是挂钩。

一些例子:

1。一个带选项的挂钩

例如如果你的钩子 AB 可以选择计算两个不同的值,它们需要相同的 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 );
};

但我可以想象您不能(或不喜欢)那样做的原因。