useImperativeHandle 是一个 React Hook,它允许你自定义作为 ref. 暴露的句柄
useImperativeHandle(ref, createHandle, dependencies?)参考
🌐 Reference
useImperativeHandle(ref, createHandle, dependencies?)
在组件的顶层调用 useImperativeHandle 来自定义它暴露的 ref 句柄:
🌐 Call useImperativeHandle at the top level of your component to customize the ref handle it exposes:
import { useImperativeHandle } from 'react';
function MyInput({ ref }) {
useImperativeHandle(ref, () => {
return {
// ... your methods ...
};
}, []);
// ...参数
🌐 Parameters
ref:MyInput组件接收到的ref属性。createHandle:一个不带参数并返回你想要公开的引用句柄的函数。该引用句柄可以是任何类型。通常,你会返回一个包含你想要公开的方法的对象。- 可选
dependencies:在createHandle代码中引用的所有响应式值的列表。响应式值包括 props、state,以及直接在组件体内声明的所有变量和函数。如果你的 linter 为 React 配置 ,它将验证每个响应式值是否已正确指定为依赖。依赖列表必须有固定数量的项目,并且像[dep1, dep2, dep3]一样以内联形式书写。React 将使用Object.is比较将每个依赖与之前的值进行比较。如果重新渲染导致某些依赖发生变化,或者你省略了该参数,你的createHandle函数将重新执行,并且新创建的句柄将分配给 ref。
返回
🌐 Returns
useImperativeHandle 返回 undefined。
用法
🌐 Usage
向父组件公开自定义引用句柄
🌐 Exposing a custom ref handle to the parent component
要将 DOM 节点暴露给父元素,请将 ref 属性传入该节点。
🌐 To expose a DOM node to the parent element, pass in the ref prop to the node.
function MyInput({ ref }) {
return <input ref={ref} />;
};使用上面的代码,对 MyInput 的引用将接收 <input> DOM 节点。 但是,你可以暴露一个自定义值。要自定义暴露的句柄,请在组件的顶层调用 useImperativeHandle:
🌐 With the code above, a ref to MyInput will receive the <input> DOM node. However, you can expose a custom value instead. To customize the exposed handle, call useImperativeHandle at the top level of your component:
import { useImperativeHandle } from 'react';
function MyInput({ ref }) {
useImperativeHandle(ref, () => {
return {
// ... your methods ...
};
}, []);
return <input />;
};请注意,在上面的代码中,ref 不再传递给 <input>。
🌐 Note that in the code above, the ref is no longer passed to the <input>.
例如,假设你不想暴露整个 <input> DOM 节点,但你想暴露它的两个方法:focus 和 scrollIntoView。为此,将真实的浏览器 DOM 保存在一个单独的 ref 中。然后使用 useImperativeHandle 暴露一个只包含你希望父组件调用的方法的句柄:
🌐 For example, suppose you don’t want to expose the entire <input> DOM node, but you want to expose two of its methods: focus and scrollIntoView. To do this, keep the real browser DOM in a separate ref. Then use useImperativeHandle to expose a handle with only the methods that you want the parent component to call:
import { useRef, useImperativeHandle } from 'react';
function MyInput({ ref }) {
const inputRef = useRef(null);
useImperativeHandle(ref, () => {
return {
focus() {
inputRef.current.focus();
},
scrollIntoView() {
inputRef.current.scrollIntoView();
},
};
}, []);
return <input ref={inputRef} />;
};现在,如果父组件获取了对 MyInput 的引用,它将能够调用其上的 focus 和 scrollIntoView 方法。然而,它将无法完全访问底层的 <input> DOM 节点。
🌐 Now, if the parent component gets a ref to MyInput, it will be able to call the focus and scrollIntoView methods on it. However, it will not have full access to the underlying <input> DOM node.
import { useRef } from 'react'; import MyInput from './MyInput.js'; export default function Form() { const ref = useRef(null); function handleClick() { ref.current.focus(); // This won't work because the DOM node isn't exposed: // ref.current.style.opacity = 0.5; } return ( <form> <MyInput placeholder="Enter your name" ref={ref} /> <button type="button" onClick={handleClick}> Edit </button> </form> ); }
公开你自己的命令式方法
🌐 Exposing your own imperative methods
通过命令式句柄暴露的方法不必与 DOM 方法完全匹配。例如,这个 Post 组件通过命令式句柄暴露了一个 scrollAndFocusAddComment 方法。这让父组件 Page 在点击按钮时既可以滚动评论列表,也可以聚焦输入字段:
🌐 The methods you expose via an imperative handle don’t have to match the DOM methods exactly. For example, this Post component exposes a scrollAndFocusAddComment method via an imperative handle. This lets the parent Page scroll the list of comments and focus the input field when you click the button:
import { useRef } from 'react'; import Post from './Post.js'; export default function Page() { const postRef = useRef(null); function handleClick() { postRef.current.scrollAndFocusAddComment(); } return ( <> <button onClick={handleClick}> Write a comment </button> <Post ref={postRef} /> </> ); }