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;
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.
See if this helps and come back if you modify your code and still have problems. Post your amended code if you do.