Last active
March 8, 2022 17:29
-
-
Save Aniganesh/68085288cf957290df93a564df962840 to your computer and use it in GitHub Desktop.
How to use formik with multiple fields in the same value
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Form, Formik } from "formik"; | |
import React, { useState } from "react"; | |
import "./App.css"; | |
/* To view the result in a browser, create a new react app and replace the existing App.jsx file with this file */ | |
function App() { | |
const [numAddresses, setNumAddresses] = useState(1); | |
const localStorageAddresses = JSON.parse( | |
localStorage.getItem("savedAddresses") || "[]" | |
); | |
return ( | |
<FormContextProvider> | |
<FormContext.Consumer> | |
{({ savedAddresses, setSavedAddresses }) => ( | |
<div className="App"> | |
<Formik | |
initialValues={{ | |
addresses: savedAddresses || localStorageAddresses || [], | |
// values in the form when loaded for the first time or whenever this value is changed | |
}} | |
enableReinitialize={true} // important parameter. will allow setting the new values of the form using initialValues | |
onSubmit={({ addresses }, helpers) => { | |
console.log({ addresses }); | |
// On submitting form, save in context and local storage. It is not necessary to store in both. Any one is enough. Saving in both just to show an example | |
setSavedAddresses(addresses); | |
localStorage.setItem( | |
"savedAddresses", | |
JSON.stringify(addresses) | |
); | |
helpers.resetForm(); | |
}} | |
> | |
{({ handleChange }) => { | |
console.log({ savedAddresses }); | |
return ( | |
<Form> | |
{/* Create an array of length 'numAddresses' */} | |
{Array.from({ length: numAddresses }).map((_, index) => ( | |
/* All entries in the array will have undefined as value by default. So ignoring the first parameter when mapping through the array */ | |
<div | |
key={index} | |
style={{ | |
padding: 8, | |
width: "fit-content", | |
margin: "0 auto", | |
}} | |
> | |
<div | |
style={{ | |
paddingTop: 8, | |
paddingBottom: 8, | |
textAlign: "left", | |
}} | |
> | |
Address {index + 1} | |
</div> | |
<label htmlFor={`addresses[${index}].line1`}> | |
Address line 1 | |
</label> | |
<input | |
name={`addresses[${index}].line1`} | |
onChange={handleChange} | |
/> | |
<label htmlFor={`addresses[${index}].line2`}> | |
Address line 2 | |
</label> | |
<input | |
name={`addresses[${index}].line2`} | |
onChange={handleChange} | |
/> | |
<label htmlFor={`addresses[${index}].line3`}> | |
Address line 3 | |
</label> | |
<input | |
name={`addresses[${index}].line3`} | |
onChange={handleChange} | |
/> | |
{/* MUI equivalent: | |
<TextField name={`addresses[${index}].line3`} onChange={handleChange} label="Address line 3" /> | |
*/} | |
</div> | |
))} | |
<div> | |
<button | |
type="button" | |
onClick={() => { | |
setNumAddresses(numAddresses + 1); | |
/* Increase number of addresses */ | |
}} | |
> | |
Add address | |
</button> | |
<button type="submit">Submit</button> | |
</div> | |
</Form> | |
); | |
}} | |
</Formik> | |
</div> | |
)} | |
</FormContext.Consumer> | |
</FormContextProvider> | |
); | |
} | |
export default App; | |
const FormContext = React.createContext({ | |
savedAddresses: [], | |
setSavedAddresses: (addresses /* Array of addresses */) => {}, | |
}); | |
const FormContextProvider = ({ children }) => { | |
const [savedAddresses, setSavedAddresses] = useState([]); | |
console.log({ savedAddresses }, " in FormContextProvider"); | |
return ( | |
<FormContext.Provider value={{ savedAddresses, setSavedAddresses }}> | |
{children} | |
</FormContext.Provider> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment