Skip to content

Commit 7172f5a

Browse files
authored
Fix activeStartDate not being called on value change (#322)
* Fix activeStartDate not being called on value change Fixes #305 * Fix double setState, improve unit tests * Refactor, improve unit tests
1 parent e177d0a commit 7172f5a

File tree

2 files changed

+236
-65
lines changed

2 files changed

+236
-65
lines changed

src/Calendar.jsx

Lines changed: 82 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,8 @@ const getDetailValueArray = (args) => {
101101
return [getDetailValueFrom, getDetailValueTo].map(fn => fn(args));
102102
};
103103

104-
const getActiveStartDate = (props) => {
104+
function getActiveStartDate(props) {
105105
const {
106-
activeStartDate,
107-
defaultActiveStartDate,
108-
defaultValue,
109-
defaultView,
110106
maxDate,
111107
maxDetail,
112108
minDate,
@@ -115,33 +111,62 @@ const getActiveStartDate = (props) => {
115111
view,
116112
} = props;
117113

118-
const rangeType = getView(view || defaultView, minDetail, maxDetail);
114+
const rangeType = getView(view, minDetail, maxDetail);
119115
const valueFrom = (
120-
activeStartDate || defaultActiveStartDate
121-
|| getDetailValueFrom({
122-
value: value || defaultValue, minDate, maxDate, maxDetail,
116+
getDetailValueFrom({
117+
value, minDate, maxDate, maxDetail,
123118
})
124119
|| new Date()
125120
);
121+
126122
return getBegin(rangeType, valueFrom);
127-
};
123+
}
124+
125+
function getInitialActiveStartDate(props) {
126+
const {
127+
activeStartDate,
128+
defaultActiveStartDate,
129+
defaultValue,
130+
defaultView,
131+
maxDetail,
132+
minDetail,
133+
value,
134+
view,
135+
...otherProps
136+
} = props;
137+
138+
const rangeType = getView(view, minDetail, maxDetail);
139+
const valueFrom = activeStartDate || defaultActiveStartDate;
140+
141+
if (valueFrom) {
142+
return getBegin(rangeType, valueFrom);
143+
}
144+
145+
return getActiveStartDate({
146+
maxDetail,
147+
minDetail,
148+
value: value || defaultValue,
149+
view: view || defaultView,
150+
...otherProps,
151+
});
152+
}
128153

129154
const isSingleValue = value => value && [].concat(value).length === 1;
130155

131156
export default class Calendar extends Component {
132157
state = {
133158
/* eslint-disable react/destructuring-assignment */
134-
activeStartDate: getActiveStartDate(this.props),
135-
view: this.props.defaultView,
159+
activeStartDate: this.props.defaultActiveStartDate,
136160
value: this.props.defaultValue,
161+
view: this.props.defaultView,
137162
/* eslint-enable react/destructuring-assignment */
138163
};
139164

140165
get activeStartDate() {
141166
const { activeStartDate: activeStartDateProps } = this.props;
142167
const { activeStartDate: activeStartDateState } = this.state;
143168

144-
return activeStartDateProps || activeStartDateState;
169+
return activeStartDateProps || activeStartDateState || getInitialActiveStartDate(this.props);
145170
}
146171

147172
get value() {
@@ -220,37 +245,40 @@ export default class Calendar extends Component {
220245
});
221246
}
222247

223-
/**
224-
* Called when the user uses navigation buttons.
225-
*/
226-
setActiveStartDate = (activeStartDate) => {
227-
const { onActiveStartDateChange } = this.props;
248+
setStateAndCallCallbacks = (nextState, callback) => {
249+
const {
250+
onActiveStartDateChange, onChange, onViewChange, selectRange,
251+
} = this.props;
252+
253+
this.setState(nextState, () => {
254+
const args = {
255+
activeStartDate: nextState.activeStartDate || this.activeStartDate,
256+
view: nextState.view || this.view,
257+
};
258+
259+
if ('activeStartDate' in nextState) {
260+
callIfDefined(onActiveStartDateChange, args);
261+
}
262+
263+
if ('view' in nextState) {
264+
callIfDefined(onViewChange, args);
265+
}
228266

229-
this.setState({ activeStartDate }, () => {
230-
const { view } = this;
267+
if ('value' in nextState) {
268+
if (!selectRange || !isSingleValue(nextState.value)) {
269+
callIfDefined(onChange, nextState.value);
270+
}
271+
}
231272

232-
callIfDefined(onActiveStartDateChange, {
233-
activeStartDate,
234-
view,
235-
});
273+
callIfDefined(callback, args);
236274
});
237275
}
238276

239277
/**
240278
* Called when the user uses navigation buttons.
241279
*/
242-
setActiveStartDateAndView = (activeStartDate, view, callback) => {
243-
const { onActiveStartDateChange, onViewChange } = this.props;
244-
245-
this.setState({ activeStartDate, view }, () => {
246-
const args = {
247-
activeStartDate,
248-
view,
249-
};
250-
callIfDefined(onActiveStartDateChange, args);
251-
callIfDefined(onViewChange, args);
252-
callIfDefined(callback, args);
253-
});
280+
setActiveStartDate = (activeStartDate) => {
281+
this.setStateAndCallCallbacks({ activeStartDate });
254282
}
255283

256284
drillDown = (nextActiveStartDate, event) => {
@@ -265,7 +293,10 @@ export default class Calendar extends Component {
265293

266294
const nextView = views[views.indexOf(view) + 1];
267295

268-
this.setActiveStartDateAndView(nextActiveStartDate, nextView, onDrillDown);
296+
this.setStateAndCallCallbacks({
297+
activeStartDate: nextActiveStartDate,
298+
view: nextView,
299+
}, onDrillDown);
269300
}
270301

271302
drillUp = () => {
@@ -279,16 +310,18 @@ export default class Calendar extends Component {
279310
const nextView = views[views.indexOf(view) - 1];
280311
const nextActiveStartDate = getBegin(nextView, activeStartDate);
281312

282-
this.setActiveStartDateAndView(nextActiveStartDate, nextView, onDrillUp);
313+
this.setStateAndCallCallbacks({
314+
activeStartDate: nextActiveStartDate,
315+
view: nextView,
316+
}, onDrillUp);
283317
}
284318

285319
onChange = (value, event) => {
286-
const { onChange, selectRange } = this.props;
320+
const { selectRange } = this.props;
287321

288322
this.onClickTile(value, event);
289323

290324
let nextValue;
291-
let callback;
292325
if (selectRange) {
293326
// Range selection turned on
294327
const { value: previousValue, valueType } = this;
@@ -299,15 +332,21 @@ export default class Calendar extends Component {
299332
} else {
300333
// Second value
301334
nextValue = getValueRange(valueType, previousValue, value);
302-
callback = () => callIfDefined(onChange, nextValue);
303335
}
304336
} else {
305337
// Range selection turned off
306338
nextValue = this.getProcessedValue(value);
307-
callback = () => callIfDefined(onChange, nextValue);
308339
}
309340

310-
this.setState({ value: nextValue }, callback);
341+
const nextActiveStartDate = getActiveStartDate({
342+
...this.props,
343+
value: nextValue,
344+
});
345+
346+
this.setStateAndCallCallbacks({
347+
activeStartDate: nextActiveStartDate,
348+
value: nextValue,
349+
});
311350
}
312351

313352
onClickTile = (value, event) => {

0 commit comments

Comments
 (0)