使用 forwardRef 反应总是更新子组件,即使使用备忘录

Posted

技术标签:

【中文标题】使用 forwardRef 反应总是更新子组件,即使使用备忘录【英文标题】:React using forwardRef always update child component even using memo 【发布时间】:2020-10-04 17:24:03 【问题描述】:

所以我有一个 DatePicker ChildComponent,我需要通过 ParentforwardRef 访问它的ref。基本上一切正常。

但是有一个问题。

每次我在父 Other ChildComponents 上更新与 DatePickerChild 没有任何关系的内容时, DatePicker 仍在渲染,即使它不应该渲染。

我尝试删除 ref 从父级到子级的传递,然后每次我对要解决的其他组件进行更新时,该组件都不再重新渲染。

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

我已经开始使用回调记忆,通过使用useCallback 进行优化,但仍然没有运气。

下面是我的代码:

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);

我不会只显示我的 ParentComponent 中的所有代码,只显示我传递给 DatePicker 的 props 和 refs。

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

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

我错过了什么吗?感谢您的帮助。

【问题讨论】:

【参考方案1】:

您正在使用createRef 创建一个引用,在每次重新渲染时都会返回一个新的引用实例,因此将导致使用React.memo 优化子重新渲染失败。

您应该改为使用useRef 钩子作为功能组件来创建引用

const datePickerRef = useRef<DatePicker>();

【讨论】:

很高兴有帮助:-)

以上是关于使用 forwardRef 反应总是更新子组件,即使使用备忘录的主要内容,如果未能解决你的问题,请参考以下文章

useCallBack,useMemo,forwardRef,useImperativeHandle用法总结

React中React.forwardRef的使用方式

React hook 中connect和forwardRef连用会导致传入子组件的ref失效

createRef和useRef区别——useRef的使用——forwardRef完成类组件的绑定—— useImperativeHandle——映射ref对象——更新同步

createRef和useRef区别——useRef的使用——forwardRef完成类组件的绑定—— useImperativeHandle——映射ref对象——更新同步

React中父组件如何调用子组件的方法?useImperativeHandle就够了,原理级详解