useRef 保存引用值和useImperativeHandle 透传 Ref
Posted 前端e站
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了useRef 保存引用值和useImperativeHandle 透传 Ref相关的知识,希望对你有一定的参考价值。
上一节我们介绍了useCallback 记忆函数和useMemo 记忆组件,这一节来学习一下useRef 保存引用值和useImperativeHandle 透传 Ref。
useRef 保存引用值
useRef 跟 createRef 类似,都可以用来生成对 DOM 对象的引用,看个简单的例子:
import React, useState, useRef from "react";
function App()
let [name, setName] = useState("Nate");
let nameRef = useRef();
const submitButton = () =>
setName(nameRef.current.value);
;
return (
<div className="App">
<p>name</p>
<div>
<input ref=nameRef type="text" />
<button type="button" onClick=submitButton>
Submit
</button>
</div>
</div>
);
useRef 返回的值传递给组件或者 DOM 的 ref 属性,就可以通过 ref.current 值访问组件或真实的 DOM 节点,重点是组件也是可以访问到的,从而可以对 DOM 进行一些操作,比如监听事件等等。
当然 useRef 远比你想象中的功能更加强大,useRef 的功能有点像类属性,或者说您想要在组件中记录一些值,并且这些值在稍后可以更改。
利用 useRef 就可以绕过 Capture Value 的特性。可以认为 ref 在所有 Render 过程中保持着唯一引用,因此所有对 ref 的赋值或取值,拿到的都只有一个最终状态,而不会在每个 Render 间存在隔离。
参考例子:精读《Function VS Class 组件》
React Hooks 中存在 Capture Value 的特性:
function App()
const [count, setCount] = useState(0);
useEffect(() =>
setTimeout(() =>
alert("count: " + count);
, 3000);
, [count]);
return (
<div>
<p>You clicked count times</p>
<button onClick=() => setCount(count + 1)>增加 count</button>
<button onClick=() => setCount(count - 1)>减少 count</button>
</div>
);
先点击增加button,后点击减少button,3秒后先alert 1,后alert 0,而不是alert两次0。这就是所谓的 capture value 的特性。而在类组件中 3 秒后输出的就是修改后的值,对 this 属性的访问都会获取到最新的值,类组件举例,在线Demo。讲到这里你应该就明白了,useRef 创建一个引用,就可以有效规避 React Hooks 中 Capture Value 特性。
useRef避免 Capture Value
function App()
const count = useRef(0);
const showCount = () =>
alert("count: " + count.current);
;
const handleClick = number =>
count.current = count.current + number;
setTimeout(showCount, 3000);
;
return (
<div>
<p>You clicked count.current times</p>
<button onClick=() => handleClick(1)>增加 count</button>
<button onClick=() => handleClick(-1)>减少 count</button>
</div>
);
只要将赋值与取值的对象变成 useRef,而不是 useState,就可以躲过 capture value 特性,在 3 秒后得到最新的值。
useImperativeHandle 透传 Ref
通过 useImperativeHandle 用于让父组件获取子组件内的索引。
import React, useRef, useEffect, useImperativeHandle, forwardRef from "react";
function ChildInputComponent(props, ref)
const inputRef = useRef(null);
useImperativeHandle(ref, () => inputRef.current);
return <input type="text" name="child input" ref=inputRef />;
const ChildInput = forwardRef(ChildInputComponent);
function App()
const inputRef = useRef(null);
useEffect(() =>
inputRef.current.focus();
, []);
return (
<div>
<ChildInput ref=inputRef />
</div>
);
通过这种方式,App 组件可以获得子组件的 input 的 DOM 节点。
关注我,下一节一起学习useEffect和useLayoutEffect有什么区别?。
以上是关于useRef 保存引用值和useImperativeHandle 透传 Ref的主要内容,如果未能解决你的问题,请参考以下文章
useRef 保存引用值和useImperativeHandle 透传 Ref
在 React-Hooks UseRef 我无法获得新的状态值
useEffect和useLayoutEffect有什么区别?
useEffect和useLayoutEffect有什么区别?