当子组件作为属性传递时,反应状态不会更新/传递给子组件

时间:2019-02-13 00:04:49

标签: javascript reactjs state

我正在尝试创建动态表单,因此我将一些jsx元素作为属性传递给子组件。即使状态正在更新,更新后的状态也不会传递给元素。下面是代码:

这是子组件,用于映射传递的控件并将其输出。

class Form extends Component {
  render() {
    return (
      <div>
        {this.props.controls.map((c, i) => {
          return <React.Fragment key={i}>{c}</React.Fragment>;
        })}
      </div>
    );
  }
}

这是调用子组件的应用程序:

class App extends Component {
  constructor(props) {
    super(props);

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

    this.controls = [
      <input
        type="text"
        onChange={this.onChangeUsername}
        value={this.state.username}
      />
    ];
  }

  componentDidUpdate() {
    console.log(this.state);
  }

  render() {
    return (
      <div className="App">
        <div className="app__group">
          <h1>This is not working</h1>
          <Form controls={this.controls} />
        </div>
        <div className="app__group">
          <h1>This is working</h1>
          <input
            type="text"
            onChange={this.onChangePassword}
            value={this.state.password}
          />
        </div>
      </div>
    );
  }

  onChangeUsername = e => {
    console.log('onChangeUsername', e.target.value);
    this.setState({ username: e.target.value });
  };

  onChangePassword = e => {
    console.log('onChangePassword');
    this.setState({ password: e.target.value });
  };
}

作为意外行为的示例,当输入作为属性传递给子组件时,我无法键入输入。状态会更新,但不会传递给孩子,因此文本不会显示。

另一方面,标准输入元素可以工作,我可以键入并查看输出。

我在做什么错了?

1 个答案:

答案 0 :(得分:2)

问题是您正在尝试使“固定”的东西变成动态的东西。让我们采用一种更实用的方法,它将刷新每个输入,例如它们是动态的。

class App extends Component {
  constructor(props) {
    super(props);

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

  componentDidUpdate() {
    console.log(this.state);
  }

  render() {
    return (
      <div className="App">
        <div className="app__group">
          <h1>This is not working</h1>
          <Form controls={this.controls()} />
        </div>
      </div>
    );
  }

  controls = () => {
    return [<input
            type="text"
            onChange={this.onChangeUsername}
            value={this.state.username}
           />]
  }

  onChangeUsername = e => {
    console.log('onChangeUsername', e.target.value);
    this.setState({ username: e.target.value });
  };

  onChangePassword = e => {
    console.log('onChangePassword');
    this.setState({ password: e.target.value });
  };
}