繁体   English   中英

无法对卸载的组件执行 React 状态更新。 React、redux 和 useEffect 的问题

[英]Can't perform a React state update on an unmounted component. Problem with React, redux and useEffect

我有一个使用钩子的 React 组件,如下所示:

const myComponent = (props) => {
  useEffect(() => {
     FetchData()
     .then(data => {
       setState({data: data});
     }
    // some other code
  }, []);

//some other code and render method...
}

fetchData 负责使用 axios 并从 API 获取数据:

const FetchData = async () => {
   try {
    res = await myApiClient.get('/myEndpoint);
   } catch (err) {
    console.log('error in FetchData');
    res = err.response
}
}

最后 myApiClient 是在外部定义的。 我必须使用此设置才能使用不同的 API...

import axios from "axios";
axios.defaults.headers.post["Content-Type"] = "application/json";

const myApiClient = axios.create({
  baseURL: process.env.REACT_APP_API1_BASEURL
});
const anotherApiClient = axios.create({
  baseURL: process.env.REACT_APP_API2_BASEURL
});

export {
  myApiClient,
  anotherApiClient
};

使用此设置,我收到警告

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 的请求的建议,就像这样,但我的 axios 是在外部定义的。 那么如何使用此设置发送取消通知?

此外,该应用程序正在使用 redux,不确定是否以某种方式涉及。

欢迎任何其他避免错误的建议。

您可以为此使用rxjs中的defer

const FetchData = () => {
  try {
    return myApiClient.get("/myEndpoint");
  } catch (err) {
    console.log("error in FetchData");
    return err.response;
  }
};

const myComponent = (props) => {
  useEffect(() => {
    const subscription = defer(FetchData()).subscribe({
      next: ({
        data
      }) => {
        setState({
          data: data
        });
      },
      error: () => {
        // error handling
      },
      complete: () => {
        // cancel loading state etc
      }
    });

    return () => subscription.unsubscribe();
  }, []);
}

始终检查您是否正在处理 fetch 或任何长时间操作。

let _isMounted = false;

const HooksFunction = props => {


  const [data, setData] = useState({}); // data supposed to be object

  const fetchData = async ()=> {
    const res = await myApiClient.get('/myEndpoint');
    if(_isMounted) setData(res.data); // res.data supposed to return an object
  }

  useEffect(()=> {

    _isMounted = true;

    return ()=> {
        _isMounted = false;
    }

  },[]);

  return (
    <div>
      {/*....*/}
    <div/>
  );

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM