reactjs 如何修复React Warning:无法在未挂载的组件上执行React状态更新

hrysbysz  于 2023-04-29  发布在  React
关注(0)|答案(1)|浏览(346)

每当有任何与组件相关的异步任务执行并且该组件卸载时,React通常会给出此警告-
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.
我在互联网上找到了一些解决方案,使用isMount标志(无论是通过使用useRef或useState)作为true,然后在组件卸载时将其更新为false。但是,根据React站点使用isMount的适当解决方案是一个反模式。
https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html

ddrv8njm

ddrv8njm1#

在未来的React版本中,你可能不需要修复这个问题。React开发团队将在未来的版本中删除此警告。主要原因是这种警告有时可能是假阳性。
作者:Dan Abramov https://github.com/facebook/react/pull/22114
但是在版本发布之前解决这个问题的解决方案是什么-
1.使用isMountState反模式-如果有人在他的代码中检查isMounted来解决这个问题,那么这个人在执行这个检查时已经太晚了,因为这个警告表明React已经完成了相同的检查并且失败了。
1.如果此问题是由于异步调用引起的。那么一个可能的解决方案是在代码中使用AbortController API。AbortController API可以帮助中止任何已经进行 AJAX 调用。很酷的东西。对吧?
更多细节可以在这里找到
Abort Controller1
因此,如果它是一个获取API,则可以像这样使用AbortController API

useEffect(() => {
  const abortController = new AbortController()
  // creating an AbortController
  fetch(url, {
      signal: abortController.signal
    })
    // passing the signal to the query
    .then(data => {
      setState(data)
      // if everything went well, set the state
    })
    .catch(error => {
      if (error.name === 'AbortError') return
      // if the query has been aborted, do nothing
      throw error
    })

  return () => {
    abortController.abort()
    // stop the query by aborting on the AbortController on unmount
  }
}, [])

如果你正在使用axios,那么好消息是axios还提供了对AbortController API的支持-

const fetchData = async (params) => {
        setLoading(true);
        try {
            const result = await axios.request(params);
            // more code here 

        } catch (curError) {
            if (axios.isCancel(curError)) {
                return false;
            }
            // error handling code 
        }
        return null;
    };

    useEffect(() => {
        const cancelToken = axios.CancelToken;
        const source = cancelToken.source();

            fetchData({
                ...axiosParams,
                cancelToken: source.token
            });
        
        return () => {
            source.cancel("axios request cancelled");
        };
    }, []);

相关问题