I am making a simple react application which has some basic inputs like first name
, last name
etc..,
The state of the inputs are handled in context api like,
context.js
import React, { useState } from "react";
export const FormContext = React.createContext();
export function FormProvider({ children }) {
const [formValue, setFormValue] = useState({
basicDetails: {
firstName: "",
lastName: "",
address: {
city: "",
zip: ""
}
}
});
return (
<FormContext.Provider value={[formValue, setFormValue]}>
{children}
</FormContext.Provider>
);
}
In basic details component fetching the context like,
const [value, setValue] = React.useContext(FormContext);
const { basicDetails } = value;
Here to make a copy of initial value of context, I have tried using spread operator like,
const initialValue = { ...value };
And in handleSubmit
function tried to get the initially copied value (i.e..,) initialValue
but this is logging the values of latest changes.
Working example:
Requirement:
On click of the form submission, I am in the need to reset the form values with initial context data.
To achieve the resetting of values to initial data only I have tried spread operator { ...value }
but I think I am wrong with the approach.
Even JSON.parse(JSON.stringify(value))
doen't work in this case..
Kindly anyone help me to achieve of setting the form value to initial context on submit.
The other answer here seems sufficient. You could also save the initial field values in a React ref (const initialValue = React.useRef(value);
) and access later as initialValue.current
.
In reality you want your context to have more control over the context state. I suggest creating a reset
function to include in the context that children can consume.
context.js
Factor out the initial state definition, provide a default context value, and pass the state and callbacks to the context value.
const initialFormState = {
basicDetails: {
firstName: "",
lastName: "",
address: {
city: "",
zip: "123"
}
}
};
export const FormContext = React.createContext({
formValue: initialFormState,
setFormValue: () => {},
reset: () => {}
});
export function FormProvider({ children }) {
const [formValue, setFormValue] = useState(initialFormState);
const reset = () => setFormValue(initialFormState);
return (
<FormContext.Provider
value={{ value: formValue, setValue: setFormValue, reset }}
>
{children}
</FormContext.Provider>
);
}
basicDetails.js
Consume and destructure the context value. Change the submit button to be of type="submit"
so you can submit the form, and call reset
in the submit handler to reset the form state.
const BasicDetails = () => {
const {value, setValue, reset} = React.useContext(FormContext);
const { basicDetails } = value;
const handleInputChange = (event) => {
const { name, value: val } = event.target;
setValue((prev) => {
const basicDetails = {
...prev.basicDetails,
...(value.basicDetails[name] !== undefined
? { [name]: val }
: { address: { ...value.basicDetails.address, [name]: val } })
};
return { ...prev, basicDetails };
});
};
const handleSubmit = (e) => {
e.preventDefault();
// Do what you need with the current form values
console.log("Values", value);
// Finally reset the form
e.target.reset();
};
return (
<div>
<h1> Basic Details </h1>
<form onSubmit={handleSubmit} onReset={reset}>
<label htmlFor="firstName">First Name: </label>
<input
type="text"
className="form-control"
id="firstName"
name="firstName"
value={basicDetails.firstName}
onChange={handleInputChange}
/>
<br />
<br />
<label htmlFor="lastName">Last Name: </label>
<input
type="text"
className="form-control"
id="lastName"
name="lastName"
value={basicDetails.lastName}
onChange={handleInputChange}
/>
<br />
<br />
<label htmlFor="lastName">City: </label>
<input
type="text"
id="city"
name="city"
value={basicDetails.address.city}
onChange={handleInputChange}
/>
<br />
<br />
<label htmlFor="lastName">Zip: </label>
<input
type="text"
className="form-control"
id="lastName"
name="zip"
value={basicDetails.address.zip}
onChange={handleInputChange}
/>
<br />
<br />
<button type="submit">
Submit
</button>
</form>
</div>
);
};