创建对象并将其传递给父组件的最佳做法是什么?

时间:2017-10-12 05:38:26

标签: reactjs

创建对象并将其传递给父组件的最佳做法是什么?我的下面的代码运行良好,但似乎我必须在这里投入太多东西只是为了提交一个包含2个字段的简单表单。

我正在创建构造函数,

听取事件,

绑定事件,

更新并将状态传递给App.js

这是最佳做法吗?:

class AddFishForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      title: '',
      amount: ''
    };
    this.onTitleChange = this.onTitleChange.bind(this);
    this.onAmountChange = this.onAmountChange.bind(this);
  }
  onTitleChange = (e) => {
    const title = e.target.value;
    this.setState(() => ({ title }));
  };
  onAmountChange = (e) => {
    const amount = e.target.value;
    this.setState(() => ({ amount }));
  };

  createFish(event) {
    event.preventDefault();
    this.props.addFish({
      url: this.state.url,
      title: this.state.title
    });
  }
  render () {
    return (
      <Segment>
        <Form onSubmit={(e) => this.createFish(e)}>
          <Form.Group >
            <Form.Input
              type='text'
              placeholder='picture url'
              autoFocus
              value={this.state.title}
              onChange={this.onTitleChange}
              width={6}
            />
            <Form.Input
              type='text'
              placeholder='title'
              autoFocus
              value={this.state.amount}
              onChange={this.onAmountChange}
              width={6}
            />
          </Form.Group >
          <Button fluid type='submit'>Submit</Button>
        </Form>
      </Segment>
    )
  }
}

3 个答案:

答案 0 :(得分:1)

您可以通过提供更新状态的更通用方法来简化代码:

onInputChange = (e) => {
  const target = e.target;
  const name = target.name;
  const value = target.type === 'checkbox' ? target.checked : target.value;
  // add code for other input types
  this.setState(() => ({ [name]: value }));
};

在构造函数中绑定此方法

this.onInputChange = this.onInputChange.bind(this);

并在你的元素上使用它

<input
  type='text'
  name='title'
  value={this.state.title}
  onChange={this.onInputChange}
  ...
/>

<input
  type='checkbox'
  name='is_subsribed'
  checked={this.state.is_subsribed}
  onChange={this.onInputChange}
  ...
/>

name属性将输入连接到正确的状态值

答案 1 :(得分:0)

如果您不需要对input进行进一步操作,请使用uncontrolled components。这是代码的非受控组件版本

class AddFishForm extends React.Component {
  constructor(props) {
    super(props);
  }

  createFish(event) {
    event.preventDefault();
    const url = this._url.value;
    const title = this._title.value;
    this.props.addFish({ url, title });
  }
  render () {
    return (
      <Segment>
        <Form onSubmit={(e) => this.createFish(e)}>
          <Form.Group >            
            <input
              ref={input => this._url = input}
              type='text'
              width={6} />
            <input
              ref={input => this._title = input}
              type='text
              width={6} />
          </Form.Group >
          <Button fluid type='submit'>Submit</Button>
        </Form>
      </Segment>
    )
  }
}

答案 2 :(得分:0)

最佳实践将从这样的事情开始:

class AddFishForm extends React.Component {
  onInputChange() {

  }

  render() {
    return (
      <div className="semantic ui segment">
        <form className="ui form">
          <div className="field">
            <label>Image Search</label>
            <input type="text" onChange={this.onInputChange} />
          </div>
        </form>
      </div>
    );
  }
}

export default AddFishForm;

运行onInputChange()时会自动传递一个参数,通常称为event对象。该对象包含一堆有关刚刚发生的事件的信息,如下所示:

class AddFishForm extends React.Component {
  onInputChange(event) {

  }

  render() {
    return (
      <div className="semantic ui segment">
        <form className="ui form">
          <div className="field">
            <label>Image Search</label>
            <input type="text" onChange={this.onInputChange} />
          </div>
        </form>
      </div>
    );
  }
}

export default AddFishForm;

在用户键入内容的情况下,我们关心的整个对象中通常有一个属性,即event.target.value属性。它将包含用户刚刚尝试在输入中键入的文本,如下所示:

class AddFishForm extends React.Component {
  onInputChange(event) {
   event.target.value
  }

  render() {
    return (
      <div className="semantic ui segment">
        <form className="ui form">
          <div className="field">
            <label>Image Search</label>
            <input type="text" onChange={this.onInputChange} />
          </div>
        </form>
      </div>
    );
  }
}

export default AddFishForm;

您可以通过控制台注销并查看您的状态来进行测试:

class AddFishForm extends React.Component {
  onInputChange(event) {
   console.log(event.target.value);
  }

  render() {
    return (
      <div className="semantic ui segment">
        <form className="ui form">
          <div className="field">
            <label>Image Search</label>
            <input type="text" onChange={this.onInputChange} />
          </div>
        </form>
      </div>
    );
  }
}

export default AddFishForm;

添加文本时,应该将其调出,这应该是预期的行为。

onChange是一个非常特殊的属性名称。不同的事件将被关联到不同的属性名称。因此,在这种情况下,您似乎希望在用户更改文本输入的任何时间都被告知,因此我假设这就是您使用属性名称onChange的原因。

对于事件处理程序,您在命名约定中使用社区约定,因此您在这里很好。

所以这就是事件处理的总括。还有写出事件处理程序的另一种语法。

class AddFishForm extends React.Component {
  onInputChange(event) {
   console.log(event.target.value);
  }

  render() {
    return (
      <div className="semantic ui segment">
        <form className="ui form">
          <div className="field">
            <label>Image Search</label>
            <input type="text" onChange={(event) => console.log(event.target.value)} />
          </div>
        </form>
      </div>
    );
  }
}

export default AddFishForm;

当事件处理程序方法中的逻辑行不多时,这种方法非常有用。

现在,在我在render()方法内提供的示例中,我有一个不受控制的表单元素。通常,作为开发人员,我们希望使用受控表单元素。因此,我将对其进行重构,以便您可以看到不同之处。

之所以提出这一点,是因为我看到在您的事件处理程序中您实现了this.setState(() => ({ title }));,但是您想更加仔细地考虑实现,如果您的想法是拥有一个受控的表单元素,那么您希望实现该实现像这样:

class AddFishForm extends React.Component {
    state = {
      title: '',
      amount: ''
    };
  }

  createFish(event) {
    event.preventDefault();
    this.props.addFish({
      url: this.state.url,
      title: this.state.title
    });
  }
  render () {
    return (
      <Segment>
        <Form onSubmit={(e) => this.createFish(e)}>
          <Form.Group >
            <Form.Input
              type='text'
              placeholder='picture url'
              autoFocus
              value={this.state.title}
              onChange={(e) => this.setState({ title: e.target.value })}
              width={6}
            />
            <Form.Input
              type='text'
              placeholder='title'
              autoFocus
              value={this.state.amount}
              onChange={(e) => this.setState({ amount: e.target.value })}
              width={6}
            />
          </Form.Group >
          <Button fluid type='submit'>Submit</Button>
        </Form>
      </Segment>
    )
  }
}

因此,您将使用输入的当前值来更新titleamount属性。

那我们为什么要使用state?为什么每次更改输入时都用setState()更新状态,为什么还要传递一个称为value的东西?

  1. 输入的用户类型
  2. 调用回调,onChange
  3. 在回调中,我们称为setState(),它将状态更新为新的value。因此this.state.title将包含用户输入的内容。
  4. 组件将重新呈现自己。
  5. 我们采用this.state.title并将其分配给输入的value道具,它将覆盖输入中已经存在的所有文本。

可以通过给该值一个名为乱码的字符串来证明这一点:

class SearchBar extends React.Component {
  state = { term: '' };

  render() {
    return (
      <div className="semantic ui segment">
        <form className="ui form">
          <div className="field">
            <label>Image Search</label>
            <input type="text" value="gibberish" onChange={(e) => this.setState({ term: e.target.value })} />
          </div>
        </form>
      </div>
    );
  }
}

当您在浏览器中转到表单时,您将看到乱码已经填充在那里。

因此,上面概述的五个步骤是受控元素的流程。