javascriptreactjsrefreact-forwardrefcreate-ref

React using forwardRef always update child component even using memo


So I have a DatePicker ChildComponent that I need to access its ref via forwardRef from the Parent. Basically everything works fine.

But there's one problem.

Each time I update something on the Parent Other ChildComponents that has no any relation with DatePickerChild, the DatePicker is still rendering even it shouldn't be.

I tried to remove the passing of ref from parent to child then the component is not rerendering anymore each time I made an update to other components that I want to solve.

<NativeDatePicker
  ref={datePickerRef} // <-- When I comment this component is not rendering anymore.
  currentDate={values.birthday}
  onDateChange={handleBirthdayChange}
/>

I already started using callback memoization by using useCallback to optimize but still no luck.

Here is my code below:

DatePicker.tsx

type Props = {
  // ref: RefObject<DatePicker>;
  currentDate: string | Date | undefined;
  onDateChange: (newDate: string) => void;
};

const NativeDatePicker = forwardRef(
  ({ currentDate, onDateChange }: Props, ref: any) => {
    console.log('tadah!');
    return (
      <DatePicker
        ref={ref}
        style={wrapperStyle.wrapper}
        date={currentDate}
        mode="date"
        placeholder="select date"
        format="YYYY-MM-DD"
        // minDate="2016-05-01"
        // maxDate={Date.now()}
        confirmBtnText="Confirm"
        cancelBtnText="Cancel"
        customStyles={styles}
        onDateChange={onDateChange}
      />
    );
  },
);

const MemoizedNativeDatePicker = memo(NativeDatePicker);

I would not show every code in my ParentComponent only the props and refs I'm passing into the DatePicker.

 // Memoized Callback Function
 const handleBirthdayChange = useCallback(
    (newDate: string) => setFieldValue('birthday', newDate),
    [setFieldValue],
  );

 const datePickerRef = createRef<DatePicker>();
 const datePickerRefOnPress = () => datePickerRef.current!.onPressDate();

Am I missing something? Thanks for any help.


Solution

  • You are creating a ref using createRef, which on every re-render will return you a new ref instance and hence will lead to failure in optimization of child re-render with React.memo.

    You should instead useuseRef hook for a functional component to create a ref

    const datePickerRef = useRef<DatePicker>();