React:根据 child 的状态设置 parent 的状态?

React: Set the state of a parent based on child's state?

第一次使用 React。
总之,我需要 child 更新 parent 组件的状态,尽管我已成功将回调函数传递给 child 它的行为与我预期的不同。 我有一个呈现 child 组件 LoginOverlay.

的组件应用程序

组件App写法如下:

export default class App extends React.Component{
  constructor(props) {
    super(props);

    this.handleLogin = this.handleLogin.bind(this);

    this.state = {
      userID:'',
      loginState:'waiting',
      loginError:'',
    };
  }

  handleLogin(un, pw){
    //just try setting a state as if the API call came back with an error code
    this.setState({
      loginError:'Wrong Password',
    })
  }

  render() {
      return (
      <div className="App">
        {/*login overlay*/}
        <LoginOverlay loginError={this.state.loginError} loginState={this.state.loginState} parentCallback={this.handleLogin}/>
        UserID:{this.state.userID}
      </div>
    );
  }
}

child组件写法如下:

export default class LoginOverlay extends React.Component{
  constructor(props){
    super(props);
    this.userNameChange=this.userNameChange.bind(this);
    this.passwordChange=this.passwordChange.bind(this);
    this.submitHandler=this.submitHandler.bind(this);

    this.state = {
      username:'',
      password:'',
      loginState:this.props.loginState,
      loginError:this.props.loginError,
    };
  }

  userNameChange(event) {
    this.setState({
      username: event.target.value
    });
  }

  passwordChange(event) {
    this.setState({
      password: event.target.value
    })
  }

  submitHandler(event) {
    event.preventDefault();
    if (this.state.username!=='' && this.state.password !=='') {
      this.setState({
        loginState:'loading',
        loginError:'',
      })
      this.props.parentCallback(this.state.username, this.state.password);
    }
    else {
      this.setState({
        loginError:'Fill out the form, please!'
      })
    }
  }

  render() {
      let bottompane = null;
      switch(this.state.loginState) {
        case 'waiting':
          bottompane =  <div className="login-ButtonContainer">
                          <input
                            type="submit"
                            value="Log In"
                            className="login-button"
                          />
                        </div>
          break;
        case 'loading':
          bottompane =  <div className="login-ButtonContainer">
                          {/*copypasted from loading.io*/}
                          <div className="lds-spinner"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
                        </div>
          break;
        default:
          break;
      }

      let errorText = null;
      switch(this.state.loginError) {
        case '':
        break;
        default:
          errorText=<div className="login-errortext">{this.state.loginError}</div>
        break;
      }

      return(
      <div className="loginOverlay">
        <form onSubmit={this.submitHandler} className="login-box">
          <label>
            Username:
          </label>
          <input
            className="login-field"
            type="text"
            onChange={this.userNameChange}
          />
          <br/>
          <label>
            Password:
          </label>
          <input
            className="login-field"
            type="password"
            onChange={this.passwordChange}
          />
          <br/>
            {bottompane}
            {errorText}
        </form>
      </div>
    );
  }
}

但是,在我点击提交按钮并执行 handeLogin 后,loginError 状态没有更新(我使用 console.log(this.state.loginError) 检查)。请问是不是我的方法不对?或者我的语法?

您不希望 mirror/copy 道具进入这样的状态:

// This is bad news:
this.state = {
  loginState: this.props.loginState,
  loginError: this.props.loginError,
};

相反,只需在任何您需要知道该值是什么的地方引用 this.props.loginState。这就是所谓的“托管组件”——父组件通过 props 管理状态。