useRef
可以用于引用一个不需要渲染的值
语法
useRef(initialValue)
initialValue
: ref对象的current
属性的初始值,只在初次渲染的时候有效
返回值
useRef
返回一个只有current
属性的对象。current
初始值为传递的initialValue
,之后可以将其设置为其他值
如果将ref对象作为一个JSX节点的ref
属性,React会为它设置current
属性
注意
ref.current
属性可以修改,它是可变的,这与state
不同
- 改变
ref.current
属性,不会重新渲染组件
- 除了进行初始化操作,不要在渲染期间写入或读取
ref.current
不要在渲染期间写入或者读取ref.current
,如果不得不在渲染期间读取或写入,应该使用state
1 2 3 4 5 6
| function App() { myRef.current = 123 return <div>{myRef.current}</div> }
|
在事件处理程序或者Effect中读取或写入ref
1 2 3 4 5 6 7
| function App() { useEffect(() => { myRef.current = 123 }) }
|
使用
useRef
的使用场景主要有两种:
- 引用或存储一些不影响视图的信息。(因为改变ref不会触发重新渲染)
- 通过ref对象赋值给DOM的
ref
属性来获取或操作DOM
引用或存储一个值
示例:保存定时器的id
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function App() { let timerRef = useRef(null)
function handleStartClick() { const timer = setTimeout(() => { }, 1000) timerRef.current = timer }
function handleStopClick() { clearTimeout(timerRef.current) }
return ( <div className="App"> // .... </div> ) }
|
通过ref操作DOM
1 2 3 4 5 6 7 8 9 10 11
| function App() { const inputRef = useRef(null)
function handleClick() { inputRef.current.focus() }
return <input ref={ref} /> }
|
无法获取自定义组件的ref
默认情况下,自定义组件不会暴露他们内部DOM节点的ref
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import { useState, useRef } from "react";
function MyComp() { const [x, setX] = useState(0)
return <p>{x}</p> }
function App() {
const myRef = useRef(null)
function handleClick() { console.log(myRef.current); }
return ( <> <MyComp ref={myRef} /> <button onClick={handleClick}>获取ref</button> </> ) }
export default App;
|
控制台警告,无法获取到ref
为了解决这个问题,可以使用forwardRef
包裹子组件,这样父组件就能得到它的ref
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import { useEffect, useState, useRef, forwardRef } from "react";
const MyComp = forwardRef((props, ref) => { const [x, setX] = useState(0)
return <p ref={ref}>{x}</p> })
function App() {
const myRef = useRef(null)
function handleClick() { console.log(myRef.current); }
return ( <> <MyComp ref={myRef} /> <button onClick={handleClick}>获取ref</button> </> ) }
export default App;
|