由于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 (
...
)
}
您如何解决这种情况?
答案 0 :(得分:1)
执行此操作的一种方法是将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 };
}
尽管这将在第一次运行时设置两个状态,而不是给它们提供初始值,但我认为这比每次运行挂钩时都建立状态并创建新的回调要好。
如果您不喜欢此路由,则可以选择创建const [constArray, setConstArray] = useState(constantIdArray);
这样的状态,并且由于useState
所提供的参数仅用作默认值,因此它永远不会更改即使constantIdArray
发生了变化。然后,您只需要在钩子的其余部分中使用constArray
即可确保它始终仅是初始值。
答案 1 :(得分:0)
另一个可行的解决方案是使用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 };
};