简体   繁体   English

反应形式道具状态

[英]React form props to state

I've got a Form component that gets passed props via its parent. 我有一个Form组件,通过其父级传递道具。 I would like the form to display these props as default values in their input. 我希望表单在输入中将这些道具显示为默认值。 I would like to allow the form to be edited and on 'save' to save these new values. 我想允许编辑表单并在“保存”中保存这些新值。

I have played around with a few different solutions that I've found online - although none of them seem to allow the behaviour mentioned above. 我已经玩过一些我在网上找到的不同解决方案 - 虽然它们似乎都没有允许上面提到的行为。

Form Component - Form.js 表单组件 - Form.js

import React, { Component } from 'react';

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

    this.state = {
      pitch: this.props.booking.pitch,
      email: this.props.booking.email,
      firstName: this.props.booking.firstName,
      arrivalDate: this.props.booking.arrivalDate,
    }

    this._handleInputChange = this._handleInputChange.bind(this); 
    this._handleUpdateClose = this._handleUpdateClose.bind(this);
    this._handleUpdateBooking = this._handleUpdateBooking.bind(this);
    this._handleDelete = this._handleDelete.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    this.state = {
      pitch: this.nextProps.booking.pitch,
      email: this.nextProps.booking.email,
      firstName: this.nextProps.booking.firstName,
      arrivalDate: this.nextProps.booking.arrivalDate,
    }
  }

  _handleInputChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;
    var partialState = {};
    partialState[name] = value;
    this.setState(partialState);
  }

  _handleUpdateClose(e) {
    this.props.updateClose();
    e.preventDefault();
  }

  _handleUpdateBooking (e) {
    var tempBooking = {
      pitch: this.state.pitch,
      email: this.state.email,
      firstName: this.state.firstName,
      arrivalDate: this.state.arrivalDate,
    }
    this.props.updateBooking(tempBooking);
    e.preventDefault();
  }

  _handleDelete (e) {
    this.props.deleteBooking();
    e.preventDefault();
  }

  render() { 

    if (this.props.viewFormVisibility === true) {
      var viewFormState = {"display": "block"};  
    } else {
      var viewFormState = {"display": "none"};
    }

    return (
      <div>
        <form style={viewFormState}>
          <h4>View Booking</h4>
          <div className="form-group row">
            <label className="col-2 col-form-label">Pitch</label>
            <div className="col-10">
              <input value={this.props.booking.pitch} onChange={this._handleInputChange} className="form-control" name="pitch" ref="inputPitch" type="number" id="example-number-input"/>
            </div>
          </div>
          <div className="form-group row">
            <label  className="col-2 col-form-label">First Name</label>
            <div className="col-10">
              <input value={this.props.booking.firstName} onChange={this._handleInputChange} className="form-control" ref="firstName" name="firstName" type="text" id="example-text-input"/>
            </div>
          </div>
          <div className="form-group row">
            <label className="col-2 col-form-label">Email</label>
            <div className="col-10">
              <input value={this.props.booking.email} onChange={this._handleInputChange} className="form-control" ref="inputEmail" type="email"  name="email" id="example-email-input"/>
            </div>
          </div>

          <div className="form-group row">
            <label className="col-2 col-form-label">Date</label>
            <div className="col-10">
              <input value={this.props.booking.arrivalDate} onChange={this._handleInputChange} className="form-control" ref="arrivalDate" name="arrivalDate" type="date" id="example-date-input"/>
            </div>
          </div>
          <button type="submit" className="btn btn-primary" onClick={this._handleUpdateBooking}>Save changes</button>
          <button className="btn btn-danger" onClick={this._handleUpdateClose}>Close</button>
          <button onClick={this._handleDelete} className="btn btn-danger">Delete</button>
        </form>
      </div>
    )
  }
}

export default ViewBooking;

You can do something like this: 你可以这样做:

class FormParent extends Component {
  constructor (props) {
    super(props)
    this.state = {
      name: ''
    }
    this.handleInputChange = this.handleInputChange.bind(this)
  }
  handleInputChange (e) {
    const { name, value } = e.target
    this.setState({
      [name]: value
    })
  }
  render () {
    const { name } = this.state
    return <Form name={name} handleInputChange={this.handleInputChange} />
  }
}

If you are passing the input values by props is not necessary to save them in a state, you can set them directly to the input. 如果要通过props传递输入值不需要将它们保存在某个状态,则可以将它们直接设置为输入。

Then to change the input values you need to have a method in your parent receiving the new date, in this case handleInputChange . 然后要更改输入值,您需要在父级中接收新日期的方法,在本例中为handleInputChange

class Form extends Component {
  render () {
    return (
      <form>
        <input
          name='name'
          value={this.props.name}
          onChange={this.props.handleInputChange}
        />
      </form>
    )
  }
}

Note: The input names should be the same as the keys in your parent state. 注意:输入名称应与父状态中的键相同。

