与常数输入参数 - 钩创建器相关挂钩



由于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 };
};

相关内容

  • 没有找到相关文章

最新更新