G Josh
G Josh

Reputation: 311

React useState() - how to update objects

I can't seem to update my state with useState(), whenever my alert displays, I always see my state displaying its initial value.

Sample code below, my expectation is that when I click the Save button, setData will update data with new values I have in my form, then display contents of data with alert. However, what's happening is that whenever I click Save, alert is always displaying my initial values.

How do I update data with my field values so that my alert can pick up the changes?

const initialValues = {
    title: "",
    description: ""
}

const CreateForm = (props) => {
    const [data, setData] = useState(initialValues);

    const handleSave = (values) => {
        setData({
            title: values.title,
            description: values.description
        });

        setTimeout(() => {
            alert(JSON.stringify(data, null, 2));
        }, 3000)
    }
    return (
        <div>
             <Formik initialValues={data}
                validationSchema={validationSchema}
                onSubmit={(values) => {
                    setTimeout(() => {
                        alert(JSON.stringify(values, null, 2));
                    }, 3000)
                }}
            >
                {props => (
                    <Form>
                        <TextField name="title" type="input" label="Title" />
                        <TextField name="description" type="input" label="description" />

                        <div >
                            <Button type="submit" variant="contained" color="primary">Submit</Button>&nbsp;
                            <Button variant="contained" color="secondary" onClick={() => handleSave(props.values)}>Save</Button>&nbsp;
                        </div>
                    </Form>
                )}
            </Formik>
        </div>
    )

}

export default CreateForm

Upvotes: 3

Views: 129

Answers (2)

AnotherWombat42
AnotherWombat42

Reputation: 121

Assuming that values also did not update, try switching to Formik's Field object instead of TextField.

<Form>
  <Field name="title" type="input" label="Title" />
  <Field name="description" type="input" label="description" />

  <div >
    <Button type="submit" variant="contained" color="primary">Submit</Button>&nbsp;
    <Button variant="contained" color="secondary" onClick={() => handleSave(props.values)}>Save</Button>&nbsp;
  </div>
</Form>

If TextField is a third-party control, then you may have to update the code like this:

<Field name="title" type="input" label="Title" component={TextField}/>

You sometimes need a bindings library to map all the formik functionality back to a third-party lib. Like you may use formik-material-ui to provide the bindings for Material-UI.

Upvotes: 0

ravi
ravi

Reputation: 1145

you can use "useEffect" hook, what it will do basically is it will see if there are any changes in the data , which we have passed as source to useEffect , if there are changes it will trigger the function passed to it , where you can alert the data , As in your code in function "handleSave" we are assigning new value to data, which will eventually trigger the useEffect.

  useEffect(() => {
         //logic for the alert
         alert(JSON.stringify(data, null, 2));
  },[data]);

Upvotes: 2

Related Questions