What you have done in the componentWillReceiveProps() is incorrect. 您在componentWillReceiveProps()所做的不正确。 You should not directly modify the state (unless it is the constructor). 您不应该直接修改状态 (除非它是构造函数)。 State updates must always happen through this.setState() method as shown below. 状态更新必须始终通过this.setState()方法进行,如下所示。

componentWillReceiveProps(nextProps) {
    this.setState({
      pitch: nextProps.booking.pitch,
      email: nextProps.booking.email,
      firstName: nextProps.booking.firstName,
      arrivalDate: nextProps.booking.arrivalDate,
    });
 }

Apart from that, the rest of the code seems correct. 除此之外,其余的代码似乎是正确的。

There are many mistakes in your code. 您的代码中存在许多错误。 I have fixed them and below is the working code. 我已修复它们,下面是工作代码。

class ViewBooking extends Component {
  constructor(props) {
    super(props)

    this.state = {
      pitch: props.booking.pitch,
      email: props.booking.email,
      firstName: props.booking.firstName,
      arrivalDate: props.booking.arrivalDate
    }

    this._handleInputChange = this._handleInputChange.bind(this)
    this._handleUpdateClose = this._handleUpdateClose.bind(this)
    this._handleUpdateBooking = this._handleUpdateBooking.bind(this)
    this._handleDelete = this._handleDelete.bind(this)
  }

  componentWillReceiveProps(nextProps) {
    this.state = {
      pitch: nextProps.booking.pitch,
      email: nextProps.booking.email,
      firstName: nextProps.booking.firstName,
      arrivalDate: nextProps.booking.arrivalDate
    }
  }

  _handleInputChange(event) {
    const target = event.target
    const value = target.type === 'checkbox' ? target.checked : target.value
    const name = target.name
    var partialState = {}
    partialState[name] = value
    this.setState(partialState)
  }

  _handleUpdateClose(e) {
    this.props.updateClose()
    e.preventDefault()
  }

  _handleUpdateBooking(e) {
    var tempBooking = {
      pitch: this.state.pitch,
      email: this.state.email,
      firstName: this.state.firstName,
      arrivalDate: this.state.arrivalDate
    }
    this.props.updateBooking(tempBooking)
    e.preventDefault()
  }

  _handleDelete(e) {
    this.props.deleteBooking()
    e.preventDefault()
  }

  render() {
    if (this.props.viewFormVisibility === true) {
      var viewFormState = { 'display': 'block' }
    } else {
      var viewFormState = { 'display': 'none' }
    }

    return (
      <div>
        fdsfdsfdf
        <form style={viewFormState}>
          <h4>View Booking</h4>
          <div className='form-group row'>
            <label className='col-2 col-form-label'>Pitch</label>
            <div className='col-10'>
              <input value={this.state.pitch} onChange={this._handleInputChange} className='form-control' name='pitch' ref='inputPitch' type='number' id='example-number-input' />
            </div>
          </div>
          <div className='form-group row'>
            <label className='col-2 col-form-label'>First Name</label>
            <div className='col-10'>
              <input value={this.state.firstName} onChange={this._handleInputChange} className='form-control' ref='firstName' name='firstName' type='text' id='example-text-input' />
            </div>
          </div>
          <div className='form-group row'>
            <label className='col-2 col-form-label'>Email</label>
            <div className='col-10'>
              <input value={this.state.email} onChange={this._handleInputChange} className='form-control' ref='inputEmail' type='email' name='email' id='example-email-input' />
            </div>
          </div>

          <div className='form-group row'>
            <label className='col-2 col-form-label'>Date</label>
            <div className='col-10'>
              <input value={this.state.arrivalDate} onChange={this._handleInputChange} className='form-control' ref='arrivalDate' name='arrivalDate' type='date' id='example-date-input' />
            </div>
          </div>
          <button type='submit' className='btn btn-primary' onClick={this._handleUpdateBooking}>Save changes</button>
          <button className='btn btn-danger' onClick={this._handleUpdateClose}>Close</button>
          <button onClick={this._handleDelete} className='btn btn-danger'>Delete</button>
        </form>
      </div>
    )
  }
}

Here is a demo of a text input using props from it's parent. 这是一个使用来自其父级的道具的文本输入的演示。

https://codepen.io/seanwasere/pen/KBWNaL?editors=0010 https://codepen.io/seanwasere/pen/KBWNaL?editors=0010

class Form extends React.Component {
  constructor () {
    super()
    this.state = {
      data: ''
    }
    this.handleChange = this.handleChange.bind(this)
  }
  handleChange (e) {
    const newData = e.target.value
    this.setState({
      data: newData
    })
  }
  render () {
    const { data } = this.state
    return (
      <div>
        <form>
          <label>
            Type something:
            <TextInput value={data} handleInputChange={this.handleChange} />
          </label>
          <div>
            You typed : {data}
          </div>
        </form>
        </div>
      )
   }
}

class TextInput extends React.Component {
  render () {
    return (      
        <input
          value={this.props.data}
          onChange={this.props.handleInputChange}
        />      
    )
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM