越是漂亮的女人越会骗人,react 19 也是。

越是漂亮的女人越会骗人

大家好,我是芋仔,距离 react 19 发布已经过去一个月了,移除了一些废弃语法,其中,让开发体验拉满的,应该是 ref 作为一个常驻参数的改动了。

ref as a prop

看到更新日志中前面几条,几乎是无感,而看到这一条,可算是不需要 forwardRef 这个玩意包裹了,可谓是方便很多。当场决定升级!

但是玫瑰都带刺。

可以看如下代码:

import { useRef, useEffect } from 'react'

const SomeComponent = ({
  style,
  ...props
}) => {
  const divRef = useRef(null)
  useEffect(() => {
    // do something with divRef.current
    // divRef.current 是 null
  }, [])
  return (
    <div style={style} ref={divRef} {...props} />
  )
}

const App = () => {
  const myRef = useRef(null)
  return (
    <SomeComponent ref={myRef} style={{}}/>
  )
}

以往这么写是没有问题的,但是当 ref 作为一个参数之后,...props 中就可能会包含一个 ref 参数(如果外面组件恰好也传递了ref参数),从而覆盖 divRef,从而导致 divRef 不会被赋值。

知道原因后,要做调整其实也非常简单

  //<div style={style} ref={divRef} {...props} />
  <div style={style} {...props} ref={divRef} />

调整参数位置即可。

就这?

说到这里,肯定有人要划走了,就这,这就栽跟头了?多大点事。

如果仅仅是这样,我也不会做记录了。

实际这些 bug,发生在我依赖的组件库中。

而组件库中的代码,是已经经过了 babel 编译的代码,可以感受下上述代码经过 jsx 编译后的结果:

import { useRef, useEffect } from 'react';
import { jsx as _jsx } from "react/jsx-runtime";
var SomeComponent = function SomeComponent(_ref) {
  var style = _ref.style,
    props = _objectWithoutProperties(_ref, _excluded);
  var divRef = useRef(null);
  useEffect(function () {
    // do something with divRef.current
    // divRef.current 是 null
  }, []);
  return /*#__PURE__*/_jsx("div", _objectSpread({
    style: style,
    ref: divRef
  }, props));
};

从代码上,是不太好推断出来这是 ref 位置写法带来的问题。甚至会怀疑,自己学的 jsx 的编译是不是正确的了。

再来看看正确写法编译后的结果:

var OkComponent = function OkComponent(_ref2) {
  var style = _ref2.style,
    props = _objectWithoutProperties(_ref2, _excluded2);
  var divRef = useRef(null);
  useEffect(function () {
    // do something with divRef.current
    // divRef.current 是 可以获取到的
  }, []);
  return /*#__PURE__*/_jsx("div", _objectSpread(_objectSpread({
    style: style
  }, props), {}, {
    ref: divRef
  }));
};

可以说是相当隐晦了。

不过还好,也算是吃到螃蟹了,其他地方暂时还没有发现比较隐晦的 bug,这篇文章也希望能帮助大家少走一些弯路。各组件库作者也可以稍稍留意喽。

最后,别忘了关注我公众号:程序员芋仔。每周(也可能每月)更新一篇程序员大佬分析。

后互联网时代,我也组建了一个前端抱团取暖群,欢迎加我微信来撩:mxb151,加群备注简单的自我介绍和加群哦。