By Sydney Loteria


2016-12-22 08:03:40 8 Comments

I would like to ask why my state is not changing when I do an onclick event. I've search a while ago that I need to bind the onclick function in constructor but still the state is not updating. Here's my code:

import React from 'react';

import Grid from 'react-bootstrap/lib/Grid';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';

import BoardAddModal from 'components/board/BoardAddModal.jsx';

import style from 'styles/boarditem.css';

class BoardAdd extends React.Component {

    constructor(props){
        super(props);

        this.state = {
            boardAddModalShow: false
        }

        this.openAddBoardModal = this.openAddBoardModal.bind(this);
    }
    openAddBoardModal(){
        this.setState({ boardAddModalShow: true });
// After setting a new state it still return a false value
        console.log(this.state.boardAddModalShow);

    }

    render() {

        return (
            <Col lg={3}>
                <a href="javascript:;" className={style.boardItemAdd} onClick={this.openAddBoardModal}>
                    <div className={[style.boardItemContainer,style.boardItemGray].join(' ')}>
                        Create New Board
                    </div>
                </a>



            </Col>
        )
    }
}

export default BoardAdd

11 comments

@Dipanshu Sharma 2019-08-28 10:20:29

Yes because setState is an asynchronous function. The best way to set state right after you write set state is by using Object.assign like this: For eg you want to set a property isValid to true, do it like this


Object.assign(this.state, { isValid: true })


You can access updated state just after writing this line.

@Preetham NT 2019-08-14 17:08:18

setState is an asynchronous function so you might need to use it as,

this.setState({key:value},()=>{ callYourFunction(this.state.key) });

@Mustkeem K 2018-07-09 11:16:20

Fortunately setState takes a callback. And this is where we get updated state. Consider this example.

this.setState(
    { name: "Mustkeom" },
      () => {                        //callback
        console.log(this.state.name) // Mustkeom
      }
);

So When callback fires, this.state is the updated state. You can get mutated/updated data in callback.

@Dende 2018-12-21 13:01:21

You can also use this callback to pass any function, initMap(), for instance

@Mustkeem K 2019-07-06 13:15:51

Exactly. You are right

@khizer 2019-05-18 07:55:26

According to React Docs

React does not guarantee that the state changes are applied immediately. This makes reading this.state right after calling setState() a potential pitfall and can potentially return the existing value due to async nature . Instead, use componentDidUpdate or a setState callback that is executed right after setState operation is successful.Generally we recommend using componentDidUpdate() for such logic instead.

