返回
函数式组件之ref解决方案:在 Hooks 中保存引用
前端
2023-09-18 06:19:54
对于 React 中需要强制修改子组件的情况,React 提供了 Refs 这种解决办法,使得我们可以操作底层 DOM 元素或者自定的 class 组件实例。除此之外,文档(v17.0.1)对函数式组件另有不能在函数式组件上使用ref属性,因为他们没有实例。
在函数式组里,想要给子元素添加一个引用,我们没有办法直接给他挂载一个ref,因为它会报错。但是我们可以把 ref 的值放入一个父组件的变量之中。以下是使用 Hooks 来保存引用的步骤:
- 使用
useCallback
创建一个引用函数。 - 将引用函数作为回调函数传递给子组件。
- 在子组件中,将引用函数用于
useEffect
或useImperativeHandle
中。
// 父组件
const Parent = () => {
const ref = useRef();
const setRef = useCallback((node) => {
ref.current = node;
}, []);
return (
<div>
<Child ref={setRef} />
</div>
);
};
// 子组件
const Child = React.forwardRef((props, ref) => {
useEffect(() => {
// 在组件挂载时,将 ref 的值存储在当前组件的实例中。
ref.current = ReactDOM.findDOMNode(this);
}, []);
return <div>我是子组件</div>;
});
useCallback
用于创建引用函数,并且当 ref 的值改变时,会返回一个新的引用函数。因此,在父组件中,useCallback
的第二个参数是一个空数组,这表明引用函数在整个组件的生命周期中保持不变。
useRef
用于创建一个引用对象,并将其存储在父组件的状态中。引用对象是可变的,因此我们可以通过 ref.current
来访问底层的 DOM 元素或组件实例。
将引用函数作为回调函数传递给子组件,使子组件能够访问该函数。在子组件中,将引用函数用于 useEffect
或 useImperativeHandle
中,以便在组件挂载时将 ref 的值存储在组件的实例中。
需要注意的是,在函数式组件中,我们不能使用 this
来访问组件的实例,因此我们需要使用 useImperativeHandle
来暴露一个公共的 API。
这样,我们就可以在函数式组件中使用 ref 来操作子组件了。