簡體   English   中英

setState只能更新已安裝或安裝的組件

[英]setState Can only update a mounted or mounting component

我有一個登錄組件,當用戶提交登錄表單時,我收到錯誤

警告:setState(...):只能更新已安裝或安裝的組件。 這通常意味着您在已卸載的組件上調用了setState()。

我甚至無法找到這個錯誤的位置

class LoginForm extends React.Component {
  state = {
    identifier: '',
    password: '',
    errors: {},
    isLoading: false
  };

  static contextTypes = {
    router: PropTypes.object.isRequired
  };

  isValid = () => {
    const { errors, isValid } = validateInput(this.state);
    if (!isValid) {
      this.setState({ errors });
    }
    return isValid;
  };

  onSubmit = (e) => {
    e.preventDefault();
    if (this.isValid()) {
      this.setState({ errors: {}, isLoading: true });
      const loginDetails = Object.assign({}, {identifier: this.state.identifier, password: this.state.password});
      this.props.login(loginDetails).then(res => {
        console.log('res', res);
        return this.context.router.push('/');
      }).catch(error => {
        return this.setState(Object.assign({}, this.state, error, {isLoading: false}));
      });
    }
  };

  onChange = (e) => {
    this.setState({ [e.target.name]: e.target.value });
  };

  render() {
    const { errors, identifier, password, isLoading } = this.state;
    return (
      <form onSubmit={this.onSubmit}>
        <fieldset>
          <legend>Login</legend>
          { errors.form && <div className="alert alert-danger">{errors.form}</div> }
          <TextFieldGroup
            name="identifier"
            label="Username / Email"
            value={identifier}
            error={errors.identifier}
            onChange={this.onChange}
          />
          <TextFieldGroup
            name="password"
            label="Password"
            value={password}
            error={errors.password}
            onChange={this.onChange}
            type="password"
          />
          <div className="form-group">
            <button className="btn btn-primary btn-lg" disabled={isLoading}>Login</button>
          </div>
        </fieldset>
      </form>
    );
  }
}

export default connect(null, { login })(LoginForm);

錯誤究竟在哪里?

您正在使用該承諾調用運行此異步代碼:

onSubmit = (e) => {
    e.preventDefault();
    if (this.isValid()) {
      this.setState({ errors: {}, isLoading: true });
      const loginDetails = Object.assign({}, {identifier: this.state.identifier, password: this.state.password});
      this.props.login(loginDetails).then(res => {
        console.log('res', res);
        return this.context.router.push('/');
      }).catch(error => {
        return this.setState(Object.assign({}, this.state, error, {isLoading: false}));
      });
    }
  };

所以每當promise失敗時,它都會調用setState 即使您的組件不再安裝,此代碼也會運行。

這里有一些文檔和建議來克服承諾問題https://facebook.github.io/react/blog/2015/12/16/ismounted-antipattern.html

這個庫似乎用裝飾器包裝了promises - 我並不是建議你使用它,它只是一種理解正在發生的事情的好方法。

順便說一句,這是使用redux的一個很好的理由。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM