Reputation: 1021
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.
Upvotes: 1
Views: 591
Reputation: 202915
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>
);
};
Upvotes: 1
Reputation: 565
if you just want to keep the initialValue always as the first time value, you need to do it like
const initialValue = useMemo(() => value, []);
as your code, the function runs whenever the value changes, so the initialValue changes every time when the value changes
Upvotes: 1