Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

state variables returns undefined

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.

like image 483
IT Cleanocean Avatar asked Oct 20 '25 11:10

IT Cleanocean


2 Answers

There are few problems in your code, Please do the following fixes:

  1. useEffect is called without dependencies

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);
  })
}, []);
  1. 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>
     </>
     );
    
  2. Change the initialisation of info. Make it an object since you are expecting an object from api. As:

    const [info, setInfo] = useState({});
    
like image 69
neeraj tk Avatar answered Oct 22 '25 00:10

neeraj tk


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.

  1. You need to set 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.
  2. The only prop you need, according to the docs with a very similar example, is 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.
like image 38
jamesTobey Avatar answered Oct 22 '25 01:10

jamesTobey



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!