
规则:refs
ReactAPI 参考:ESLint 插件
规则:refs
校验 refs 的正确用法,即不要在渲染期间读取或写入。参见 useRef() 用法 中的“陷阱”部分。
规则详情
Refs 保存的值不用于渲染。与 state 不同,更改 ref 不会触发重新渲染。在渲染期间读取或写入 ref.current 会破坏 React 的预期。当你尝试读取 refs 时,它们可能尚未初始化,其值可能是过期的或不一致的。
如何检测 refs
该 lint 仅将规则应用于它已知是 ref 的值。当编译器看到以下任一模式时,该值被推断为 ref:
-
从
useRef()或React.createRef()返回。jsconst scrollRef = useRef(null); -
一个名为
ref或以Ref结尾的标识符,读取或写入.current。jsbuttonRef.current = node; -
通过 JSX
refprop 传递(例如<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.current 和 fooRef.current 视为真正的 refs。如果你正在建模自定义容器对象,请选择不同的名称(例如 box)或将可变值移入 state。重命名可以避免 lint,因为编译器不再将其推断为 ref。
帮助我们改进文档
发现翻译问题或内容错误?请告诉我们。
