ref
- ref 只能当作所谓的应急门,如果系统中大部分的数据都依赖于 ref,系统状态可能需要重新思考。
- 不要在 render 过程做读写 ref,react 没有跟踪 ref 的能力,对它的读写会导致组件状态难以预测。
- ref 可以指向任何的值,不过大部分情况都是指向 DOM,方便 focus 一个 DOM,播放 video 组件,将某个元素滚动到屏幕中等操作。
访问子组件的 DOM
- 直接访问子组件的 DOM 元素不被允许。以下的代码会报 warning。
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
function MyInput(props) {
return <input {...props} />;
}
export default function MyForm() {
const inputRef = useRef(null);
return <MyInput ref={inputRef} />
}
直接访问其他组件的 DOM 被认为是脆弱的代码。可以通过 forwardRef
显示声明此组件暴露接口,允许外界组件访问内部的 DOM。
const MyInput = forwardRef((props, ref) => {
return <input {...props} ref={ref} />;
});
实际的应用中,底层的组件设计系统,例如 input, button 等组件,暴露内部的 DOM ,方便外部访问。而较高层的组件,例如 form,列表,页面等,一般不暴露内部的 DOM 引用,以防止内部 DOM 结构变化导致接口不兼容。
React 挂载在 ref 的时机
在 React 中,所有的更新都分为两个阶段:
- render ,React 调用组件,计算出页面上应该有什么。
- commit, React 将变化实施在 DOM 上。
所以在 render 过程中,不建议访问 ref。如果 ref 指向 DOM,第一次 render 时,它是 null,后续更新时,由于 DOM 还没有更新,它指向的是尚未更新的 DOM。
React 在 commit 时设置 ref.current。在更新 DOM 以后,React 会立即把 ref.current 挂载在对应的 DOM 元素上。
使用 Ref 的最佳实践
ref 是所谓的应急门,应该在与 React 意外的系统交互时使用。在执行无破坏性的操作,例如聚焦、滚动页面时,没有任何问题。但是如果直接手动改变 DOM ,可能会跟 React 正在执行的变化冲突。
网友评论