DaLim
DaLim

Reputation: 19

React Form Elements

Why should I always set a React Input Component's value manually? In my Example I can delete value={this.state.email} and value={this.state.password} and the code is valid and it works. But I see in the React Docs and in all of their examples you should set the value every render. Why is that?

function validate(email, password) {
  // true means invalid, so our conditions got reversed
  return {
    email: email.length === 0,
    password: password.length === 0,
  };
}

class SignUpForm extends React.Component {
  constructor() {
    super();
    this.state = {
      email: '',
      password: '',

      everFocusedEmail: false,
      everFocusedPassword: false,
      inFocus: '',
    };
  }

  handleEmailChange = (evt) => {
    this.setState({ email: evt.target.value });
  }

  handlePasswordChange = (evt) => {
    this.setState({ password: evt.target.value });
  }

  handleSubmit = (evt) => {
    if (!this.canBeSubmitted()) {
      evt.preventDefault();
      return;
    }
    const { email, password } = this.state;
    alert(`Signed up with email: ${email} password: ${password}`);
  }

  canBeSubmitted() {
    const errors = validate(this.state.email, this.state.password);
    const isDisabled = Object.keys(errors).some(x => errors[x]);
    return !isDisabled;
  }

  render() {
    const errors = validate(this.state.email, this.state.password);
    const isDisabled = Object.keys(errors).some(x => errors[x]);
    return (
      <form onSubmit={this.handleSubmit}>
        <input
          className={errors.email ? "error" : ""}
          type="text"
          placeholder="Enter email"
          value={this.state.email}
          onChange={this.handleEmailChange}
        />
        <input
          className={errors.password ? "error" : ""}
          type="password"
          placeholder="Enter password"
          value={this.state.password}
          onChange={this.handlePasswordChange}
        />
        <button disabled={isDisabled}>Sign up</button>
      </form>
    )
  }
}

ReactDOM.render(<SignUpForm />, document.body);

Upvotes: 0

Views: 76

Answers (2)

Galupuf
Galupuf

Reputation: 2957

The code may be valid and work, but you now have the same value (input) in two places; The input element's state AND React's state.

This is why react has controlled components.

"In HTML, form elements such as input, textarea, and select typically maintain their own state and update it based on user input. In React, mutable state is typically kept in the state property of components, and only updated with setState()." - https://reactjs.org/docs/forms.html

This practice makes React state the single source of truth.

And, as most know, anytime you are trying to keep track of one value in two places you can run into many issues

Upvotes: 1

Shirley
Shirley

Reputation: 190

It's the difference between a React controlled form and a non-React controlled form. It's totally possible to use uncontrolled forms in React, but that limits your forms to just very, very basic forms. It can also create potential problems down the road because React should be the one controlling everything in your app. I think it's good practice to use controlled forms because then it's easy to add in validations, or some other dynamic element to your page based on form input.

I think this blog post and this one do a pretty good job of explaining in more detail.

Upvotes: 0

Related Questions