首页 > 解决方案 > React 在重定向之前使用 ajax 时抛出错误

问题描述

我收到以下错误:

警告:无法在未安装的组件上调用 setState(或 forceUpdate)。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消 componentWillUnmount 方法中的所有订阅和异步任务。在 ViewMessage 中(由 Route 创建)

这是有问题的组件,如您所见,没有 componentWillUnmount:

class ViewMessage extends React.Component{
  state={
    message: {},
    messageId: '',
    redirect: false,
    reply: false
  }

  static getDerivedStateFromProps(props, state){
    if(props.location.state){
      return { messageId: props.location.state.id };
    }else{
      return { redirect: true}
    }
  }

  componentDidMount(){
    this.getMessage()
  }

  getMessage = () => {
    this.setState({_loading: true});
    axios({
      method: 'get',
      url: 'http://localhost:8080/getMessage',
      params: {
        id: this.state.messageId
      },
      withCredentials: true
    }).then((result) => {
      this.setState({message: result.data[0], _loading: false});
    })
  }

  handleReply = () => {
    if(this.state.reply){
      this.setState({reply: false});
    }else{
      this.setState({reply: true});
    }
  }


  render(){

    if(this.state.redirect){
      return(
        <Redirect to='/messages' />
      )
    }

    return(
      <Container>
        {this.state.loading ? <Loader active /> : <div></div>}
        <div style={{float: 'right'}}>
          {this.state.message.date}
        </div>
          From: {this.state.message.senderName}
        <Divider />
          Subject: {this.state.message.subject}
        <Divider />
          {this.state.message.text}
        <Divider />
        <Button icon='reply' onClick={this.handleReply}/>
        {this.state.reply ? <Composer recipient={this.state.message.senderName}/> : <div></div>}

      </Container>

    )
  }
}

export default ViewMessage;

当我添加以下行时发生错误,当我删除它时消失:

    if(this.state.redirect){
      return(
        <Redirect to='/messages' />
      )
    }

我在渲染方法中做错了吗?

标签: reactjs

解决方案


Promise 是一个有保证的未来,这意味着整个 Promise 链一旦被调用就会触发,你几乎无法阻止它。

this在实际层面上,这意味着您需要在尝试访问 setState 之前检查以确保您的上下文仍然存在,因为组件可能在此承诺链完成之前已卸载。

getMessage = () => {
    this.setState({_loading: true});
    axios({
      method: 'get',
      url: 'http://localhost:8080/getMessage',
      params: {
        id: this.state.messageId
      },
      withCredentials: true
    }).then((result) => {
        if (this) { // be sure the instance still exists!
          this.setState({message: result.data[0], _loading: false});
        }
    })
  }

推荐阅读