Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
215 views
in Technique[技术] by (71.8m points)

reactjs - React Datepicker

I'm trying to create small calendar calculator which subtracts two dates and give amount of days.

For that I've chosen library react-datepicker.

Now I have a problem that state updates one click after. This means that when I choose date 2nd time I get result for the previous one.

Also, I can't understand why when I uncomment ...this.state for saving immutability of state it stops updating.

There is my code

import React, { Component } from 'react';
import DatePicker from 'react-datepicker';
import moment from 'moment';

import 'react-datepicker/dist/react-datepicker.css';
import CalendarInput from '../../UI/CalendarInput/CalendarInput';

class CalendarPage extends Component {
  constructor(props) {
    super(props);
    this.state = {
      startDate: moment(),
      endDate: moment(),
      days: 0
    };
    this.handleChangeEnd = this.handleChangeEnd.bind(this);
    this.handleChangeStart = this.handleChangeStart.bind(this);
    this.daysLeft = this.daysLeft.bind(this);
  }

  daysLeft() {
    let {startDate, endDate} = this.state;
    console.log(startDate);
    console.log(endDate);
    let amount = endDate.diff(startDate, 'days');
    this.setState({
      // ...this.state,
      days: amount
    });
  }

  handleChangeStart(date) {
    this.setState({
      // ...this.state,
      startDate: date
    });
    this.daysLeft();
  }

  handleChangeEnd(date) {
    this.setState({
      // ...this.state,
      endDate: date
    });
    this.daysLeft();
  }

  render() {
    return (
      <div>
        <h2 className="pl-2 mb-4">
          Calendar
        </h2>

        <div className="row no-gutters calculator-container">
          <DatePicker
            selected={this.state.startDate}
            selectsStart
            startDate={this.state.startDate}
            endDate={this.state.endDate}
            onChange={this.handleChangeStart}
            customInput={<CalendarInput label="departure"/>}
          />

          <DatePicker
            selected={this.state.endDate}
            selectsEnd
            startDate={this.state.startDate}
            endDate={this.state.endDate}
            onChange={this.handleChangeEnd}
            customInput={<CalendarInput label="arrival"/>}
          />

          <div className="amount">
            {this.state.days}
          </div>
        </div>

      </div>
    );
  }
}

export default CalendarPage;
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You are making multiple calls to setState within one cycle, and referencing this.state within the same cycle. setState does not guarantee to update the state object when you call it, but at some later time.

Therefore, your calls to this.daysLeft() will be accessing the prior state, not the one you expected as a result of the setState call.

setState has two modes, one to provide an object which is shallow merged at a later time, another a callback function which is called when state can be updated. You may need to use the latter form so that you can guarantee that state changes are done in sequence. If you read the docs, the latter is actually the preferred mode, the object form is for convenience in simplistic code paths, and historically I think has found its way into a lot of tutorials, which leads to confusion.

React setState docs

See if this helps and come back if you modify your code and still have problems. Post your amended code if you do.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...