由于react钩子依赖于执行顺序,因此通常不应在循环内使用钩子。我遇到了几个情况,在这种情况下,我对钩子有不断的输入,因此应该没有问题。我唯一想知道的是如何执行输入是恒定的。
以下是一个简化的示例:
const useHookWithConstantInput = (constantIdArray) => {
const initialState = buildInitialState(constantIdArray);
const [state, changeState] = useState(initialState);
const callbacks = constantIdArray.map((id) => useCallback(() => {
const newState = buildNewState(id, constantIdArray);
changeState(newState);
}));
return { state, callbacks };
}
const idArray = ['id-1', 'id-2', 'id-3'];
const SomeComponent = () => {
const { state, callbacks } = useHookWithConstantInput(idArray);
return (
<div>
<div onClick={callbacks[0]}>
{state[0]}
</div>
<div onClick={callbacks[1]}>
{state[1]}
</div>
<div onClick={callbacks[2]}>
{state[2]}
</div>
</div>
)
}
是否有如何强制执行constantIdArray
不更改的模式?我的想法是将创建器函数用于这样的钩子:
const createUseHookWithConstantInput = (constantIdArray) => () => {
...
}
const idArray = ['id-1', 'id-2', 'id-3'];
const useHookWithConstantInput = createUseHookWithConstantInput(idArray)
const SomeComponent = () => {
const { state, callbacks } = useHookWithConstantInput();
return (
...
)
}
您如何解决这样的情况?
做到这一点的一种方法是将useEffect
与空依赖关系列表一起使用,以便仅运行一次。在此内部,您可以设置回调,之后它们将永远不会更改,因为useEffect
不会再运行。看起来如下:
const useHookWithConstantInput = (constantIdArray) => {
const [state, changeState] = useState({});
const [callbacks, setCallbacks] = useState([]);
useEffect(() => {
changeState(buildInitialState(constantIdArray));
const callbacksArray = constantIdArray.map((id) => {
const newState = buildNewState(id, constantIdArray);
changeState(newState);
});
setCallbacks(callbacksArray);
}, []);
return { state, callbacks };
}
尽管这将在第一次运行时设置两个状态,而不是给它们初始值,但我认为它比建立状态并每次运行时都会创建新的回调。
如果您不喜欢此路线,则可以创建像SO const [constArray, setConstArray] = useState(constantIdArray);
这样的状态,并且由于给出的useState
的参数仅用作默认值,因此即使constantIdArray
更改,它也永远不会更改。然后,您只需要在其余的钩子中使用constArray
即可确保它始终是初始值。
要使用的另一个解决方案是useMemo
。这就是我最终实施的方法。
const createCallback = (id, changeState) => () => {
const newState = buildNewState(id, constantIdArray);
changeState(newState);
};
const useHookWithConstantInput = (constantIdArray) => {
const initialState = buildInitialState(constantIdArray);
const [state, changeState] = useState(initialState);
const callbacks = useMemo(() =>
constantIdArray.map((id) => createCallback(id, changeState)),
[],
);
return { state, callbacks };
};