Search code examples
reactjsreact-bootstrapcontrolled-component

Can I programmatically update the values of React bootstrap <Form.Control> after it's been updated?


Is it possible to update the value of a React Bootstrap <Form.Control> after it's been edited by a user?

I've created a small Bootstrap form in React with four controlled fields. Details are below. Submission works, but I'd like a way to update the values of various fields programmatically, both to reset the form and to fill in sets of common defaults.

  • My code, in which various buttons call setFormContents, works until a field is updated. After this, updating the value passed into the defaultValue of the <Form.Control>. This makes sense, but I'm not sure what is the preferred way to proceed.
  • The variables formContents and setFormContents are assorted with the parent element of <MyForm>.

Details

The state of the form and the associated updating function is provided via props

define MyForm(props)
 return <Form
      onSubmit={(e) => {
        e.preventDefault();
        onSubmit(props.formContents);
      }}
    >
      <Form.Group className="mb-3" controlId="field1">
        <Form.Label>Field 1</Form.Label>
        <Form.Control
          defaultValue={props.formContents.val1}
          onChange={({ target: { value } }) =>
            props.setFormContents({ ...props.formContents, val1: value })
          }
        />
      </Form.Group>
      ///... Other <Form.Group>s
</Form>

Solution

  • In my case, the update was for all fields. My solution, which is modeled on this StackOverflow response was to reset the form before updating it.

    1. Create a state that will store reference to the DOM <form> element.
        const [formDOM, setFormDOM] = useState(null);
    
    1. Use the ref= property of the <Form> element to capture the DOM element. The state will have type ?HTMLFormElement
        <Form
          ref={(form) => props.setFormDOM(form)}
         ...
        >
    
    1. Provide this ReactDOM to elements that update the form. Reset the form before any updates.
    onClick={(e) => {
      if (props.formDOM != null) {
        props.formDOM.reset();
      }
      props.setFormContents(...);
    }}