Skip to main content

谈谈 useImperativeHandle

是什么

  1. useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。
  2. 在大多数情况下,应当避免使用 ref 这样的命令式代码。
  3. useImperativeHandle 应当与 forwardRef 一起使用

怎么用

预览地址

import React, {
useState,
useRef,
useImperativeHandle,
useCallback
} from "react";

// 子组件
const Child = React.forwardRef((props, ref) => {
const [fresh, setFresh] = useState(false);
const attRef = useRef(0);

// 根据 fresh 是否展示最新 ref,而不是总是最新值
useImperativeHandle(
ref,
() => ({
attRef,
fresh
}),
[fresh] // 依赖
);

const handleClick = useCallback(() => {
attRef.current++;
}, []);

return (
<div>
{attRef.current}
<button onClick={handleClick}>Fancy</button>
<button onClick={() => setFresh(!fresh)}>刷新</button>
</div>
);
});

// 父组件
const App = (props) => {
const fancyInputRef = useRef();

return (
<div>
<Child ref={fancyInputRef} />
<button onClick={() => console.log(fancyInputRef.current)}>
父组件访问子组件的实例属性
</button>
</div>
);
};

export default App;

解决了什么

  1. 正常情况下 ref 是不能挂在到函数组件上的,因为函数组件没有实例,但是 useImperativeHandle 为我们提供了一个类似实例的东西。
  2. 它帮助我们通过 useImperativeHandle 的第 2 个参数,控制是否更新 返回的对象的内容挂载到 父组件的 ref.current 上。

参考文章