访问 useEffect 中的变量而不在它们更新时触发效果

Access variables in a `useEffect` without triggering the effect when they get updated

我需要访问 useEffect 中的变量,但只有当其中一些变量得到更新时才会触发该方法。

例如:

我想在 data 更改时调用 useEffect,但在 saveTimeoutsaveMethod 更改时不调用。

以同样的方式,我想在我的组件卸载时调用 saveMethod,但我不能,因为它需要在依赖数组中,因此在 [=15= 的每次更改时调用它].

function SavingComponent({data, apiInfo}){
    [saveTimeout, setSaveTimeout] = useState(null);

    const saveMethod = useCallBack(()=>{
        clearTimeout(saveTimeout);

        // api call to save the data using apiInfo

    }, [data, saveTimeout, apiInfo])

    // Start a timer to save the data 2 seconds after it is changed (not working)
    useEffect(()=>{
        clearTimeout(saveTimeout);
        setSaveTimeout(setTimeout(saveMethod, 2000));
    }, [data, saveTimeout, saveMethod]);

    // Save immediately on dismount only (not working)
    useEffect(()=>{
      return ()=> { saveMethod(); }
    },[saveMethod])

    return (// some rendering)
}

这是一个问题,我经常运行处理其他案例,不得不四处寻找。通常使用自定义 usePrevious 方法。如果我感兴趣的道具没有改变,我会立即将道具的先前值与当前值和 return 进行比较。

function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}

只有在更新某些依赖项时才调用 useEffect 的正确方法是什么?

首先,建议将 useEffect 中使用的变量和函数作为依赖项,这也是最佳实践。 This is a very good article written by Dan Abramov 深入探讨了 useEffect 的工作原理以及您需要遵循该最佳实践的原因。

现在回到你的案例。

我不认为你希望组件在你设置 saveTimeout 时重新渲染,所以使用 useState 你可以 useRef saveTimeout = useRef(null) 所以你可以从依赖项中删除 saveTimeout

如果您不希望 saveMethod 处于依赖项中,您可以将其移至 useEffect 中,这样您也可以将其从依赖项中删除。

function SavingComponent({data, apiInfo}){
    const saveTimeout = useRef(null);

    // move saveMethod inside
    useEffect(()=>{
        const saveMethod = ()=>{
            clearTimeout(saveTimeout.current);
            // api call to save the data using apiInfo
        }
        // saveMethod will be called after 2 seconds
        saveTimeout.current = setTimeout(saveMethod, 2000);
    }, [data]);

    // move saveMethod inside
    useEffect(()=>{
        const saveMethod = ()=>{
            // api call to save the data using apiInfo
        }
        // saveMethod will be call when the component unmounted
        // But make sure you are not update any state inside saveMethod
        return saveMethod
    },[])

    return (// some rendering)
}