当 useCallback 函数同时被 useEffect 和 onClick 处理程序调用时,有没有办法让 useEffect 拥有详尽的依赖?

问题描述 投票:0回答:1

我有一个与此类似的伪代码 React 组件:

const codeApplier = ({ code, prices }: Props) => {
  const [isAccepted, setIsAccepted] = useState(false);

  const applyCode = useCallback(async () => {
    const validationResult = await callToApplyCode(code, prices);

    if (validationResult.status === "OK") {
      setIsAccepted(true);
    } else {
      setIsAccepted(false);
    }
    //do more stuff

  }, [code, prices]);

  useEffect(() => {
    if (isAccepted) applyCode();
  }, [prices]);

  return <button onClick={applyCode} />;
};

重要部分:

  • 如果用户单击按钮我想应用代码
  • 如果价格发生变化我想重新应用代码

现在,像这样的组件工作正常,但 linter 抱怨在 useEffect 上我没有列出所有依赖项。臭名昭著的详尽部门规则。

问题是:如果我将“applyCode”(甚至 isAccepted)添加到 useEffect 的依赖项中,如下所示:

  useEffect(() => {
    if (isAccepted) applyCode();
  }, [isAccepted, applyCode, prices]);

然后 linter 很高兴,但是 useEffect 将在每次点击时重复调用。

  1. 更改“代码”-> 自动更改“应用代码”-> 预期
  2. onclick -> 调用新的 applycode -> 预期
  3. callToApplyCode -> 预期
  4. “applycode”变化触发的useEffect -> applycode(); -> 出乎意料
  5. 另一个 callToApplyCode -> 不需要

这是可以禁用详尽依赖的情况之一吗? 或者有没有一种方法可以在不影响 linter 的情况下重构组件?

我看了这个评论:https://github.com/facebook/react/issues/14920#issuecomment-471070149 以及 StackOverflow 上的各种类似问题,但我无法找到针对我的具体案例的答案。

reactjs react-hooks eslint lint
1个回答
0
投票

您可以使用 ref 来保存

isAccepted
的值,因此它可用于
useEffect
而无需将其设置为依赖项。

此外,您不需要使用

prices
作为
useEffect
的依赖项,因为每当
prices
更改时,
applyCode
也会更改。然而,
code
也会有这种效果,所以改变
code
也会触发
useEffect

const codeApplier = ({ code, prices }: Props) => {
  const [isAccepted, setIsAccepted] = useState(false);
  
  const isAcceptedRef = useRef(isAccepted); // save isAccepted as a ref as well
  
  useEffect(() => { // update the ref on each render
    isAcceptedRef.current = isAccepted;
  });

  const applyCode = useCallback(async () => {
    const validationResult = await callToApplyCode(code, prices);

    setIsAccepted(validationResult.status === "OK");
    
    //do more stuff

  }, [code, prices]);

  useEffect(() => {
    if (isAcceptedRef.current) applyCode(); // use the ref to decide when to apply
  }, [applyCode]); // applyCode would change when prices or code change

  return <button onClick={applyCode} />;
};
© www.soinside.com 2019 - 2024. All rights reserved.