Skip to content

Commit 16bff74

Browse files
authored
fix: do not update android dialog on each re-render (#374)
1 parent 9e91b9e commit 16bff74

File tree

1 file changed

+78
-51
lines changed

1 file changed

+78
-51
lines changed

src/datetimepicker.android.js

+78-51
Original file line numberDiff line numberDiff line change
@@ -29,85 +29,112 @@ function validateProps(props: AndroidNativeProps) {
2929
);
3030
}
3131

32-
export default function RNDateTimePicker(props: AndroidNativeProps) {
33-
validateProps(props);
34-
const {
35-
mode,
36-
value,
37-
display,
38-
onChange,
39-
is24Hour,
40-
minimumDate,
41-
maximumDate,
42-
neutralButtonLabel,
43-
minuteInterval,
44-
} = props;
45-
let picker;
46-
32+
function getPicker({
33+
mode,
34+
value,
35+
display,
36+
is24Hour,
37+
minimumDate,
38+
maximumDate,
39+
neutralButtonLabel,
40+
minuteInterval,
41+
}) {
4742
switch (mode) {
4843
case MODE_TIME:
49-
picker = pickers[MODE_TIME].open({
44+
return pickers[MODE_TIME].open({
5045
value,
5146
display,
5247
minuteInterval,
5348
is24Hour,
5449
neutralButtonLabel,
5550
});
56-
break;
57-
5851
case MODE_DATE:
5952
default:
60-
picker = pickers[MODE_DATE].open({
53+
return pickers[MODE_DATE].open({
6154
value,
6255
display,
6356
minimumDate,
6457
maximumDate,
6558
neutralButtonLabel,
6659
});
67-
break;
6860
}
61+
}
62+
63+
export default function RNDateTimePicker(props: AndroidNativeProps) {
64+
validateProps(props);
65+
const {
66+
mode,
67+
value,
68+
onChange,
69+
display,
70+
is24Hour,
71+
minimumDate,
72+
maximumDate,
73+
neutralButtonLabel,
74+
minuteInterval,
75+
} = props;
76+
const valueTimestamp = value.getTime();
6977

7078
useEffect(() => {
71-
// This effect runs on unmount, and will ensure the picker is closed.
79+
// This effect runs on unmount / with mode change, and will ensure the picker is closed.
7280
// This allows for controlling the opening state of the picker through declarative logic in jsx.
7381
return () => (pickers[mode] ?? pickers[MODE_DATE]).dismiss();
7482
}, [mode]);
7583

76-
picker.then(
77-
function resolve({action, day, month, year, minute, hour}) {
78-
const date = new Date(value);
79-
const event: AndroidEvent = {
80-
type: 'set',
81-
nativeEvent: {},
82-
};
84+
useEffect(
85+
function showOrUpdatePicker() {
86+
const picker = getPicker({
87+
mode,
88+
value: valueTimestamp,
89+
display,
90+
is24Hour,
91+
minimumDate,
92+
maximumDate,
93+
neutralButtonLabel,
94+
minuteInterval,
95+
});
8396

84-
switch (action) {
85-
case DATE_SET_ACTION:
86-
event.nativeEvent.timestamp = date.setFullYear(year, month, day);
87-
onChange(event, date);
88-
break;
97+
picker.then(
98+
function resolve({action, day, month, year, minute, hour}) {
99+
const date = new Date(valueTimestamp);
100+
const event: AndroidEvent = {
101+
type: 'set',
102+
nativeEvent: {},
103+
};
89104

90-
case TIME_SET_ACTION:
91-
event.nativeEvent.timestamp = date.setHours(hour, minute);
92-
onChange(event, date);
93-
break;
105+
switch (action) {
106+
case DATE_SET_ACTION:
107+
event.nativeEvent.timestamp = date.setFullYear(year, month, day);
108+
onChange(event, date);
109+
break;
94110

95-
case NEUTRAL_BUTTON_ACTION:
96-
event.type = 'neutralButtonPressed';
97-
onChange(event);
98-
break;
111+
case TIME_SET_ACTION:
112+
event.nativeEvent.timestamp = date.setHours(hour, minute);
113+
onChange(event, date);
114+
break;
99115

100-
case DISMISS_ACTION:
101-
default:
102-
event.type = 'dismissed';
103-
onChange(event);
104-
break;
105-
}
106-
},
107-
function reject(error) {
108-
// ignore or throw `activity == null` error
109-
throw error;
116+
case NEUTRAL_BUTTON_ACTION:
117+
event.type = 'neutralButtonPressed';
118+
onChange(event);
119+
break;
120+
121+
case DISMISS_ACTION:
122+
default:
123+
event.type = 'dismissed';
124+
onChange(event);
125+
break;
126+
}
127+
},
128+
function reject(error) {
129+
// ignore or throw `activity == null` error
130+
throw error;
131+
},
132+
);
110133
},
134+
// the android dialog, when presented, will actually ignore updates to all props other than `value`
135+
// we need to change the behavior as described in https://github.com/react-native-datetimepicker/datetimepicker/pull/327#issuecomment-723160992
136+
// eslint-disable-next-line react-hooks/exhaustive-deps
137+
[onChange, valueTimestamp, mode],
111138
);
112139

113140
return null;

0 commit comments

Comments
 (0)