Should a React form for editing update the underlying model?
Tags: react, forms, javascript
Published: 2017-11-08 03:44:26

---
title: "Should a React form for editing update the underlying model?"
published: true
tags: React, Forms, javascript
canonical_url: https://goshakkk.name/react-forms-for-editing/
---

In an imaginary world where forms are only ever used to enter something from scratch, what you know about forms in React might be enough. In the real world, however, forms are often lively creatures – you can come back to them and change your data.

Up until now, our forms were pretty stand-alone and isolated.

Forms for entering new data start out like this:

```js
constructor() {
  super();
  this.state = {
    email: '',
    password: '',
  };
}
```

and they are used something like this, perhaps:

```js
<SignUpForm />
```

We can see they don’t receive any props, they keep the current values in the state, and they initialize the state with empty values. Which is perfect if all you need is to collect brand new data through the form.

But what if you had a different form… for editing a post, for example. It would somehow have to accept current title and body. Maybe like this:

```js
<PostForm title={someTitle} body={someBody} />
```

Except now there are several possibilities as of how to go further with this:

- **Make the form itself fully controlled with regard to its parent.** It means _instead of_ keeping its own state, the form is always going to receive field values, as well as callbacks to change them. Just like with controlled/uncontrolled inputs, this will make an entire form controlled.

  ```js
  <PostForm
    title={...}
    body={...}
    onChangeTitle={...}
    onChangeBody={...}
  />
  ```

  This is not a usual case, however. Only a subtle fraction of forms out there needs to have something like that. It could be used when the changes to the form, as you make them, need to be immediately reflected in the rest of the app.

  And it’s not without its drawbacks, either. Doing it this way means invalid unsaved data now has a way out of the form: if you are directly updating some global state with work-in-progress form values, your app may end up consuming partial or errneous data.

- **Initialize the form state via props.** The form will still have its own state with input values. It will simply use the passed field values as a starting point.

  Used as:

  ```js
  <PostForm title={someTitle} body={someBody} />
  ```

  The form is going to take initial props, which will be passed to its `constructor`, and set initial state based on them:

  ```jsx
  class PostForm extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        title: props.title || '',
        body: props.body || '',
      };
    }
  }
  ```

  In a way, this is similar to making the form “uncontrolled” with respect to its parent. It maintains its own state, and uses the passed props as default values of the fields.

  New values should be communicated to the parent when the form is submitted:

  ```js
  <PostForm
    title={someTitle}
    body={someBody}
    onSubmit={(newTitle, newBody) => { ... }}
  />
  ```

  Unlike with individual inputs, having a form “uncontrolled” is a preferred method to make a form. A form is not a way to change a thing directly, rather, it’s a _request_ to change one.

  Think about paperwork to change the name. It doesn’t directly change your name as you fill it in; it doesn’t “bind” to your name. It is just initialized with some data (your current name), and you fill in the new name and take it to bureaucrats before it has any effect.

  And the same is often true of forms on the web – they do something only when submitted.

_This post was originally published on [goshakkk.name](https://goshakkk.name/react-forms-for-editing/)_

---

[I blog about forms](http://goshakkk.name/on-forms-react/) in React specifically, and other React-related things.
If you like what you see here, [subscribe here](http://goshakkk.name/subscribe/) to make sure you don't miss out on my next post.