弹窗组件 Visible 参数的性能优化

2023-06-19

今天在群里面发了一下使用 forwardRef 优化 React 组件性能的一个对比,结果遭到大佬吐槽了。@咲奈 大佬说 forwardRef 一般都是组件库才会去使用。

forwardRef 不要在非组件库的项目里出现,因为其他的 props 也能传 ref,传下去挂方法就行了,写 forwardRef 还会造成大量模板代码和冗余 Type 的传递和书写

我继续追问,他并没有继续细说。结果 @Innei 他给我甩出了他的 Jotai,不得不说,它的原子化状态管理机制在控制组件单个 Visible 状态的这种场景,看上去是挺好用的。

状态管理的优势,主要在于不需要修改寄托于父组件的状态,即可让子的状态刷新,减少 Diff 成本,从而达到性能优化。前面我也提到过,Zustand 也是类似的东西。只是它更偏向于一组数据的同时维护,而不是单个单个的。只要使用了状态管理,至少可以在任意一个祖先或是同级组件操作,比 Provider 还是 forwardRef 都要更加方便。

function Parent() {
  const setDrawerVisible = useSetDrawerVisible();

  return (
    <A />
    <Drawer />
  );
}

const drawerVisible = atom(false);

function Drawer() {
  const [visible, setVisible] = useAtom(drawerVisible);

  return (
    <Drawer visible={visible} onClose={() => setVisible(false)} />
  );
}

const useSetDrawerVisible = () => useSetAtom(drawerVisible);

forwardRef 作为 React 内置的方法,通用性比较好,没有额外依赖。它虽然对于性能优化也挺好用,但它的缺点也比较明显。首先需要单独导出类型定义给父组件,还需要寄托一个 useRef 在父组件上。如果想要让同级组件修改它的状态,还需要该同级组件提供一个 Props 用于调用父组件的方法。

function Parent() {
  const drawerRef = useRef<DrawerInst>(null);

  return (
    <A onToggleDrawer={() => drawerRef.current?.toggle()} />
    <Drawer ref={drawerRef} />
  );
}

其他琐碎事也记录一下吧:

  • 更新了相册,内容是 2022 年 4 月的照片
  • 我的 iPad 依旧没有音讯,再等一个星期看看吧
  • 消失的租客终于有了后续,说是盗刷信用卡被抓派出所了

    • 我只能说,牛
  • 观看了 @Innei 直播,没学到啥,偷他的歌倒是真的
ぎゅっとして欲しいんだ 小雨 一般
概览页 时间轴
奇趣音乐盒 技术源于 Kico Player
Emmm,这里是歌词君