React Native,“setState()在未安装的组件上”警告

时间:2015-11-19 21:21:29

标签: reactjs react-native

我有一段可以触发警告的代码(代码应该登录到REST并关闭Activity Indicator)。我不明白我的组件是如何卸载的,因为我在按钮点击上绑定了onLoginPressed,之后所有可能的安装都应该已经完成​​。请帮助我摆脱它,并了解警告的原因...
UPD:感谢评论,我发现组件已卸载,并且调用了componentWillUnmount ......但我不明白为什么以及何时发生......

  

“警告:setState(...):只能更新已安装或已安装   零件。这通常意味着您在已卸载时调用了setState()   零件。这是一个无操作。请检查未定义的代码   部件“。

以下是我的代码,警告由第二个setState触发:

onLoginPressed(){
    console.log('Attempted to login with: '+this.state.username);
    this.setState({showProgress: true});

    AuthService.login({
      login: this.state.username,
      password: this.state.password
    }, (results)=> {
      this.setState(Object.assign({ // have to create a solid Object with all states to be changed at once
        showProgress: false // turning off ActivityIndicator
      }, results));

      if(results.success && this.props.onLogin){
        this.props.onLogin(); // Yey! We logged in! Let's move to the next View
      }
    });
  }

... AuthService.js:

login (creds, callback) {
    fetch(CFG.AUTH_URL)
      .then((response)=> {
        if((response.status >= 200) && (response.status < 300)){
          return response.json();
        }
        throw {
          serverError: (response.status == 500) || (response.status == 501),
          unknownError: (response.status != 500) || (response.status != 501)
        };
      })
      .then((result)=> {
          AsyncStorage.multiSet([ // Have to save login+password and session_hash for later use...
            [authKey, JSON.stringify(creds)],
            [sessionKey, result.data.session_hash]
          ], (err)=> {
            if (err) throw err;
          });
          return callback({success: true});
      }
      })
      .catch((err)=> {
        return callback(err);
      });
  }// end of login

1 个答案:

答案 0 :(得分:4)

ФедорУсаков,我也遇到了这个问题。我发现由于在AuthService.login()的回调函数中设置状态,组件正在重新渲染。问题(在这种情况下)与setState

  

无法保证对setState的调用同步操作   并且可以批量调用以获得性能提升。

来自React docs的

我的猜测是没有立即设置状态,然后调用this.props.onLogin()。这可以在设置状态之前取消组件,瞧,警告

为了让我的工作,我删除了条件和onLogin()的调用,并向shouldComponentUpdate()类添加了Login方法。在shouldComponentUpdate()我放置了删除的条件和调用。像这样:

onLoginButtonPress() {
    // some code

    AuthService.login({
        username: this.state.username,
        password: this.state.password
    }, (results) => {
        this.setState({
            ...results,
            showProgress: false
        });
    });
}

shouldComponentUpdate() {
    if (this.state.loginSuccess && this.props.onLogin) {
        this.props.onLogin();
    }
    return true;
}

这确保了状态已设置,然后组件重新呈现,并且因为this.state.loginSuccess现在为真,请调用this.props.onLogin(),这会导致Login卸载。