Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Formik Material UI Autocomplete: How can I populate value inside of autocomplete from localStorage?

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>,...
like image 593
utazabanje Avatar asked Dec 09 '19 13:12

utazabanje


People also ask

How do I use material UI Autocomplete with Formik?

To use React Material UI's Autocomplete component with Formik, we can call Formik's setFieldValue function with the name prop value of the Autocomplete and the value that is selected. We add the Form component with the Autocomplete component inside.

How do you use autocomplete material UI in React?

Material UI has props built in to handle the state of the Autocomplete vs input values. In your example, you would want to add the inputChange and onInputChange props to the Autocomplete component. These will get passed down to your TextField through the params passed to the renderInput function.

What does Formik handleChange do?

Using Formik's handleChange The handleChange method updates the form values based on the input's name attribute that was changed. The handleChange method is used with input elements. Field component internally updates the values without the need of implementing the handleChange method.

Can I use material UI with Formik?

Formik can be easily used/integrated with Material UI, with just passing a few formik props to the respective Material UI Component props.


1 Answers

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

like image 53
Vencovsky Avatar answered Oct 03 '22 04:10

Vencovsky