【问题标题】:React: 2 way binding propsReact:2 路绑定道具
【发布时间】:2020-09-19 15:14:39
【问题描述】:

如何对父组件 (Form.js) 中的变量进行 2 路绑定,以便子组件 (InputText.js) 中发生的更改将在父组件中更新?

预期结果:在InputText.js 中的input 中键入值将更新Form.js 的状态

在 Form.js 中

render() {
    return (
      <div>
        <InputText
          title="Email"
          data={this.state.formInputs.email}
        />

        <div>
          Value: {this.state.formInputs.email} // <-- this no change
        </div>

      </div>
    )
  }

在 InputText.js 中

export default class InputText extends React.Component {

  constructor(props) {
    super(props);
    this.state = props;
    this.handleKeyChange = this.keyUpHandler.bind(this);
  }

  keyUpHandler(e) {
    this.setState({
      data: e.target.value
    });
  }

  render() {
    return (
      <div>
        <label className="label">{this.state.title}</label>
        <input type="text" value={this.state.data} onChange={this.handleKeyChange} /> // <-- type something here
        value: ({this.state.data}) // <-- this changed
      </div>
    )
  }
}

【问题讨论】:

标签: javascript reactjs


【解决方案1】:

您可以简单地将一个回调从 Form.js 传递给 InputText,然后在 InputText 中的 handleKeyChange 上调用该回调

【讨论】:

    【解决方案2】:

    您需要将状态提升到父级

    父类看起来像

    onChangeHandler(e) {
       this.setState({
          inputValue: e.target.value // you receive the value from the child to the parent here
       })
    }
    render() {
        return (
          <div>
            <InputText
              title="Email"
              onChange={this.onChangeHandler}
              value={this.state.inputValue}
            />
    
            <div>
              Value: {this.state.inputValue}
            </div>
    
          </div>
        )
      }
    

    子类看起来像

    export default class InputText extends React.Component {
    
      constructor(props) {
        super(props);
        this.state = props;
      }
    
      render() {
        return (
          <div>
            <label className="label">{this.state.title}</label>
            <input type="text" value={this.state.value} onChange={this.props.onChange} />
            value: ({this.state.value})
          </div>
        )
      }
    }
    

    【讨论】:

      【解决方案3】:

      您可以在父组件本身中管理状态,而不是像这样在子组件上管理状态 (lifting state up):

      在 Form.js 中

      constructor(props) {
        super(props);
        this.handleKeyChange = this.keyUpHandler.bind(this);
      }
      
      
      keyUpHandler(e) {
        const { formInputs } = this.state;
        formInputs.email = e.target.value
        this.setState({
          formInputs: formInputs
        });
      }
      
      render() {
          // destructuring
          const { email } = this.state.formInputs;
          return (
            <div>
              <InputText
                title="Email"
                data={email}
                changed={this.handleKeyChange}
              />
      
              <div>
                Value: {email}
              </div>
      
            </div>
          )
        }
      

      在 InputText.js 中

      export default class InputText extends React.Component {
        render() {
          // destructuring
          const { title, data, changed } = this.props;
          return (
            <div>
              <label className="label">{title}</label>
              <input type="text" value={data} onChange={changed} />
              value: ({data})
            </div>
          )
        }
      }
      

      您还可以使 InputText.js 成为功能组件,而不是基于类的组件,因为它现在是无状态的。

      更新:(如何重用处理程序方法)

      您可以向函数添加另一个参数,该参数将返回属性名称,如下所示:

      keyUpHandler(e, attribute) {
        const { formInputs } = this.state;
        formInputs[attribute] = e.target.value
        this.setState({
          formInputs: formInputs
        });
      }
      

      您可以这样发送:

      <input type="text" value={data} onChange={ (event) => changed(event, 'email') } />
      

      这假设您对每个表单输入都有不同的输入,否则您可以将该属性名称也从 props 中的父级传递给子级并相应地使用它。

      【讨论】:

      • 非常感谢。有没有办法让this.handleKeyChange = this.keyUpHandler.bind(this);keyUpHandler 函数也可用于其他表单输入?
      • @Jingles 我已经更新了答案以使函数可重用。
      猜你喜欢
      • 2017-04-14
      • 2021-10-28
      • 1970-01-01
      • 1970-01-01
      • 2013-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-08
      相关资源
      最近更新 更多