Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recommended way to set initialValues from async api call #1033

Closed
dem0nbruce opened this issue Oct 21, 2018 · 23 comments
Closed

Recommended way to set initialValues from async api call #1033

dem0nbruce opened this issue Oct 21, 2018 · 23 comments

Comments

@dem0nbruce
Copy link

❓Question

What is the recommended/best practice way to set the forms values when loading data from an asynchronous api call?

My use case involves using redux to load data into my components props and binding it to initialValues:

<Formik enableReinitialize={true} initialValues={this.props.user}>
...
</Formik>

This however throws the following error because this.props.user is initially undefined:

Warning: A component is changing an uncontrolled input of type undefined to be controlled.

Is this the recommended/best practice way to load data into a form? If so, how would I resolve the error above?

@akhil-gautam
Copy link

Are you using this component inside some other component from where you are passing data?
It would be better if you initialize the form with empty values like below:
const initialData = { user: { email: '', name: '', } }
In this way, it won't throw any errors.

A bit more code block sample will make the community easy to understand.
Hope this works for you.

@jaredpalmer
Copy link
Owner

You pass them as props to initialValues

@akhil-gautam
Copy link

You pass them as props to initialValues

I think he is already using props but using Redux's HOC(connect).
Are you saying to pass the props from parent component?
Alternatively, he can initialize the user in the reducer also if is sticking to redux.

@davemooreuws
Copy link

davemooreuws commented Oct 22, 2018

@dem0nbruce Just have a default value for user, so you will always have an object as initialValues.

const { user = {} } = this.props;
return (
<Formik enableReinitialize={true} initialValues={user}>
...
</Formik>
)

@dem0nbruce
Copy link
Author

@davemooreuws Your solution defaulting the user field values worked for me.

@aleksey-pro
Copy link

What if I make update data in form? It's necessary to save last loaded input values in form as default values. In this case initial data will change, and cannot be empty.

@NKBelousov
Copy link

@davegahn yeah, I have similar case. Would like to have an ability to merge updated form with new initial values myself

@jaredpalmer is there a way to do that right now?

@zach-watrhub
Copy link

@aleksey-pro did you ever resolve that use case? I am running into the same issue at the moment - unable to keep field values from other fields when the API-dependent field is updated via initialValues with enableReinitialize

@john-dominguez
Copy link

@aleksey-pro did you ever resolve that use case? I am running into the same issue at the moment - unable to keep field values from other fields when the API-dependent field is updated via initialValues with enableReinitialize

I believe you have the same issue i had. I am fetching the initialized formik data onComponentMount, and was getting the stated error above.
I'm using Graphql/Apollo on my backend/frontend, data is the returned response from the server:

The following gets called when loading the component.

const { data, loading, refetch } = useQuery(query, {
    variables: { id }
  })

On the Formik Component i set the following:

initialValues={getData()}
enableReinitialize={true}

The key is getData:
const getData = () => data?.employee || tempData

Where tempData is just an object with the field value keys:
const tempData = {id: '', name''}

@fmozaffari
Copy link

@aleksey-pro did you ever resolve that use case? I am running into the same issue at the moment - unable to keep field values from other fields when the API-dependent field is updated via initialValues with enableReinitialize

I set the Formik's initial value to a local state and updated that state when I got new data to populate the form. It worked after I set enableReinitialize to True

@dagenius007
Copy link

I am using useFormik instead , how do I set the values from api call in my redux action passed as props to my component

@AndyYuanZhou
Copy link

I really don't understand how it works...

@halberio
Copy link

const { user } = this.props; 

return ( 
<Formik 
enableReinitialize={true} 
initialValues={{
 name: user.name ? user.name : "",
 age: user.age ? user.age : ""
 }} 
> ... 
</Formik>

@kilinkis
Copy link

but how can you have default values for fields you don't know?
I mean, in a dynamic form for example, where you'll get the fields from an API.

@moiz-frost
Copy link

but how can you have default values for fields you don't know?
I mean, in a dynamic form for example, where you'll get the fields from an API.

I think in that case you can pass the value prop to once you receive the form fields and their default values from your API call asynchronously

@johnrom
Copy link
Collaborator

johnrom commented Jan 17, 2021

@kilinkis I don't have an answer at the moment because your request isn't supported in the Formik API. But if you are in control of your API and able to create a new build when updating the fields in your form (CMS ??) you can trigger a github action to re-run your build, make your API call to Fields during your build which populates the default initial values, and use those to prepopulate your form.

Or if your page is being printed by a server with access to that info, WordPress as an example, wp_localize_scripts can let you serialize the JSON initial values of your fields to a script object on your page which your script can check for.

None of these are ideal, for sure, and in the future maybe this information could be obtained via registerField.

@iblokhin
Copy link

We can use shorted code for default value

const { user } = this.props;

return ( 
  <Formik 
    enableReinitialize={true} 
    initialValues={{
      name: user?.name ?? "",
      age: user?.age ?? ""
    }} 
  > ... 
  </Formik>

@iblokhin
Copy link

but how can you have default values for fields you don't know?
I mean, in a dynamic form for example, where you'll get the fields from an API.

You can subscribe in props and when props will be change, you can create need fields and initialValues for them. Into initialValue you put method which well be return new genereted default values. So as enableReinitialize={true}, formik will make new fields with them values and to do rerender

@koiralakiran1
Copy link

koiralakiran1 commented Aug 5, 2021

My use case was to handle both 'Create' and 'Update' actions in the same page/form. enableReinitialize made it seamless. enableReinitialize makes the code so neat. Neater than the whiskey that I might drink, with all this free time I got, after getting right to this thread. 😄

Awesome stuff 👍 🥃

@bhuvanesh1506
Copy link

can you share the example of get api call for enablereinitialize value need to bind using functional components?

@kaiz123
Copy link

kaiz123 commented Apr 13, 2022

If you are getting your initial values from an API call then they are technically NOT initial values. They are the first state after initial values. So you should set your initial state to something like empty values, and then pass down the updated values from the API to the specific formik components and use something like setFieldValue or value prop.

@sanginovs
Copy link

some of my form fields weren't updating after async call. My issue was that i set initial field value to undefined instead of an empty string. Changing it back to empty string solved the problem.

@isaacadam25
Copy link

@iblokhin You saved my problem. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests