【问题标题】:How to sto React useEffect hook from rendering duplicated data如何阻止 React useEffect 钩子渲染重复数据
【发布时间】:2020-11-19 18:30:44
【问题描述】:

我有一个组件,我使用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 之前尝试过使用我最初拥有的 reducer,并且据我所知,如果没有任何改变,那么为什么我的 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 结合使用,同时仍然拥有我的 reducer……

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

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

【问题讨论】:

    标签: reactjs react-hooks usecallback


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2020-07-06
      • 2021-04-17
      • 2021-05-18
      • 2020-06-27
      • 1970-01-01
      • 2021-11-11
      • 2021-04-27
      • 2021-08-25
      • 1970-01-01
      相关资源
      最近更新 更多