- ReactJS 教程
- ReactJS - 首页
- ReactJS - 简介
- ReactJS - 路线图
- ReactJS - 安装
- ReactJS - 特性
- ReactJS - 优点与缺点
- ReactJS - 架构
- ReactJS - 创建 React 应用
- ReactJS - JSX
- ReactJS - 组件
- ReactJS - 嵌套组件
- ReactJS - 使用新创建的组件
- ReactJS - 组件集合
- ReactJS - 样式
- ReactJS - 属性 (props)
- ReactJS - 使用属性创建组件
- ReactJS - props 验证
- ReactJS - 构造函数
- ReactJS - 组件生命周期
- ReactJS - 事件管理
- ReactJS - 创建一个事件感知组件
- ReactJS - 在 Expense Manager APP 中引入事件
- ReactJS - 状态管理
- ReactJS - 状态管理 API
- ReactJS - 无状态组件
- ReactJS - 使用 React Hooks 进行状态管理
- ReactJS - 使用 React Hooks 进行组件生命周期管理
- ReactJS - 布局组件
- ReactJS - 分页
- ReactJS - Material UI
- ReactJS - Http 客户端编程
- ReactJS - 表单编程
- ReactJS - 受控组件
- ReactJS - 非受控组件
- ReactJS - Formik
- ReactJS - 条件渲染
- ReactJS - 列表
- ReactJS - Keys
- ReactJS - 路由
- ReactJS - Redux
- ReactJS - 动画
- ReactJS - Bootstrap
- ReactJS - Map
- ReactJS - 表格
- ReactJS - 使用 Flux 管理状态
- ReactJS - 测试
- ReactJS - CLI 命令
- ReactJS - 构建和部署
- ReactJS - 示例
- Hooks
- ReactJS - Hooks 简介
- ReactJS - 使用 useState
- ReactJS - 使用 useEffect
- ReactJS - 使用 useContext
- ReactJS - 使用 useRef
- ReactJS - 使用 useReducer
- ReactJS - 使用 useCallback
- ReactJS - 使用 useMemo
- ReactJS - 自定义 Hooks
- ReactJS 高级
- ReactJS - 可访问性
- ReactJS - 代码分割
- ReactJS - Context
- ReactJS - 错误边界
- ReactJS - 转发 Refs
- ReactJS - 片段
- ReactJS - 高阶组件
- ReactJS - 与其他库集成
- ReactJS - 性能优化
- ReactJS - Profiler API
- ReactJS - Portals
- ReactJS - 无 ES6 ECMAScript 的 React
- ReactJS - 无 JSX 的 React
- ReactJS - Reconciliation (协调)
- ReactJS - Refs 和 DOM
- ReactJS - Render Props
- ReactJS - 静态类型检查
- ReactJS - Strict Mode (严格模式)
- ReactJS - Web Components
- 附加概念
- ReactJS - 日期选择器
- ReactJS - Helmet
- ReactJS - 内联样式
- ReactJS - PropTypes
- ReactJS - BrowserRouter
- ReactJS - DOM
- ReactJS - 轮播图
- ReactJS - 图标
- ReactJS - 表单组件
- ReactJS - 参考 API
- ReactJS 有用资源
- ReactJS - 快速指南
- ReactJS - 有用资源
- ReactJS - 讨论
ReactJS - useImperativeHandle Hook
useImperativeHandle 是 React 18 中引入的一个 React Hook。这个 Hook 允许我们自定义作为子组件 ref 公开的句柄。当我们需要立即与子组件连接时,这非常有用,这意味着我们希望立即访问和调用子组件上的方法或属性。
语法
useImperativeHandle(ref, createHandle, optional_dependency)
参数
ref − 这是一种特殊的工具,可以帮助我们与子组件连接。在使用 forwardRef 创建子组件时,它作为第二个参数接收。
createHandle − 这是关于我们想要对子组件执行的操作的指令集。这是我们从 useImperativeHandle 返回的内容。
可选 _dependencies − 我们需要列出我们在 createHandle 部分中使用的所有内容(例如 props、state 和变量)。这样 React 就会检查这些内容,并确保它们不会意外更改。如果它们确实更改了,它将更新我们的特殊工具。
返回值
此方法返回 undefined。
如何使用它?
我们可以在组件的顶层使用 “useImperativeHandle” 来自定义它公开的 ref 句柄 −
import { forwardRef, useImperativeHandle } from 'react'; const MyComp = forwardRef(function MyComp(props, ref) { useImperativeHandle(ref, () => { return { // the methods we want in our code ... }; }, []);
示例
因此,我们可以通过两种不同的方式使用此 Hook。首先是创建可用于父组件的自定义 ref 句柄,其次是公开我们自己的指令式方法。我们将进一步逐一讨论这两种方法。
向父组件提供自定义 ref 句柄
默认情况下,React 组件不提供对底层 DOM 元素的直接访问。我们将不得不使用 forwardRef 来允许父组件访问子组件中的 <input> DOM 节点。
import { forwardRef } from 'react'; const InputComp = forwardRef(function InputComp(props, ref) { return <input {...props} ref={ref} />; });
此代码会将实际的 <input> DOM 节点返回给赋予 InputComp 的 ref。
有时我们不想公开完整的 DOM 节点,而只想公开其方法或属性的一部分。例如,在不公开整个 DOM 节点的情况下聚焦和滚动子组件。我们可以借助 useImperativeHandle Hook 来自定义公开的句柄。
例如
import { forwardRef, useImperativeHandle } from 'react'; const InputComp = forwardRef(function InputComp(props, ref) { useImperativeHandle(ref, () => ({ focus() { inputRef.current.focus(); }, scrollIntoView() { inputRef.current.scrollIntoView(); }, }), []); return <input {...props} />; });
在上面的示例中,我们正在修改父组件公开的句柄。父组件可以调用 InputComp 的 focus 和 scrollIntoView 方法。但它不会直接访问 DOM 节点 <input>。
示例 - 简短的应用程序来理解此 Hook
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react'; const Counter = forwardRef(function Counter(props, ref) { const [count, setCount] = useState(0); const increment = () => { setCount(count + 1); }; const reset = () => { setCount(0); }; useImperativeHandle(ref, () => ({ increment, reset, }), []); return ( <div> <p>Counter: {count}</p> </div> ); }); function App() { const counterRef = useRef(); const handleIncrement = () => { counterRef.current.increment(); }; const handleReset = () => { counterRef.current.reset(); }; return ( <div> <Counter ref={counterRef} /> <button onClick={handleIncrement}>Increment Count</button> <button onClick={handleReset}>Reset</button> </div> ); } export default App;
输出
示例 - 公开我们自己的指令式方法
在一个组件中,我们可以创建我们自己的自定义方法并将其提供给其父组件。这些自定义方法不必与 HTML 元素的内置方法相同。
假设我们有一个 InputForm 组件,它显示一个简单的输入字段组件 (InputForm),当按下按钮时,可以将其滚动到视图中并聚焦。当我们单击名为 App 的父组件中的按钮时,将执行输入字段上的此方法,使其滚动到视图中并获得焦点。
import React, { forwardRef, useRef, useImperativeHandle } from 'react'; const InputForm = forwardRef((props, ref) => { const inputRef = useRef(null); useImperativeHandle(ref, () => ({ scrollAndFocus() { inputRef.current.scrollIntoView(); inputRef.current.focus(); } }), []); return <input type="text" ref={inputRef} placeholder="Type here..." />; }); function App() { const inputRef = useRef(); const handleButtonClick = () => { inputRef.current.scrollAndFocus(); }; return ( <div> <button onClick={handleButtonClick}>Scroll and Focus</button> <InputForm ref={inputRef} /> </div> ); } export default App;
在上面的示例中,我们演示了如何使用 forwardRef 和 useImperativeHandle 来滚动和聚焦输入字段。
总结
在 18 版中,useImperativeHandle 是一个有用的 React Hook,它允许通过更改 ref 来立即与子组件交互。当我们需要快速访问子组件的函数或属性时,它非常有用。通过使用此 Hook,我们可以创建连接并定义我们想要对子组件执行的操作,在需要时提供流畅的通信和更新,并且该方法返回 undefined。