I have a DayPicker
component that allows a user to select multiple dates. I store this data in an array of Date
objects that gets sent to the reducer when the user clicks next in a multistep form. However, if I return back to this form, I cannot add AND remove any dates. This is what my component looks like
class StepThree extends Component {
static getDerivedStateFromProps = (nextProps) => {
const {
stepThree: { dates }
} = nextProps;
const shouldUpdate = dates.length !== 0;
if (shouldUpdate) {
const newDates = dates.map(date => new Date(date));
return {
dates: newDates
};
}
return null;
};
state = {
dates: []
};
handleDayClick = (day, { selected }) => {
const { dates } = this.state;
if (selected) {
const selectedIndex = dates.findIndex(selectedDay => DateUtils.isSameDay(selectedDay, day));
dates.splice(selectedIndex, 1);
} else {
dates.push(day);
}
this.setState({ dates });
};
handleNext = (e) => {
e.preventDefault();
this.props.setStepThree(this.state.dates);
};
render() {
return (
<Col>
<Col style={{ textAlign: 'center' }}>
<DayPicker selectedDays={this.state.dates} onDayClick={this.handleDayClick} />
</Col>
<div
style={{
width: '100%',
position: 'fixed',
bottom: '0px',
zIndex: '100',
textAlign: 'center',
padding: '10px',
left: '0px'
}}
>
<PreviousButton handleClick={this.props.handlePrevious} />
<NextButton handleClick={this.handleNext} />
</div>
</Col>
);
}
}
When I return to this form, I see the new date being passed into the handleClick method, but it does not append to the array. The state remains the name.
NOTE: This is a reproducible pattern after the first time the user has filled the form. After the first time, this is basically uneditable.
This is the reducer code
case ACTIONS.SET_STEP_THREE: {
const newDates = action.dates.map(d => new Date(d));
return {
...state,
stepThree: {
...state.stepThree,
dates: newDates
}
};
}
Pushing or removing date to/ from dates array will not change its reference. you should recreate the dates array to update its reference and allow react to detect the changes of the component state. you can use any method to recreate the dates array exp : array.concat
or array.slice
or the Spread syntax let newDatesRf = [...dates];
handleDayClick = (day, { selected }) => {
const { dates } = this.state;
if (selected) {
const selectedIndex = dates.findIndex(selectedDay =>
DateUtils.isSameDay(selectedDay, day));
dates.splice(selectedIndex, 1);
} else {
dates.push(day);
}
let newDatesRf = [...dates];//copy dates array to a new array
this.setState({ dates:newDatesRf });
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.