useRef文档
useRef 是一个ReactHook,它能帮助引用一个不需要渲染的值。
const ref = useRef(initialValue)
参数
- initialValue:ref对象的 current 属性的初始值,可以是任意类型的值,这个参数在首次渲染后被忽略。
返回值
useRef 返回一个只有一个属性的对象:
- current:初始值为传递的 initialValue。之后可以将其设置为其他值。如果将ref对象作为一个JSX节点的 ref 属性传递给React,React 将为它设置 current 属性。
在后续的渲染中,useRef 将返回同一个对象。
注意
- 可以修改 ref.current 属性。与 state 不同,它是可变的。然而,如果它持有一个用于渲染的对象(例如 state 的一部分),那么就不应该修改这个对象。
- 改变 ref.current 属性时,React 不会重新渲染组件。React 不知道它何时会发生改变,因为 ref 是一个普通的 JavaScript 对象。
- 除了 初始化 外不要在渲染期间写入或者读取 ref.current,否则会使组件行为变得不可预测。
- 在严格模式下,React 将会 调用两次组件方法,这是为了 帮助发现意外问题。但这只是开发模式下的行为,不会影响生产模式。每个 ref 对象都将会创建两次,但是其中一个版本将被丢弃。如果使用的是组件纯函数(也应当如此),那么这不会影响其行为。
应用
1. 存储数值
// 通过 useRef 存储 数据状态变更之前的值
import { useRef, useState } from "react"
export default function App() {
const [count, setCount] = useState(0);
const prevCount = useRef();
function increase() {
// 存储更新前的数值,不会触发组件渲染
prevCount.current = count;
setCount(count + 1);
}
return (
<>
<button onClick={increase}>+</button>
<div>更新后的值:{count}</div>
<div>更新前的值:{prevCount.current}</div>
</>
)
}
2. 父组件通过 ref 获取子组件功能
- forwardRef 允许组件使用 ref 将DOM阶段暴露给父组件。
- useImperativeHandle 能让你自定义由 ref 暴露出来的句柄.
import { forwardRef, useImperativeHandle, useRef } from "react"
// 父组件通过 ref 访问子组件功能,需要用到 forwardRef、useImperativeHandle
// 1. forwardRef 允许组件使用 ref 将 DOM 节点暴露给父组件。
const Child = forwardRef(function(props, ref) {
// 2. useImperativeHandle 可以自定义要暴露给父组件的方法
useImperativeHandle(ref, () => ({
childFun: () => {
console.log('console 子组件');
}
}));
return (
<div>子组件内容</div>
)
})
export default function App(){
const childRef = useRef(null);
function handleClick() {
childRef.current.childFun();
}
return (
<>
<Child ref={childRef} />
<button onClick={handleClick}>调用子组件内部方法</button>
</>
)
}