Реагировать: Установить состояние родителя на основе состояния ребенка? - PullRequest
2 голосов
/ 05 июня 2019

Первая работа с React.
Таким образом, мне нужно, чтобы дочерний элемент обновил состояние родительского компонента, хотя я успешно передал функцию обратного вызова дочернему элементу, она не ведет себя так, как я ожидаю. У меня есть компонент App, который отображает дочерний компонент LoginOverlay.

Компонент приложения записывается следующим образом:

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>
    );
  }
}

Дочерний компонент записывается следующим образом:

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)). Интересно, это мой подход не так? Или мой синтаксис?

1 Ответ

0 голосов
/ 05 июня 2019

Вы не хотите зеркалировать / копировать реквизиты в такое состояние, как это:

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

Вместо этого просто указывайте this.props.loginState везде, где вам нужно знать, что это за значение.Это то, что называется «управляемый компонент» - родительский компонент управляет состоянием через реквизит.

...