首页 > 解决方案 > 反应 useContext 和 useEffect 显示陈旧数据

问题描述

https://codesandbox.io/s/react-usecontextuseeffect-stale-data-bug-l81sn

在一个组件useEffect中,当某个值发生变化时,我会做一些事情。现在它只是一个简单计数器的值,但在现实世界中它将是一个数组,其中删除或添加项目等。有点复杂。

useEffect我也有一个调整大小的检测。同样,在这个例子中不是很有趣。

const App = props => {
  const [count, dispatch] = useReducer((state, action) => {
    switch (action.type) {
      case 'INCREMENT':
        return state + 1;
      case 'DECREMENT':
        return state - 1;
      default:
        return state;
    }
  }, 0);
  return (
    <CountContext.Provider value={{ count, dispatch }}>
      <div className="App">
        <h1>App</h1>
        <Counter />
      </div>
    </CountContext.Provider>
  );
};

const Counter = () => {
  const counter = useContext(CountContext);

  useEffect(() => {
    window.addEventListener('resize', () => {
      console.log(counter.count);
    })
  },[counter])

  return (
    <div className="Counter">
      <p>Counter: {counter.count}</p>
      <input
        type="button"
        value="+"
        onClick={() => counter.dispatch({ type: 'INCREMENT' })}
      />
      <input
        type="button"
        value="-"
        onClick={() => counter.dispatch({ type: 'DECREMENT' })}
      />
    </div>
  );
};

问题是,当我调整视口大小时,会console.log(counter.count)显示所有以前的值:

在此处输入图像描述

标签: reactjs

解决方案


问题是 useEffect() 方法中的内存泄漏。您需要清理重新渲染。我分叉了你的沙箱并用它进行了测试,它按预期工作:

useEffect(() => {
    const resizeEvent = () => {
      console.log(counter.count);
    };
    window.addEventListener("resize", resizeEvent);
    return () => {
      window.removeEventListener("resize", resizeEvent);
    };
  }, [counter]);

请注意清理的返回并将代码重构为调用的函数,以便可以在卸载时正确删除它。


推荐阅读