使用 Refs 反应功能组件
使用 Refs 反应功能组件
— 带有 forwardRef 和 useImperativeHandle 的示例
逆境中成长 — grow in adversity
我一直不清楚 参考 和 前向引用 ,在做了一些研究之后,我想写一篇文章,用两个小例子来记录这个学习过程。
现在让我们直奔主题吧!
在react的典型数据流中, 道具 是父子组件交互的唯一方式,要修改子组件,您可以使用新的道具重新渲染它。
当然,如上所述 反应官网 ,除了典型的react数据流,在某些情况下(比如关注一个DOM元素等)为了修改子组件,我们可能还需要另外一种方式: 参考 方法。 Refs 提供了一种访问 DOM 节点或 React 元素的方法。
*由于本文使用了功能组件,所以我将重点介绍它们。
让我们从第一个例子开始,这样我们可以更好地理解。
示例一:焦点输入
cursor focused on input when a user clicks a button
假设我们有一个输入字段,当用户开始输入或单击按钮时,我们希望光标聚焦在它上面。修改更有意义 只要 输入字段,而不是改变状态(通过 道具 ) 这会导致组件重新渲染,这可以通过创建一个引用来完成。
我们可以使用 使用参考() 钩子创建一个 ref ,它返回一个可变对象 当前的 属性设置为我们传递给钩子的初始值,并在 DOM 元素上使用它:
常量输入参考 = 使用参考 (无效的);
<input ref={ 输入参考 } 类型=“文本” />
inputRef.current.focus() => 焦点输入
console.log(inputRef)
很简单,当用户开始输入时,输入字段是焦点,但是假设由于某种原因,当用户单击按钮时,这个输入字段也应该具有焦点,我们的输入字段位于名为 react 的子组件内 输入包装器 .
也许我们会尝试这样做:
常量 **输入** **包装器** = ({ref,...}) => <> <input ref={ **参考** } .../>...</> 导出默认函数 **应用程序** () {
常量 **输入参考** = useRef(null);
const focusInput = () => inputRef.current.focus();
返回 (
// 这将 **不是** 工作!
< **输入** **包装器** 参考={ **输入参考** }>
<button onClick={focusInput}>...</button>
</ **输入** **包装 >**
)}}
这不起作用,因为默认情况下,refs 只在原生 html 元素中工作,我们不能为 React 组件提供 ref(在我们的例子中 输入包装器) ,并且由于函数组件没有实例,我们也可以不使用 参考
属性,这意味着:
常规函数或类组件不接收
参考
参数,并且 ref 在 道具 任何一个。
所以我们需要传递我们的 InputWrapper **** 进入 前向引用 ,它接收传递给功能组件的 props 和 refs 并为其返回 JSX.Element。
const InputWrapper = forwardRef((props, ref) => {…})
create and pass ref to InputWrapper inside App component
button event handler inside App which triggers focus
forwarding ref to input DOM element
通过这样做,我们告诉 React 这个组件可以接受一个 ref 和我们的第二个参数。 输入包装器
将是传入的 ref。 第二个 参考
争论 只要 当我们定义一个组件时存在 前向引用
称呼。
*在类组件上也可以进行引用转发
示例二:播放/暂停视频和焦点输入
using useImperativeHandle for multiple refs
在这个例子中,我们有一个视频播放器和 2 个按钮 播放/暂停 视频,我们也想 重点 当我们单击播放按钮时,下面的输入字段,这意味着我们将有多个参考(视频,输入)。
如何转发多个参考?
第一个解决方案,我们可以创建 refs 并将它们传递给一个对象,然后使用与上面示例相同的逻辑。
家长应用:
导出默认函数 **应用程序** () {
常量 **视频参考** = 使用参考();
常量 **焦点参考** = 使用参考(); const focusInput = () => inputRef.current.focus();
常量句柄播放 = () => {
videoRef.current.play();
focusRef.current.focus();
};
常量句柄暂停 = () => {
videoRef.current.pause();
}; 返回 (
< **视频包装器** **ref={{ videoRef, focusRef }}** > // 传递 refs
<button onClick={handlePlay}>玩</button>
<button onClick={handlePause}>暂停</button>
</ **视频包装器** >
)
儿童 VideoWrapper:
功能 VideoWrapper(道具,参考){
**常量 { videoRef, focusRef } = 参考; // ** 解构参考
返回 (
<>
<video
参考={ **视频参考** }
宽度=“...”
高度=“...”
控制
src={"..."}
/>
{props.children}
<input ref={ **焦点参考** } ... />
</>
);
导出默认值 **前向引用** (视频包装);
第二种解决方案:使用 React Hook 使用命令式句柄
useImperativeHandle 自定义使用 ref 时暴露给父组件的实例值,应该和 前向引用 .
这可能听起来很混乱,让我们先更新组件:
在 App 中创建一个 ref 并将其传递给 VideoWrapper:
导出默认函数 App() {
**常量 ref = useRef(null);
** 常量句柄播放 = () => {
参考电流。 **播放视频** (); // 暴露方法 _
_ 参考电流。 **焦点这个输入** ();
};
const handlePause = () => ref.current。 **暂停我** ();
返回 (
< **视频包装器** **参考={参考}** > // 传递 ref
<button onClick={handlePlay}>玩</button>
<button onClick={handlePause}>暂停</button>
</ **视频包装器** >
)}
在 VideoWrapper 组件中,我们可以确定哪些属性将在 ref 上公开 使用命令式句柄 Hook( 你可以随意称呼它们: 播放视频 , focusThisInput, pauseMe …)
从“反应”导入{ forwardRef,useImperativeHandle,useRef}; 功能 VideoWrapper(道具,参考){
常量 **视频参考** = 使用参考();
常量 **输入参考** = 使用参考(); **使用命令式句柄** ( **参考** , () => ({
_你可以随便称呼他们
_ **播放视频** : () => {
videoRef.current.play();
},
**暂停我** : () => {
videoRef.current.pause();
},
**焦点这个输入** : () => {
inputRef.current.focus();
}
}),[]); 返回 (
<>
<video
参考={ **视频参考** }
宽度=“...”
高度=“...”
控制
src={"..."}
/>
{props.children}
<input ref={ **输入参考** } .../>
</>
);
}
导出默认值 **前向引用** (视频包装);
上面的代码是什么意思?我们在里面添加方法 使用命令式句柄
钩子,然后它们将被其父级公开和使用。
如上例所示,我们可以使用 hook 访问 react 功能子组件的底层 DOM 元素 前向引用 ,我们可以处理多个引用,甚至可以通过将引用传递给其子组件来修改父组件可以访问的引用 使用命令式句柄。
注意: 使用命令式句柄 启用命令式代码,这违背了 React 的声明性,这使得它非常独特。由于这个原因,除非绝对需要,否则通常建议避免使用此钩子。
你可以看到结果并尝试一下 这里 .
而已!我相信有更好的方法和解决方案,在这里我只想分享我到目前为止所学到的东西,希望你觉得这些例子很有趣。谢谢你的时间! ⏰
如果你也对我的其他文章感兴趣,这里有一些链接:
[
为 React 应用程序创建一个简单的 Express 服务器 (Node.js)
关于如何创建简单的 Express 服务器 (Node.js)、将其连接到 React 应用程序以及解决错误的教程……
javascript.plainenglish.io
[
使用会话存储在 React 组件中保持状态
sessionStorage 中的数据在页面会话结束时被清除。
javascript.plainenglish.io
[
使用会话存储在 React 组件中保持状态
sessionStorage 中的数据在页面会话结束时被清除。
javascript.plainenglish.io
[
以 React 方式隐藏和替换滚动时的粘性元素
— 棘手但有趣
媒体网
[
以 React 方式创建响应式 iframe 嵌入
— 令人惊讶的是,YouTube 没有响应式嵌入代码,让我们玩一下 css ...
enlear.academy
](https://enlear.academy/create-responsive-iframe-embed-in-a-react-way-f52075bf3b04)
[
创建一个简单的 React 自定义 Hook
一个关于如何创建一个简单的 React 自定义钩子的教程
javascript.plainenglish.io
](https://javascript.plainenglish.io/create-a-simple-react-custom-hook-fc733d7b977a)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明