xgfe / react-native-datepicker

react native datePicker component for both Android and IOS, useing DatePikcerAndroid, TimePickerAndroid and DatePickerIOS
MIT License
2.12k stars 726 forks source link

Contamination of refs #352

Closed bneigher closed 5 years ago

bneigher commented 5 years ago

Issue

Pressing the mask with datePicker1Ref open is calling the onDateEndChange function

It appears that if you have multiple DatePicker components mounted they will not listen to functions called on their ref objects independently.

I'm noticing that always the lowest component in the DOM's ref always will operate its internal methods on rather than the ones set for its own component.

If I were to open the first instance, and then press the mask to trigger the ref onPressConfirm(), the onDateEndChange function will be called (which is on the onDateChange of the second component! WTF?

Expected Behavior

Pressing the mask with datePicker1Ref open should call the onDateStartChange function

Code

<DatePicker
     ref={ref => {
       this._datePicker1Ref = ref;
    }}
    onPressMask={()=> {
      this._datePicker1Ref.onPressConfirm();
    }}
    date={moment(props.startDate)}
    onDateChange={props.onDateStartChange}
    mode="datetime"
    minuteInterval={5}
    androidMode={"spinner"}
    format="h:mm A"
    placeholder={props.placeholder}
    confirmBtnText="Confirm"
    cancelBtnText="Cancel"
    allowFontScaling={false}
    adjustsFontSizeToFit={true}
    showIcon={false}
/>

<DatePicker
    ref={ref => {
      this._datePicker2Ref = ref;
    }}
    onPressMask={()=> {
      this._datePicker2Ref.onPressConfirm();
    }}
    placeholder="End Time"
    date={props.endDate ? moment(props.endDate) : null}
    onDateChange={props.onDateEndChange}
    mode="datetime"
    minuteInterval={5}
    androidMode={"spinner"}
    format="h:mm A"
    placeholder={props.placeholder}
    confirmBtnText="Confirm"
    cancelBtnText="Cancel"
    allowFontScaling={false}
    adjustsFontSizeToFit={true}
    showIcon={false}
/>

Note that the onPressMask function isn't being called on the second component, but the onPressConfirm() is being triggered on the datePicker2Ref

Environment

  1. react-native -v: 0.60.4
  2. node -v: 11.9.0
  3. npm -v: 6.7.0 ~4. yarn --version:~
  4. target platform: iOS
  5. operating system: Mac OS X 10.14.6
bneigher commented 5 years ago

Turned out to be an issue with using functional components. forwardRefs to the rescue