Skip to content

[RFC] Enabling form.reset() on controlled inputs, make value and defaultValue more transparent #8011

Closed
@nhunzaker

Description

@nhunzaker

I would like to make a case for supporting form.reset() for controlled inputs, and to make control over value and defaultValue more direct.

Background

React synchronizes the value attribute and the value property on inputs. I believe this is for two reasons:

  1. It is easy for testing frameworks like Selenium to select on [value="*"] when testing
  2. form.reset reverts an input back to it's value attribute. It also does not trigger change events, which causes input state to be out of sync with React state.

There are many reasons listed in #11896 to stop syncing the value attribute, so I'll keep this issue focused on my desired outcome.

The Change

I want to be able to control the value attribute and property directly from a component, at the same time:

// I won't add Flow types, but this is just for clarity
type Widget {
  name: string
}

class EditWidget extends React.Component {
  constructor() { 
    this.state = this.props.widget
  }
  onChange(event) {
    this.setState({ name: event.target.value })
  }
  render() {
    return (
      <form>
        <input value={this.state.name} defaultValue={this.props.widget.name} onChange={this.onChange} />
        <button type="reset">Revert</button>
        <button type="submit">Save</button>
      </form>
    )
  }
}

With this change:

  1. The value React property directly maps to the value property
  2. The defaultValue React property directly maps to the value attribute
  3. Both value and defaultValue are configurable at the same time
  4. An input becomes controlled when it specifies a value property
  5. Support form.reset, sending synthetic change events for fields that mismatch the last tracked value (or maybe just fire blindly for simplicity)

Why

This change creates a more controlled input, and makes it much clearer how React applies changes. More control is granted to the user. It provides away to allow props coming into a form to dictate a canonical state for the form, while still supporting native browser behavior.

Also, it means that we don't synchronize the value attribute, which would save a lot of headaches 😄.

Things to figure out

Server rendering. What property do we use? In the case, we can only send along the default value. That might be fine for most cases, but I have not thought through the edge cases.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions