【问题标题】:react-redux useCallback infinite renderreact-redux useCallback 无限渲染
【发布时间】:2020-01-09 15:44:33
【问题描述】:

我正在尝试将“动作调度”传递给子组件并陷入无限渲染循环,这是我所拥有的一个简单示例:

const ParentComponent = () => {
  const dispatch = useDispatch();
  const error = useSelector(getError);
  const fetching = useSelector(getFetching);
  const things = useSelector(getThings);

  const fetchData = useCallback(arg => { dispatch(fetchThings(arg)); });
  return (
   {error && <span>{error}</span>}
   {fetching &&< <span>Fetching...</span>}
   {!fetching && (
     <ChildComponent fetchData={fetchData} data={things} />
   })
  );
};

const ChildComponent = ({fetchData, data, ...otherStuff}) => {
  const [arg, setArg] = useState();
  useEffect(() => { fetchData(arg); }, [fetchData, arg]);

  return (
   ... MARKUP ...
  );
};
export default ChildComponent;

“arg”是孩子中的一个变量,我可以在 UI 中更改,我希望在数据更改时重新调整数据。在初始渲染(和无限渲染)时,我可以看到它永远不会改变。 Per the docs,我觉得还可以;我做错了什么?

【问题讨论】:

  • 如果在useEffect中放置了一个空的依赖数组,是否还会出现死循环?不建议将此作为修复,只是一个故障排除步骤。如果这停止了循环,它会告诉您问题出在哪里。
  • 它仍然发生。我看到当我分派 fetch 时,它改变了 fetching 变量状态,它重新渲染了父级,这让一切都退缩了。不知道如何处理,这只是将 Container/Presenter redux 连接模式转换为钩子。
  • 我认为问题在于useCallback 还需要一个依赖数组,否则它将在每个正在更改fetchData 并导致useEffect 再次运行的渲染上创建一个新回调。在您从文档链接的示例中,您将看到 dispatch 被传递给回调依赖数组。所以应该是const fetchData = useCallback(arg =&gt; { dispatch(fetchThings(arg)); }, [dispatch]);

标签: reactjs redux react-redux react-hooks


【解决方案1】:

正如@azundo 在 cmets 中指出的那样,这里的问题是 useCallback 中缺乏依赖关系。

如果没有传递依赖,useCallback 在每次渲染中创建一个新的函数引用。当函数被传递给ChildComponent 时,它实际上是一个新的函数引用。所以每个渲染 useEffect(() =&gt; { fetchData(arg); }, [fetchData, arg]); 都会收到一个新的 fetchData 函数并运行它。

要解决它,只需将依赖项传递给useCallback。在这种情况下,如果useCallback 中的函数在第一次渲染后不会改变(我假设fetchThingsdispatch 都没有改变,如果他们改变了,传递它们)我们可以传递一个空数组。

const fetchData = useCallback(arg => { dispatch(fetchThings(arg)); }, []);

也就是说,如果 ChildComponent 没有被记忆,我不确定你是否获得了 useCallback 的好处,因为无论如何它会在每次父级时呈现。

【讨论】:

  • 这是真的,但我实际上在我的 args 中有一个依赖列表,我只是在我的帖子中错过了它。此外,内联条件渲染 ({!fetching && ) 正在删除并重新创建子项(每次创建时都会获取)并导致循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
  • 1970-01-01
  • 2019-09-21
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多