如何停止使用中的内存泄漏

时间:2019-09-21 06:59:16

标签: reactjs react-table use-effect

我正在使用效果钩子从服务器获取数据,这些数据被传递到反应表,在那里我使用相同的api调用从服务器加载下一组数据。 当应用程序加载后,我会收到如下警告

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

效果钩子:

useEffect(() => {
setPageLoading(true);
props
  .dispatch(fetchCourses())
  .then(() => {
    setPageLoading(false);
  })
  .catch((error: string) => {
    toast.error(error);
    setPageLoading(false);
  });
}, []);

反应表页面:

<ReactTable
  className="-striped -highlight"
  columns={columns}
  data={coursesData}
  defaultPage={currentPage}
  defaultPageSize={courses.perPage}
  loading={isLoading}
  manual={true}
  onFetchData={setFilter}
/>

设置过滤器功能

const setFilter = (pagination: any) => {
  props.dispatch(updateCoursePageSize(pagination.pageSize));
  props.dispatch(updateCourseCurrentPage(pagination.page + 1));
  setCurrentPage(pagination.page);
  setPerPage(pagination.pageSize);
  setLoading(true);
  props.dispatch(fetchCourses()).then(() => {
    setLoading(false);
  });
};

有人知道如何清理React中的钩子吗?

2 个答案:

答案 0 :(得分:5)

使用useEffect可以返回一个将在清理时运行的函数。因此,在您的情况下,您需要这样的东西:

useEffect(() => {
  let unmounted = false;

  setPageLoading(true);

  props
    .dispatch(fetchCourses())
    .then(() => {
      if (!unmounted) {
        setPageLoading(false);
      }
    })
    .catch((error: string) => {
      if (!unmounted) {
        toast.error(error);
        setPageLoading(false);
      }
    });

  return () => { unmounted = true };
}, []);

编辑:如果您需要在useEffect之外启动的调用,那么它仍然需要检查一个未装入的变量,以告知是否应跳过对setState的调用。该卸载的变量将由useEffect设置,但是现在您需要经历一些障碍,以使该变量可以在效果之外访问。

const Example = (props) => {
  const unmounted = useRef(false);
  useEffect(() => {
    return () => { unmounted.current = true }
  }, []);

  const setFilter = () => {
    // ...
    props.dispatch(fetchCourses()).then(() => {
      if (!unmounted.current) {
        setLoading(false);
      }
    })
  }

  // ...
  return (
    <ReactTable onFetchData={setFilter} /* other props omitted */ />
  );
}

答案 1 :(得分:2)

其他答案当然有用,我只想分享我想出的解决方案。 我构建了这个hook,它的工作方式与React的useState一样,但是只有在安装了组件的情况下才可以设置setState。我觉得它更优雅,因为您不必在组件中混入isMounted变量!

安装:

npm install use-state-if-mounted

用法:

const [count, setCount] = useStateIfMounted(0);

您可以在挂钩的npm page上找到更多高级文档。