当前位置: 首页 > 面试题库 >

如何取消对componentWillUnmount的提取

孔阳炎
2023-03-14
问题内容

我认为标题说明了一切。每当我卸载仍在读取的组件时,都会显示黄色警告。

安慰

警告:无法在未安装的组件上调用setState(或forceUpdate)。这是一项禁忌措施,但是…若要修复,请取消方法中的所有订阅和异步任务componentWillUnmount

  constructor(props){
    super(props);
    this.state = {
      isLoading: true,
      dataSource: [{
        name: 'loading...',
        id: 'loading',
      }]
    }
  }

  componentDidMount(){
    return fetch('LINK HERE')
      .then((response) => response.json())
      .then((responseJson) => {
        this.setState({
          isLoading: false,
          dataSource: responseJson,
        }, function(){
        });
      })
      .catch((error) =>{
        console.error(error);
      });
  }

问题答案:

当您触发Promise时,它可能需要花费几秒钟的时间才能解决,到那时,用户可能已经导航到应用程序中的另一个位置。因此,setState在未安装的组件上执行Promise
resolves时,您会得到一个错误-就像您的情况一样。这也可能导致内存泄漏。

这就是为什么最好将某些异步逻辑移出组件。

否则,您将需要以某种方式取消Promise。另外,作为一种不得已的技术(这是一种反模式),您可以保留一个变量来检查组件是否仍处于安装状态:

componentDidMount(){
  this.mounted = true;

  this.props.fetchData().then((response) => {
    if(this.mounted) {
      this.setState({ data: response })
    }
  })
}

componentWillUnmount(){
  this.mounted = false;
}

我会再次强调-这是一种反模式,但在您的情况下可能就足够了(就像他们对Formik实现所做的一样)。

GitHub上的类似讨论

编辑:

这可能是我如何使用Hooks解决相同的问题(除了React之外什么也没有):

选项A:

import React, { useState, useEffect } from "react";

export default function Page() {
  const value = usePromise("https://something.com/api/");
  return (
    <p>{value ? value : "fetching data..."}</p>
  );
}

function usePromise(url) {
  const [value, setState] = useState(null);

  useEffect(() => {
    let isMounted = true; // track whether component is mounted

    request.get(url)
      .then(result => {
        if (isMounted) {
          setState(result);
        }
      });

    return () => {
      // clean up
      isMounted = false;
    };
  }, []); // only on "didMount"

  return value;
}

选项B: 或者,useRef其行为类似于类的静态属性,这意味着它的值更改时不会使组件重新呈现:

function usePromise2(url) {
  const isMounted = React.useRef(true)
  const [value, setState] = useState(null);


  useEffect(() => {
    return () => {
      isMounted.current = false;
    };
  }, []);

  useEffect(() => {
    request.get(url)
      .then(result => {
        if (isMounted.current) {
          setState(result);
        }
      });
  }, []);

  return value;
}

// or extract it to custom hook:
function useIsMounted() {
  const isMounted = React.useRef(true)

  useEffect(() => {
    return () => {
      isMounted.current = false;
    };
  }, []);

  return isMounted; // returning "isMounted.current" wouldn't work because we would return unmutable primitive
}

示例:https://codesandbox.io/s/86n1wq2z8



 类似资料:
  • 问题内容: 由于异步方法问题,我收到一条错误消息。在我的终端中,我看到: 我注意到这是特别指出 这是我用于该部分的代码: 我试图弄清楚如何在此异步方法中使用a 。我该怎么办? 谢谢! 问题答案: 您可以在此处使用React模式来避免内存泄漏。 在您的构造函数中: } 在你的 在你里面 基于可取消承诺模式的推荐使用 Axios的 方法。因此,您可以在卸载组件的同时取消任何网络呼叫。这是Axios取消

  • 我在java中有一个函数,在这个函数中我试图获取未读的消息。例如,如果我在broker中有偏移量为0、1、2的消息,这些消息已经被使用者读取,并且如果我关闭我的使用者一个小时。那时我产生的信息偏移量为3,4,5。之后,当我的消费者启动时,它应该从偏移量3读取消息,而不是从0读取消息。但是,它要么读取所有的消息,要么读取启动Kafka Consumer后产生的消息。我想读那些未读或未提交的消息 我尝

  • 问题内容: 如何取消代理hibernate对象,以支持多态? 考虑以下示例。A和B类是两个hibernate实体。B具有两个子类型C和D。 该代码无法执行C或D块,因为B集合已被延迟加载,并且B的所有实例均为Hibernate代理。我想要一种取消代理的方法。 注意:我意识到可以优化查询以急切地获取所有B。我正在寻找替代方案。 问题答案: 这是我们的解决方案,已添加到持久性工具中:

  • 因此,根据我对Apache Kafka中事务的理解,read_committed消费者不会返回作为正在进行的事务一部分的消息。因此,我猜想,消费者可以选择将其偏移量提交给那些正在进行的事务消息(例如,读取非事务消息),或者可以选择在提交/中止遇到的事务之前不进一步推进。我只是假设(Kafka)允许跳过那些挂起的交易记录,但考虑到它的抵消可能已经很远了,那么消费者在提交时将如何读取它们呢? 更新 考

  • 在revert可以取消指定的提交内容。使用后面要提到的rebase -i或reset也可以删除提交。但是,不能随便删除已经发布的提交,这时需要通过revert创建要否定的提交。 主要使用的场合: 安全地取消过去发布的提交

  • 不一致js是一个用于Discord的API,允许开发人员为程序Discord制作插件。这是js中API代码的链接,https://github.com/hydrabolt/discord.js/ 不和谐被设置成像一个服务器,你在那里连接和聊天的渠道,我的问题是我如何从渠道拉消息数据。 他们所做的是在JSON缓存中设置所有通道,在通道中,对象是另一个带有消息对象的缓存(留档所说的)。但是当我到达消息