question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Next] Should form automatically reset if passed-in props change?

See original GitHub issue

The scenario I’m trying to implement is the following:

  1. User clicks “edit”
  2. GraphQL query gets dispatched, form gets rendered with loading indicator
  3. GraphQL response gets returned, apollo updates underlying bound components
  4. Form gets filled with response data, loading indicator gets removed

The problem I’m running into is that mapPropsToValues() only gets called in the constructor and not in componentWillReceiveProps(), and as a result Formik never updates the form with the received values and just renders the empty state. Is there any way around this right now, or is this not supported?

With a slightly hacky workaround I’m currently passing down the values as a different prop so they reach the form component itself, where I’m doing a this.props.resetForm() whenever the prop changes. Does the job for now, but wondering if we could just use componentWillReceiveProps() in Formik itself. I realize it can be a bit tricky but by checking if the previous values prop were falsy and/or the values state is not dirty this should be rather safe I think.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:5
  • Comments:12 (1 by maintainers)

github_iconTop GitHub Comments

9reactions
pleunvcommented, Oct 24, 2017

If you use the <Formik> component you should be able to pass enableReinitialize, which will reinitialize when it detects your initialValues have changed. So what should work is something like this:

const emptyFormState = {
  id: undefined,
  firstName: '',
  lastName: ''
};

export default class MyForm extends React.Component {
  getInitialValues() {
    return this.props.data.user || emptyFormState;
  }

  render() {
    return (
      <Formik
        enableReinitialize
        initialValues={this.getInitialValues()}
        onSubmit={this.props.onSubmit}
      >
        <YourFormLogic />
      </Formik>
    )
  }
}

MyForm.propTypes = {
  data: PropTypes.shape({
    user: PropTypes.shape({
      id: PropTypes.number.isRequired,
      firstName: PropTypes.string.isRequired,
      lastName: PropTypes.string.isRequired
    })
  }).isRequired,
  onSubmit: PropTypes.func.isRequired
};

Your user query data starts off undefined -> apollo fires the request -> apollo receives the response -> user prop gets updated -> MyForm re-renders -> Formik detects change in initialValues -> Formik reinitializes the form.

That said, you could also very easily block rendering of <Formik ... /> and just return null or a <Loader /> as long is this.props.data.user === undefined. Depends what behavior you want.

1reaction
pleunvcommented, Oct 24, 2017

Looking at your gist that’s normal, since your values will be undefined until apollo gets a response back from your query. 2 options:

  • You initialize your values with some kind of default value (i.e. empty string - see my emptyFormState example) since input components will throw that uncontrolled-to-controlled warning when you initialize them with undefined.
  • You block rendering until this.props.data.user !== undefined or this.props.loading === false.
Read more comments on GitHub >

github_iconTop Results From Across the Web

Updating state on props change in React Form
we set the state using setState, using useEffect we check for changes to the specified prop, and take the action to update the...
Read more >
Preserving and Resetting State
Resetting a form with a key​​ Resetting state with a key is particularly useful when dealing with forms. Try entering something into the...
Read more >
useForm - reset
Reset the entire form state, fields reference, and subscriptions. There are optional arguments and will allow partial form state reset. Props. Reset has...
Read more >
How and when to force a React component to re-render
React automatically re-renders components, but what happens when a component is not updating as expected? Find out what you can do here.
Read more >
When does React re-render components?
As we already saw before, React re-renders a component when you call the setState function to change the state (or the provided function...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found