React Hooks useEffect从useCallback调用prop回调

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

我正在尝试使用React Hooks(和ResearchGate React Intersection观察器)制作一个通用的无限滚动器。这个想法是,父对象将传递一个映射的JSX数据数组,并传递一个回调,该回调将异步获取该数组的更多数据,并且当交集观察者触发时,因为您向下滚动足以显示加载图标,该回调将调用并加载更多数据。

效果很好,除了一件事:esLint告诉我,因为我正在useEffect内调用getMore函数(来自props),所以它必须是该效果的依赖项。但是因为在父级的回调中,我正在访问其数据数组的长度,所以该数组必须是useCallback的依赖项。然后该回调修改数组。

TL; DR:我遇到了导致不正确的异步回调多次触发的竞争状况,因为回调函数引用正在更改,然后传递给正在调用它的事物。

这里有一些代码需要澄清。

父级中的回调:

const loadData = useCallback(async () => {
    if (hasMore) {
        const startAmount = posts.length;
        for (let i = 0; i < 20; ++i) {
            posts.push(`I am post number ${i + startAmount}.`);
            await delay(100);
        }
        setPosts([...posts]);
        setHasMore(posts.length < 100);
    }
}, [posts, hasMore]);

posts和hasMore只是状态变量,posts作为props中的数据数组传递给子级。该函数将通过props传递给子级,而props具有此子项(getMore是回调的分解后的prop,isLoading只是一个布尔状态变量):

useEffect(() => {
    if (isLoading) {
        (async () => {
            await getMore();
            setIsLoading(false);
        })();
    }
}, [isLoading, getMore]);

我将isLoading设置为true以触发效果;但它也会触发,因为当父级加载数据并且该函数进行记忆时,getMore的引用会更改。那不应该发生的。我可以为此行禁用esLint,但我认为有更好的解决方案,我想知道它是什么。

javascript reactjs react-hooks race-condition use-effect
1个回答
0
投票

解决方案:根本不使用useEffect。只需直接从观察者调用加载函数,并设置isLoading并调用回调即可,而不是让isLoading触发回调。

© www.soinside.com 2019 - 2024. All rights reserved.