React useContext&useEffect显示陈旧数据

时间:2020-08-04 21:05:49

标签: reactjs

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)显示所有以前的值:

enter image description here

2 个答案:

答案 0 :(得分:2)

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

$tableName = $query->getModel()->getTable();

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

答案 1 :(得分:1)

每次状态更改时,您都会添加一个新的eventListener。三个更改-三个eventListeners。此外,在卸载Counter组件时,侦听器会保持活动状态,从而导致内存泄漏。 首先,您可以在useEffect之外使用此部分:

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

或者您应该使用空数组作为useEffect中的依赖项列表,然后它将仅触发一次:

useEffect(() => {

}, []) // empty array here says 'do it once'

最后,useEffect是获取数据或预订事件等的理想场所。但不要忘记在不再需要组件后将其清除。为此,请返回useEffect中的清洗功能:

useEffect(() => {
  // your main logic here
  ...
  // cleaning up function:
  return () => {
    removeEventListener, unsubscribe etc...
  }

}, [])