首页 > 解决方案 > 如何从渲染重复数据中存储 React useEffect 钩子

问题描述

我有一个组件,我在其中使用useEffect并在内部调用一个函数fetchLatest()fetchLatest()是一个动作,它发出网络请求以获取当年已发布的所有电影。我正在使用 Redux,在我的商店里我有一个state.movies.latest,每次我第一次启动应用程序时,最新的电影行都是准确的,没有重复的数据。当我渲染一个不同的组件并返回我的主组件时,我会fetchLatest得到重复的数据。

我发现我的问题是因为在我的减速器中我返回了类似...

return {
    ...state,
    latest: [...state, ...payload]
}

其中payload是对象(电影)的数组。

所以我把减速机改成...

return {
    ...state,
    latest: [...payload]
}

它现在可以工作,我没有得到重复的数据,但我担心我没有正确地做或理解这一点。如果我要使用 useEffect 并将我的 fetchLatest 函数放在我的 useEffect 挂钩中,并将其作为依赖项传递给我的理解,我的函数fetchLatest将在每个渲染周期后重新创建为一个全新的对象。由于我已经在商店中有我latest的电影数组,因此我不想每次都重新渲染一个全新的对象,从而导致在我的state.movies.latest重复数据中添加到我的商店中。我至少相信这就是它正在做的事情。

我决定也许我应该使用它来确保除非它的依赖关系发生变化,否则不会创建useCallback这个全新的对象。fetchLatest

所以我不确定的是,也许我可以拥有我现在拥有的更新的减速器,并且还使用回调来确保在我重新构建该组件时,每次都没有无限循环运行以将我的 fetchLatest 函数重新创建为新对象?

另外,我实际上可能不了解 useCallback 的作用,因为我在使用 useCallback 之前尝试过使用我最初拥有的减速器,并且据我所知,如果没有任何改变,那么为什么我的 fetchLatest 在我重建组件时运行。当我第一次安装我的组件时,我只想要我在商店中已经拥有的最新电影

我的这个组件的代码看起来像这样

const Latest = ({ fetchLatest, latest }) => {
  useEffect(() => {
    fetchLatest();
  }, [fetchLatest]);

  return (
    <div className='genre-temp'>
      <h3 className='text-light'>Latest</h3>
      <div className='movies-container d-flex'>
        {latest.map((movie) => (
          <Movie
            key={movie.id}
            movieId={movie.id}
            image={movie.image}
            title={movie.title}
            description={movie.description}
          />
        ))}
      </div>
    </div>
  );
};

我最初尝试做的是在我的 useEffect 中添加这个 useCallback 并调用 handleFetching 并将其作为依赖项传递。

const handleFetching = useCallback(() => {
    fetchLatest()
}, []);

但是,useCallback 与 useEffect 结合使用,同时仍然拥有我的减速器......

return {
    ...state,
    latest: [...state, ...payload]
}

每次重建组件时仍然会运行。

标签: reactjsreact-hooksusecallback

解决方案


尝试将请求状态添加到您的状态对象。然后,您将能够检查列表是否已获取。通常,我对请求使用四种状态:初始化、请求、成功、失败。这是一个请求的粗略示例:

if (requestState !== 'request' && requestState !== 'success') {
    try {
        setRequestState('request');
        const response = await fetchList();
        setList(response);
        setRequestState('success');
    catch (e) {
        setRequestState('failure');
        log(e);
    }
}

如果您有请求状态,您将始终知道何时需要请求数据、显示微调器、显示错误消息等。希望您明白了。

PS在您的代码中,它应该是:

{
    ...state,
    latest: [...payload]
}

latest: [...state.latest, ...payload] 不会像您期望的那样工作。最新:[...state, ...payload] 看起来不对。


推荐阅读