2

I would like to update the state of a component when a date is selected from the React-DatePicker. I am getting some odd behavior below.

Example of Current Behavior:

  1. Component loads with empty date field
  2. I select 3/28/2017 and get the following console log

    main.ffde8a1f.js:8 it changed dates

    main.ffde8a1f.js:8 date = 1490673600000

    main.ffde8a1f.js:8 dueDate value =

  3. Say then I select 3/22/2017 and get the following console log:

    main.ffde8a1f.js:8 it changed dates

    main.ffde8a1f.js:8 date = 1490155200000

    main.ffde8a1f.js:8 dueDate value = 1490673600000

The second and third logs should have the same value. Can anyone explain to me why this weird behavior is occurring?

MY ATTEMPT

Imports

import React from 'react';
import DatePicker from 'react-datepicker';
import moment from 'moment';
import 'react-datepicker/dist/react-datepicker.css';

Component

I set the state of dueDate to '' to begin.

export default class Request extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      dueDate: '',
    }

    this.handleChangeDate = this.handleChangeDate.bind(this);

  }

Handle Date Selection

ISSUE My handleChangeDate function will fire when a date is provided and the date in milliseconds will log to the console, but the dueDate is logged as being the previous value it should have been.

 handleChangeDate(date) {
    console.log("it changed dates");
    console.log('date = ' + date);  //date in milliseconds logs properly
    this.setState({
      dueDate: date
    });
    console.log('dueDate value = ' + this.state.dueDate);  //date from state logs the previous value rather than its new value
  }

Render
I am keeping the date picker simple at the moment to minimize potential bugs. Only the selected date is passed in from the state and the handleChangeDate method for a selected date.

  render() {
    return (
      <div className="requestDetails">
        <h2>Due Date</h2>
        <DatePicker
           selected={this.state.dueDate}
           onChange={this.handleChangeDate}
        />
      </div>
    );
  }
}
Rbar
  • 3,740
  • 9
  • 39
  • 69
  • 1
    see this ans. http://stackoverflow.com/questions/30782948/why-calling-react-setstate-method-doesnt-mutate-the-state-immediately – Sumit R Mar 30 '17 at 22:38

2 Answers2

1

this.setState is not guaranteed to be synchronous, because they can be processed in batches. This means that although you call console.log in your code after your setState, the state may not have actually changed yet.

From the 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.

If you would like to check if your state is updated, you can either used a callback as the second argument to setState or put some logic in the shouldComponentUpdate(nextProps, nextState) lifecycle method.

Example:

handleChangeDate(date) {
  this.setState({
    dueDate: date
  }, () => console.log(this.state.dueDate)); // This will show the updated state when state is set.
}

or

shouldComponentUpdate(nextProps, nextState) {
  if (this.state.dueDate !== nextState.dueDate) {
    console.log('dueDate:  ', nextState.dueDate);
  }
}

setState Documentation: (Note the function signature, setState(nextState, callback))

https://facebook.github.io/react/docs/react-component.html#setstate

shouldComponentUpdate Documentation:

https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate

Yo Wakita
  • 5,322
  • 3
  • 24
  • 36
  • Huge help! This is great for me to keep in mind for all implementations of setState and logging to make sure it change. Very reusable. Thanks! – Rbar Mar 31 '17 at 18:01
-1
shouldDidUpdate(nextProps, nextState) {
        if (this.state.startDate !== nextState.startDate) {
            return true;
        }
        return true;
    }

Use your date in place of startDate

  • 1
    What is the purpose of this method? It only returns `true` in all the cases. Do you mean that some code has to be but in one of the `if` branches? – Dmitriy Popov Jul 02 '19 at 09:17