访问`useEffect`中的变量,但在更新变量时不触发效果

时间:2020-05-11 09:23:50

标签: react-native use-effect

我需要访问useEffect中的变量,但仅在其中一些变量被更新时才触发该方法。

例如:

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

以同样的方式,我想在卸下组件时调用saveMethod,但是我不能,因为它必须位于依赖项数组中,因此在saveMethod的每次更改时都调用它。

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方法。我会将道具的先前值与当前值进行比较,如果我感兴趣的道具没有变化,则立即返回。

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

在某些依赖项得到更新时仅调用useEffect的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

首先要推荐并推荐在useEffect中使用变量和函数作为依赖项的方法。 This is a very good article written by Dan Abramov深入探讨了useEffect的工作原理以及为什么需要遵循最佳实践。

现在回到您的情况。

我认为您不希望在设置saveTimeout时重新渲染组件,因此可以使用useStateuseRef来替换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)
}