0

我正在尝试创建减去两个日期并给出天数的小型日历计算器。

为此,我选择了 library react-datepicker

现在我遇到了state一个点击后更新的问题。这意味着当我第二次选择日期时,我会得到前一个日期的结果。

另外,我不明白为什么当我取消注释...this.state以保存它的不变性时state会停止更新。

有我的代码

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;
4

2 回答 2

1

您在一个周期内进行多次调用,并在同setState一个周期内进行引用this.statesetState不保证在您调用它时更新状态对象,但在稍后的某个时间。

因此,您的调用this.daysLeft()将访问先前的状态,而不是您期望的setState调用结果。

setState有两种模式,一种是提供一个稍后浅合并的对象,另一种是在状态可以更新时调用的回调函数。您可能需要使用后一种形式,以便保证状态更改是按顺序完成的。如果您阅读文档,后者实际上是首选模式,对象形式是为了方便简化代码路径,并且从历史上看,我认为已经在很多教程中找到了它,这会导致混乱。

反应 setState 文档

看看这是否有帮助,如果您修改代码并且仍然有问题,请返回。如果您这样做,请发布您修改后的代码。

于 2018-04-15T16:32:52.063 回答
0

来自文档:

React 可以将多个 setState() 调用批处理到单个更新中以提高性能。

意思就是:

handleChangeStart(date) {
  // this update will not be executed directly...
  this.setState({
    startDate: date
  });
  this.daysLeft();
}

daysLeft() {
    // previous setState didn't yet take effect, so we access an old startDate
    let {startDate, endDate} = this.state; 
    console.log(startDate);
    console.log(endDate);
    let amount = endDate.diff(startDate, 'days');
    this.setState({
      days: amount
    });
}

您可以通过以下方式修复它:

handleChangeStart(date) {
  this.setState(prevState => {
    return { 
      startDate: date,
      days: this.daysLeft(date, prevState.endDate),
    }
  });
}

daysLeft(startDate, endDate) {
  return endDate.diff(startDate, 'days');
}
于 2018-04-15T16:38:19.337 回答