react-redux useCallback无限渲染

时间:2019-09-06 19:21:50

标签: reactjs redux react-redux react-hooks

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

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,对我来说还不错;我在做什么错了?

1 个答案:

答案 0 :(得分:0)

正如@azundo在评论中指出的,这里的问题是useCallback中缺少依赖项。

如果未传递任何依赖项,则useCallback将在每个渲染器中创建该函数的新引用。当函数传递给ChildComponent时,它实际上是一个新的函数引用。因此,每个渲染useEffect(() => { fetchData(arg); }, [fetchData, arg]);都会收到一个新的fetchData函数并运行它。

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

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

也就是说,如果没有记下ChildComponent,我不确定您会从useCallback那里受益,因为无论如何,每次父母都会这样做。