Example:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      counter: 1
    };
  }
  componentDidUpdate() {
    console.log("componentDidUpdate fired");
    console.log("STATE", this.state);
  }

  updateState = () => {
    this.setState(
      (state, props) => {
        return { counter: state.counter + 1 };
      });
  };
  render() {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
        <button onClick={this.updateState}>Update State</button>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

@Atchutha rama reddy Karri 2019-04-12 06:42:36

 this.setState({
    isMonthFee: !this.state.isMonthFee,
  }, () => {
    console.log(this.state.isMonthFee);
  })

@stuli 2019-03-03 07:55:00

setState() is asynchronous. The best way to verify if the state is updating would be in the componentDidUpdate() and not to put a console.log(this.state.boardAddModalShow) after this.setState({ boardAddModalShow: true }) .

according to React Docs

Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately

@Aman Seth 2018-11-26 18:09:19

setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall. Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, read about the updater argument below.

setState() will always lead to a re-render unless shouldComponentUpdate() returns false. If mutable objects are being used and conditional rendering logic cannot be implemented in shouldComponentUpdate(), calling setState() only when the new state differs from the previous state will avoid unnecessary re-renders.

The first argument is an updater function with the signature:

(state, props) => stateChange

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. For instance, suppose we wanted to increment a value in state by props.step:

this.setState((state, props) => {
    return {counter: state.counter + props.step};
});

@Spock 2018-09-07 15:19:50

This callback is really messy. Just use async await instead:

async openAddBoardModal(){
    await this.setState({ boardAddModalShow: true });
    console.log(this.state.boardAddModalShow);
}

@T.J. Crowder 2019-08-19 09:06:27

That makes no sense. React's setState doesn't return a promise.

@Mike Richards 2019-10-03 17:57:19

@T.J.Crowder is right. setState doesn't return a promise, so it should NOT be awaited. That said, I think I can see why this is working for some people, because await puts the inner workings of setState on the call stack ahead of the rest of the function, so it gets processed first, and thus seems like the state has been set. If setState had or implements any new asynchronous calls, this answer would fail.To implement this function properly, you can use this: await new Promise(resolve => this.setState({ boardAddModalShow: true }, () => resolve()))

@Ravin Gupta 2018-07-28 21:20:27

If you want to track the state is updating or not then the another way of doing the same thing is

_stateUpdated(){
  console.log(this.state. boardAddModalShow);
}

openAddBoardModal(){
  this.setState(
    {boardAddModalShow: true}, 
    this._stateUpdated.bind(this)
  );
}

This way you can call the method "_stateUpdated" every time you try to update the state for debugging.

@Adnan shah 2018-07-20 13:20:20

Since setSatate is a asynchronous function so you need to console the state as a callback like this.

openAddBoardModal(){
    this.setState({ boardAddModalShow: true }, () => {
        console.log(this.state.boardAddModalShow)
    });
}

@Shubham Khatri 2016-12-22 08:06:39

Your state needs some time to mutate, and since console.log(this.state.boardAddModalShow) executes before the state mutates, you get the previous value as output. So you need to write the console in the callback to the setState function

openAddBoardModal(){
        this.setState({ boardAddModalShow: true }, function () {
             console.log(this.state.boardAddModalShow);
        });

}

setState is asynchronous. It means you can’t call setState on one line and assume state has changed on the next.

according to React docs

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.

Why would they make setState async

This is because setState alters the state and causes rerendering. This can be an expensive operation and making it synchronous might leave the browser unresponsive.

Thus the setState calls are asynchronous as well as batched for better UI experience and performance.

@maudev 2019-01-25 06:16:31

Until now it is an great idea, BUT what if we can't use console.log because u're using eslint rules?

@Shubham Khatri 2019-01-25 06:44:24

@maudev, eslint rules stop you to have console.logs so that they don't end up in production, but the above example is purely for debugging. and console.log and be replaced with an action which takes into account the updated state

@Alex Jolig 2019-08-29 06:31:31

What if the callback does not work as you said? mine does not!

Related Questions

Sponsored Content

1 Answered Questions

[SOLVED] fetch data in react native from mlab

32 Answered Questions

[SOLVED] How do I update each dependency in package.json to the latest version?

6 Answered Questions

[SOLVED] Why calling react setState method doesn't mutate the state immediately?

0 Answered Questions

ModalFilterPicker load more on scroll

0 Answered Questions

`setState` in React portal containing a text input causes browser to scroll in Safari

1 Answered Questions

[SOLVED] setState changes state but doesn't re-render

  • 2017-09-18 15:23:15
  • user1932694
  • 1794 View
  • 3 Score
  • 1 Answer
  • Tags:   reactjs

1 Answered Questions

[SOLVED] Update React Grandparent State from onClick in Grandchild

1 Answered Questions

[SOLVED] How get value datapicker in react toobox custom?

  • 2017-06-05 18:14:51
  • Luiz Carlos Pedroso Gomes
  • 1016 View
  • 0 Score
  • 1 Answer
  • Tags:   reactjs react-toolbox

1 Answered Questions

[SOLVED] AboutHeader.jsx:21 Uncaught TypeError: this.setState is not a function

  • 2016-10-15 19:24:46
  • Devsterefic
  • 234 View
  • 1 Score
  • 1 Answer
  • Tags:   reactjs

Sponsored Content