React Hooks组件化开发——useRef&&useImperativeHandle
useRef和useImperativeHandle
useRef
是 React 提供的一个 Hook,用于在组件的整个生命周期内持久保存一个可变的 ref
对象。它有两个主要的用途:
- 访问 DOM 节点:使用
useRef
来获取对 DOM 节点的直接引用。这可以用于读取 DOM 信息(如尺寸、位置等)或者调用 DOM API(比如聚焦一个输入框)。
1 | /* |
获取组件实例
子组件是类组件,直接通过
useRef
获取子组件的实例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
28
29
30
31
32
33
34
35
36
37
38
39/*
* @Description:
* @Author: xiuji
* @Date: 2024-01-26 10:34:09
* @LastEditTime: 2024-01-26 11:06:29
* @LastEditors: Do not edit
*/
import React, { useEffect, useRef } from 'react';
class SonCom extends React.Component {
state = {
count: 0
}
render() {
const { count } = this.state;
return (
<div>
<h1>子组件{count}</h1>
</div>
)
}
}
const RefDemo = () => {
const box = useRef(null);
useEffect(() => {
console.log(box.current); // 第一次渲染完毕即可获取到子组件实例(包含子组件内部状态及方法
},[]);
return (
<div>
<SonCom ref={box} />
</div>
)
}
export default RefDemo;子组件是函数组件
直接通过
useRef
访问函数子组件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
28
29
30
31
32/*
* @Description:
* @Author: xiuji
* @Date: 2024-01-26 10:34:09
* @LastEditTime: 2024-01-26 11:11:44
* @LastEditors: Do not edit
*/
import React, { useEffect, useRef } from 'react';
const SonCom = () => {
return (
<div>
<h1>子组件</h1>
</div>
)
}
const RefDemo = () => {
const box = useRef(null);
useEffect(() => {
console.log(box.current);
});
return (
<div>
<SonCom ref={box} />
</div>
)
}
export default RefDemo;控制台报错:Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
需要通过
forwardRef
转发才能在父组件中获取函数子组件节点1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23const SonCom = React.forwardRef((props, ref) => {
return (
<div>
<h1 ref={ref}>子组件</h1>
</div>
)
})
const RefDemo = () => {
const box = useRef(null);
useEffect(() => {
console.log(box.current); // <h1>子组件</h1>
});
return (
<div>
<SonCom ref={box} />
</div>
)
}
export default RefDemo;这样可以获取到绑定ref的DOM节点,
但无法获取到子组件内的状态及方法
。借助
useImperativeHandle
暴露函数子组件内的状态及方法。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
28
29
30
31
32
33
34
35
36
37
38const SonCom = React.forwardRef((props, ref) => {
let [count, setCount] = React.useState(0);
const add = () => {
setCount(count + 1);
}
useImperativeHandle(ref, () => {
return { // 将需要暴露的状态和方法return出去
count,
setCount,
add
}
})
return (
<div ref={ref}>
<h1>子组件{count}</h1>
<button onClick={add}>add</button>
</div>
)
})
const RefDemo = () => {
const box = useRef(null);
useEffect(() => {
console.log(box.current);
});
return (
<div>
<SonCom ref={box} />
</div>
)
}
export default RefDemo;
保存任意可变值:
useRef
还可以用来保存在组件的生命周期内持续存在的任何可变值。这和useState
不同,因为当ref
对象的.current
属性被修改时,不会触发组件的重新渲染。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
28
29/*
* @Description:
* @Author: xiuji
* @Date: 2024-01-26 10:34:09
* @LastEditTime: 2024-01-26 10:54:05
* @LastEditors: Do not edit
*/
import React, { useEffect, useRef } from 'react';
const RefDemo = () => {
const id = useRef(null);
useEffect(() => {
id.current = setInterval(() => {
console.log('id', id.current);
}, 1000);
return () => {
clearInterval(id.current);
}
})
return (
<div>
保存任意可变值
</div>
)
}
export default RefDemo;
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Xiuji957!