I need help with managing react states, I can't seem to wrap my head around it.
I have a component that receives the id of a database entry from another page via useLocation, I then use that id with an axios get request to pull the rest of the data into an array. However, when I am trying to use the data from the get request as a defaultValue for an MUI TextField it doesn't render the data naturally, the states returns as undefined after the page loads. I have to set the TextField's key to the get request data (a work around I found in the web) to render. Then when I try to submit the form, the value from the Textfield displays as undefined though the Texfield contains the data from the get request.
const location = useLocation();
const [info, setInfo] = useState([]);
useEffect(()=>{
axios
.get("//localhost:3001/Info/" + location.state.id)
.then((response)=>{
setInfo(response.data);
})
});
const validationSchema = Yup.object().shape({});
const formik = useFormik({
initialValues: {
name: info.name
},
validationSchema: validationSchema,
onSubmit: (values) => {
console.log(values) // displays {name: undefined, .....}
}
});
return(
<>
<Container>
<form onSubmit = {formik.handleSubmit}>
<TextField
id = "name"
label = "Name"
name = "name"
onChange = {formik.handleChange}
onBlur = {formik.handleBlur}
key = {info.name} //Textfield blank without setting key
defaultValue = {info.name}
/>
<Button type = "Submit"> Submit </Button>
</form>
</Container>
</>
);
I am expecting the TextFields default values to render correctly without declaring a key as a work around. Also, I expect the values of the textfields to contain the initialvalues from the formik declaration on submit.
There are few problems in your code, Please do the following fixes:
Update your useEffect as follows so that it gets triggered only on initial mount:
useEffect(()=>{
axios
.get("//localhost:3001/Info/" + location.state.id)
.then((response)=>{
setInfo(response.data);
})
}, []);
Check if the property name exists before rendering:
if(!info.name){
return <div>Loading</div>
}
return(
<>
<Container>
<form onSubmit = {formik.handeSubmit}>
<TextField
id = "name"
label = "Name"
name = "name"
onChange = {formik.handleChange}
onBlur = {formik.handleBlur}
key = {info.name} //Textfield blank without setting key
defaultValue = {info.name}
/>
<Button type = "Submit"> Submit </Button>
</form>
</Container>
</>
);
Change the initialisation of info. Make it an object since you are expecting an object from api. As:
const [info, setInfo] = useState({});
I created a Codesandbox with a working solution for the code that you provided; first, I had to switch the API method to call something that is not running on localhost, and second, I swapped out the custom component for a standard input.
enableReinitialize
to true in your useFormik
hook, otherwise the form won't reinitialize on the subsequent render that happens once the API promise method has been resolved.value
, which I've provided here. This sets the initial value of the field properly, and in conjunction with the onChange()
and onBlur()
methods, updates the form state correctly when the user interacts with the field.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With