javascript - 如何取消异步 promise 中的订阅以避免 Reactjs 中的内存泄漏

标签 javascript reactjs promise

在我的 React 组件中,我有一个 async 请求,它向我的 Redux 存储分派(dispatch)一个操作,该操作在 useEffect Hook 中调用:

    const loadFields = async () => {
        setIsLoading(true);
        try {
            await dispatch(fieldsActions.fetchFields(user.client.id));
        } catch (error) {
            setHasError(true);
        }
        setIsLoading(false);
    }
    useEffect(() => { if(isOnline) { loadFields() } }, [dispatch, isOnline]);

该操作通过获取请求请求数据:

    export const fetchFields = clientId => {
        return async dispatch => {
            try {
                const response = await fetch(
                    Api.baseUrl + clientId + '/fields',
                    { headers: { 'Apiauthorization': Api.token } }
                );

                if (!response.ok) {
                    throw new Error('Something went wrong!');
                }

                const resData = await response.json();
                dispatch({ type: SET_FIELDS, payload: resData.data });
            } catch (error) {
                throw error;
            }
        }
    };

    export const setFields = fields => ({
        type    : SET_FIELDS,
        payload : fields
    });

当它在 React 应用程序中呈现时,会导致以下警告:

无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,取消 %s 中的所有订阅和异步任务。%s,一个 useEffect 清理函数

我相信这是因为 promise 没有“清理”功能。但我不确定把它放在哪里?我是否应该在 LoadFields() 中包含一些逻辑?还是必须在 useEffect Hook 中完成?

最佳答案

tutorial这将帮助您解决问题。

简单示例:使用 Promises

function BananaComponent() {

  const [bananas, setBananas] = React.useState([])

  React.useEffect(() => {
    let isSubscribed = true
    fetchBananas().then( bananas => {
      if (isSubscribed) {
        setBananas(bananas)
      }
    })
    return () => isSubscribed = false
  }, []);

  return (
    <ul>
    {bananas.map(banana => <li>{banana}</li>)}
    </ul>
  )
}

简单示例:使用 async/await(不是最好的,但应该与匿名函数一起使用)

function BananaComponent() {

  const [bananas, setBananas] = React.useState([])

  React.useEffect(() => {
    let isSubscribed = true
    async () => {
      const bananas = await fetchBananas();
      if (isSubscribed) {
        setBananas(bananas)
      }
    })();

    return () => isSubscribed = false
  }, []);

  return (
    <ul>
    {bananas.map(banana => <li>{banana}</li>)}
    </ul>
  )
}

关于javascript - 如何取消异步 promise 中的订阅以避免 Reactjs 中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58166044/

相关文章:

javascript - 是否可以执行两次匿名函数?

javascript - 使用 TimelineJS 和 AMD

javascript - 如何使用 RxJS 发出多个 HTTP 请求并将响应合并到一个有效负载中并将其映射到另一个操作?

javascript - 如何使用react-redux-forms和自定义reducer避免表单对象的奇怪嵌套

reactjs - 如何在useState中使用数组?

promise - Elixir,默认关键字列表参数

javascript - 如何在 for 循环中使用带有超时的 promise ?

javascript - 如何使用 javascript/jquery 操作 xml 文件

javascript - 正则表达式搜索 html 返回,但不是实际的 html jQuery

node.js - node/express 中的 async/await 似乎不等待 Promise 解决