4

I am getting the data from my form component and trying to set the state of my app component with this data.

However, the state.data is an empty object and is not updating the data. I console log the model data before setting it to check if it exists. Their is data within the model.

import React, { Component, Fragment } from "react";
import Form from "../components/Form";

import product from "./product.json";

class App extends Component {

    constructor() {
        super();  

        this.state = {
            data: {}
        };

    }

    onSubmit = (model) => {

        console.log("Outer", model);

        this.setState({
            data: model
        });

        console.log("Form: ", this.state);
    }
    render() {

        const fields = product.fields;

        return (
            <Fragment>
                <div>Header</div>
                <Form
                    model={fields}
                    onSubmit={(model) => {this.onSubmit(model);}}
                />
                <div>Footer</div>
            </Fragment>
        );
    }
}

export default App;
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Kay
  • 17,906
  • 63
  • 162
  • 270
  • 1
    I do think the `this.setState` isn't necessarily synchron, so your `console.log("Form: ", this.state);` could be to early to call. See also [the tutorial](https://reactjs.org/docs/state-and-lifecycle.html). I would expect that you can query `this.state` inside `render()` but not directly after calling `this.setState()`. Regarding forms, I would expect that you can succeed with [how the Forms tutorial does it](https://reactjs.org/docs/forms.html). – Uwe Keim Nov 25 '18 at 15:56
  • @UweKeim really? because in the onSubmit button i want to post this data to a server. – Kay Nov 25 '18 at 15:57
  • 4
    Possible duplicate of [setState doesn't update the state immediately](https://stackoverflow.com/questions/41278385/setstate-doesnt-update-the-state-immediately) – tex Nov 25 '18 at 16:00
  • @Kay, you need to `console.log()` your `state` object and see what properties are in there. Somehow `model` just does not seem right, but you can check that way or share what you have in the console with us regarding your `state` object. – Daniel Nov 25 '18 at 16:31

3 Answers3

13

setState() is an async call in React. So you won't likely get the updated state value in the next line. To check the updated value on successful state update, you could check in the callback handler.

Change this

onSubmit = (model) => {
  console.log("Outer", model);
  this.setState({
    data: model
  });
  console.log("Form: ", this.state);
}

to

onSubmit = (model) => {
  console.log("Outer", model);
  this.setState({
    data: model
  }, () => {
    console.log("Form: ", this.state);
  });
}
Dinesh Pandiyan
  • 5,814
  • 2
  • 30
  • 49
1

As per the react docs, setState is an asynchronous call. You can ensure your state has updated to perform a particular action in two ways as shown below:

  1. You can pass the setState a function which will have your current state and props and you the value you return will be your next state of the component. Keep in mind following:

state is a reference to the component state at the time the change is being applied. It should not be directly mutated. Instead, changes should be represented by building a new object based on the input from state and props.

Following is an example:

 this.setState((state, props) => {
      //do something
      return {counter: state.counter + props.step};
    });
  1. You can pass a callback to the setState function as mentioned in Dinesh's answer. The callback will be executed once the state has been updated successfully hence ensuring you will have the updated state in the call back.

Following is an example:

this.setState({ ...new state }, () => {
 // do something
});

Hope it helps.

Pranay Tripathi
  • 1,614
  • 1
  • 16
  • 24
  • Is it possible to use async and await here? Im looking for best practise – Kay Nov 26 '18 at 08:32
  • Best practice would be using any of these options. Using async await on setState can cause heavy load on your application and can cause slowness as well. – Pranay Tripathi Nov 26 '18 at 09:08
0

I just want to add, that if you will do like this its not going to work:

this.setState({things} , console.log(this.state))

You have to pass a refarence to the call back and not the exscutable code itself. If you won't do so, the function will envoke before the state is updated,even you will see the log.

Netanel R
  • 126
  • 1
  • 7