知海

规则:refs

ReactAPI 参考:ESLint 插件

规则:refs

校验 refs 的正确用法,即不要在渲染期间读取或写入。参见 useRef() 用法 中的“陷阱”部分。

规则详情

Refs 保存的值不用于渲染。与 state 不同,更改 ref 不会触发重新渲染。在渲染期间读取或写入 ref.current 会破坏 React 的预期。当你尝试读取 refs 时,它们可能尚未初始化,其值可能是过期的或不一致的。

如何检测 refs

该 lint 仅将规则应用于它已知是 ref 的值。当编译器看到以下任一模式时,该值被推断为 ref:

  • useRef()React.createRef() 返回。

    js 复制代码
    const scrollRef = useRef(null);
  • 一个名为 ref 或以 Ref 结尾的标识符,读取或写入 .current

    js 复制代码
    buttonRef.current = node;
  • 通过 JSX ref prop 传递(例如 <div ref={someRef} />)。

    jsx 复制代码
    <input ref={inputRef} />

一旦某个值被标记为 ref,该推断会通过赋值、解构或辅助函数调用跟踪该值。这使 lint 即使在另一个接收 ref 作为参数的函数中访问 ref.current 时也能发现违规。

常见违规

  • 在渲染期间读取 ref.current
  • 在渲染期间更新 refs
  • 将本应为 state 的值使用 refs

无效

此规则的不正确代码示例:

js 复制代码
// ❌ Reading ref during render
function Component() {
  const ref = useRef(0);
  const value = ref.current; // Don't read during render
  return <div>{value}</div>;
}

// ❌ Modifying ref during render
function Component({value}) {
  const ref = useRef(null);
  ref.current = value; // Don't modify during render
  return <div />;
}

有效

此规则的正确代码示例:

js 复制代码
// ✅ Read ref in effects/handlers
function Component() {
  const ref = useRef(null);

  useEffect(() => {
    if (ref.current) {
      console.log(ref.current.offsetWidth); // OK in effect
    }
  });

  return <div ref={ref} />;
}

// ✅ Use state for UI values
function Component() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      {count}
    </button>
  );
}

// ✅ Lazy initialization of ref value
function Component() {
  const ref = useRef(null);

  // Initialize only once on first use
  if (ref.current === null) {
    ref.current = expensiveComputation(); // OK - lazy initialization
  }

  const handleClick = () => {
    console.log(ref.current); // Use the initialized value
  };

  return <button onClick={handleClick}>Click</button>;
}

故障排查

lint 标记了我带有 .current 的普通对象

命名启发式有意将 ref.currentfooRef.current 视为真正的 refs。如果你正在建模自定义容器对象,请选择不同的名称(例如 box)或将可变值移入 state。重命名可以避免 lint,因为编译器不再将其推断为 ref。

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。