在重定向之前使用ajax时,React引发错误

时间:2018-06-22 22:49:42

标签: reactjs

我遇到以下错误:

  

警告:无法在已卸载的设备上调用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' />
      )
    }

我在render方法中做错了吗?

3 个答案:

答案 0 :(得分:1)

承诺是有保证的未来,这意味着一旦调用,整个承诺链就会触发,并且您无能为力。

实际上,这意味着您需要检查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});
        }
    })
  }

答案 1 :(得分:0)

也许尝试三元声明?我知道三元语句通常是人们有条件地返回不同组件的方式。

render(){
  return(
    this.state.redirect ?
      <Redirect to='/messages' />
    :
      <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>
  )
}

答案 2 :(得分:0)

有点棘手的解决方案是:

  componentDidMount(){
    if(!this.state.redirect){
      this.getMessage()      
    }
  }

防止在挂载后发生重定向时调用getMessage。