15
votes

So, I'm trying to create form with Formik and Material UI. For all the fields everything is working as it should but the problem is with Autocomplete. I cannot find the way to populate the field from the localStorage. I tried everything, from putting the value props, inputValue, defaultValue, etc but nothing seems to work.

import React from 'react'
import { Grid } from '@material-ui/core'
import { Autocomplete } from '@material-ui/lab'
import { Formik, Form, Field } from 'formik'
import { TextField } from 'formik-material-ui'
import * as yup from 'yup'
import { nationality } from '../../constants/nationality'
import Button from '../Button/Button'

export default function ForeignAddress () {

  let localStorageData = localStorage.getItem('foreignAddress'),
    retrivedData = JSON.parse(localStorageData)


  const handleNextClick = () => {
    console.log('clicked next')
  }

  const handleBackClick = () => {
    console.log('clicked back')
  }

  const validationSchema = yup.object({
    streetName: yup.string().required('Street name is required'),
    streetNumber: yup.string().required('Street number is required'),
    postalCode: yup.string().required('Postal code is required'),
    city: yup.string().required('City is required'),
    country: yup.string().required('Country is required'),
  })

  console.log(retrivedData)

  return (
    <React.Fragment>
      <div className="pages-wrapper address">
        <Formik
          initialValues={retrivedData ? retrivedData : {streetName: '', streetNumber: '', postalCode: '', city: '', coAddress: '', country: ''}}
          onSubmit={(data) => {
            console.log(data)
            localStorage.setItem('foreignAddress', JSON.stringify(data))
            handleNextClick()
          }}
          validationSchema={validationSchema}
        >
          {({setFieldValue}) => (
            <Form>
              <Grid container spacing={3}>
                <Grid item xs={12} md={8}>
                  <Field component={TextField} name="streetName" label="Street Name" variant="outlined" fullWidth />
                </Grid>
                <Grid item xs={12} md={4}>
                  <Field component={TextField} name="streetNumber" label="Street Number" variant="outlined" fullWidth />
                </Grid>
                <Grid item xs={12} md={4}>
                  <Field component={TextField} name="postalCode" label="Postal Code" variant="outlined" fullWidth />
                </Grid>
                <Grid item xs={12} md={8}>
                  <Field component={TextField} name="city" label="City" variant="outlined" fullWidth />
                </Grid>
                <Grid item xs={12} md={6}>
                  <Field component={TextField} name="coAddress" label="C/O Address" variant="outlined" fullWidth />
                </Grid>
                <Grid item xs={12} md={6}>
                  <Autocomplete
                    id="foreignCountry"
                    className="country-select"
                    name="country"
                    options={nationality}
                    getOptionLabel={option => option.label}
                    onChange={(e, value) => {
                      console.log(value)
                      setFieldValue("country", value.code)
                    }}
                    renderInput={params => (
                      <Field component={TextField} {...params} name="country" label="Country" variant="outlined" fullWidth/>
                    )}
                  />
                </Grid>
              </Grid>
              <div className="button-wrapper">
                <Button label="Back" go="back" handleClick={handleBackClick}/>
                <Button label="Next" go="next" type="submit" />
              </div>
            </Form>
          )}
        </Formik>
      </div>
    </React.Fragment>
  )
}

EDIT:

Thanks to @Vencovsky i was able to get it done

in case someone in the future needs this here is the working code. Just change Autocomplete component to

<Autocomplete
  id="foreignCountry"
  className="country-select"
  name="country"
  options={nationality}
  getOptionLabel={option => option.label}
  defaultValue={values.country}
  onChange={(e, value) => {
    console.log(value)
    setFieldValue("country", value)
}}
  renderInput={params => (
    <Field component={TextField} {...params} name="country" label="Country" variant="outlined" fullWidth/>
)}
/>

and in the Formik props just add values prop

{({setFieldValue, values}) => (
   <Form>,...
1
thanks for sharing, helped me a lot :+1Gabo
Thanks for pointing me in the right direction!Robert Moskal

1 Answers

14
votes

Edit:

There is a few thing you need to change.

First you can't just store the code to load it later, you need to store everything (the hole value object) from the options.

Change the initial value of country: '' to country: {code: "", label: "", phone: ""} which is all the default value of the options.

Then to load the value correctly you should pass value={values.country} where values comes from formik props.

And on onChange you should save the hole value onChange={(e, value) => {setFieldValue("country", value); }}

But you are also importing and using some wrong things like

  <Field
    component={TextField}
    {...params}
    name="country"
    label="Country"
    variant="outlined"
    fullWidth
  />

Where Field is form formik and TextField from formik material ui.

Not sure why you use it like that, but I have changed it.

Here is a working example