Is there a more DRY approach for creating React te

2019-07-15 02:32发布

问题:

In React and React Native the accepted practice to include <input> form fields is to include an onChange handler that updates the state on every keystroke. e.g. :

<input type="text" value={this.state.valueField1} onChange={this.handleChangeField1} />

The state is updated in order to prevent the value from being restored to the original value while the user is typing.

This leads to a lot of repeated code, thus violating the old DRY (Do not repeat your self) principle. e.g. (based in the React Docs):

  handleChangeField1(event) {
    this.setState({valueField1: event.target.value});
  }

  handleChangeField2(event) {
    this.setState({valueField2: event.target.value});
  }

The problem here is having to repeat the field name "Field1" 3 times instead of one (just for the declaration) and forcing the creation of an onChange logic that can easily (and by mistake), alter the standardized expected behavior of the UI components for the APP users.

The question: Is there a less verbose, less repeating and less risky way to include <input> fields in ReactJS/React-Native apps?

When I talk about preserving the component´s native behavior, I´m mainly thinking about not changing the value while the user is typing.

As a reference, in simple HTML/VanillaJS example we would just add the <input value="{ServerSideValue}" name="field1"> once and then get the value from field1 wherever we need it, thus preserving the native component behavior and without repeating the field1 more than once in the declaration.

回答1:

This is a pattern that we use a lot. I'm pretty sure it answers your question:

class MyForm extends React.Component {
  state = {
    firstName: '',
    lastName: ''
  };

  handleChange = e => {
    this.setState({
      [e.target.name]: e.target.value
    });
  };

  render() {
    return (
      <div>
        <input
          name="firstName"
          onChange={this.handleChange}
          placeholder="Enter your first name"
          value={this.state.firstName}
        />
        <input
          name="lastName"
          onChange={this.handleChange}
          placeholder="Enter your last name"
          value={this.state.lastName}
        />
      </div>
    );
  }
}

I made an example for you:

Edit: As for your concern with the native behavior, you don't need to worry about changing the value with an onChange. onChange is an event callback so that we can react to that event.

There is concern with controlled vs uncontrolled inputs, and they recommend controlling them. That's why I'm supplying the value back to the inputs.

Let me know how that goes or if you've got any questions.