在未挂载的组件上调用 setState [英] Calling setState on an unmounted component

查看:58
本文介绍了在未挂载的组件上调用 setState的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的很多组件中,我需要做这样的事情:

In a lot of my components I need to do something like this:

handleSubmit() {
  this.setState({loading: true})
  someAsyncFunc()
    .then(() => {
      return this.props.onSuccess()
    })
    .finally(() => this.setState({loading: false}))
}

onSuccess 函数

  • 可能是也可能不是承诺(如果是,loading 应该保持真实,直到它被解决)
  • 可能会也可能不会卸载组件(它可能会关闭该组件所在的模式,甚至导航到不同的页面)
  • may or may not be a promise (if it is, loading should stay true until it is resolved)
  • may or may not unmount the component (it may close the modal this component is in or even navigate to different page)

如果函数卸载组件,this.setState({loading: false}) 显然会触发警告 Can't call setState (or forceUpdate) on an unmounted component.代码>

If the function unmounts the component, this.setState({loading: false}) obviously triggers a warning Can't call setState (or forceUpdate) on an unmounted component.

我的两个问题:

  1. 有没有一种简单的方法可以避免这个问题?我不想在 componentDidMountcomponentWillUnmount 中设置一些 _isMounted 变量,然后在我的大多数组件中需要时检查它,另外我可能下次写这样的东西时忘记这样做了......
  2. 真的有问题吗?我知道,根据警告,它表示我的应用程序中存在内存泄漏,但在这种情况下它不是内存泄漏,是吗?也许忽略警告就可以了......
  1. Is there a simple way to avoid the issue ? I don't want to set some _isMounted variable in componentDidMount and componentWillUnmount and then check it when needed in most of my components, plus I may forget to do it next time writing something like this ...
  2. Is it really a problem ? I know that, according to the warning, it indicates a memory leak in my application, but it is not a memory leak in this case, is it ? Maybe ignoring the warning would be ok ...

对我来说,第二个问题比第一个问题更重要一点.如果这确实是一个问题并且我无法在未安装的组件上调用 setState,我可能会自己找到一些解决方法.但我很好奇我是否不能忽略它.

The second question is a little bit more important for me than the first. If this really is a problem and I just can't call setState on unmounted component, I'd probably find some workaround myself. But I am curious if I can't just ignore it.

问题的实例:

const someAsyncFunc = () => new Promise(resolve => {
  setTimeout(() => {
  	console.log("someAsyncFunc resolving");
    resolve("done");
  }, 2000);
});

class Example extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = {loading: false};
  }
  
  componentDidMount() {
    setTimeout(() => this.handleSubmit(), 100);
  }
  
  handleSubmit() {
    this.setState({loading: true})
    someAsyncFunc()
      /*
      .then(() => {
        return this.props.onSuccess()
      })
      */
      .finally(() => this.setState({loading: false}))
  }
  
  render() {
    return <div>{String(this.state.loading)}</div>;
  }
}

class Wrapper extends React.Component {
	constructor(props, ...rest) {
  	super(props, ...rest);
    this.state = {
    	children: props.children
    };
  }
	componentDidMount() {
  	setTimeout(() => {
    	console.log("removing");
    	this.setState({children: []});
    }, 1500)
  }
	render() {
  	return <div>{this.state.children}</div>;
  }
}

ReactDOM.render(
	<Wrapper>
    <Example />
	</Wrapper>,
  document.getElementById("root")
);

.as-console-wrapper {
  max-height: 100% !important;
}

<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>

推荐答案

class myClass extends Component {
  _isMounted = false;

  constructor(props) {
    super(props);

    this.state = {
      data: [],
    };
  }

  componentDidMount() {
    this._isMounted = true;
    this._getData();
  }

  componentWillUnmount() {
    this._isMounted = false;
  }

  _getData() {
    axios.get('example.com').then(data => {
      if (this._isMounted) {
        this.setState({ data })
      }
    });
  }


  render() {
    ...
  }
}

这篇关于在未挂载的组件上调用 setState的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