ref
# Ref
定义:当你希望组件“记住”某些信息,但又不想让这些信息 触发新的渲染 时,你可以使用 ref 。
# 使用方式
# class组件
过时的string类型
class Demo extends React.Component{ testRef = ()=>{ console.log(this.refs.inputRef.value) } render (){ return ( <> <h1>Hello, <b>React</b> world!</h1> <input ref="inputRef" pleaseholder="请输入的内容" /> <br /> <button onClick={this.testRef}>test</button> </> ) } } ReactDOM.render(<Demo />, document.getElementById('root')); /** Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20回调ref类型
class Demo extends React.Component{ InputRef = null; testRef = ()=>{ console.log(this.inputRef.value) } /** 用于解决内联绑定式的回调在更新state的过程中,执行两次的问题*/ saveInputRef(e){ this.InputRef = e } render (){ return ( <> <h1>Hello, <b>React</b> world!</h1> {/** 回调类型的ref,会在更新过程中执行两次,但是并不会对业务造成影响, 第一次会返回一个null,第二次才会返回绑定的DOM节点 */} <input ref={ e => this.inputRef = e } pleaseholder="请输入的内容" /> {/** 用于解决内联绑定式的回调在更新state的过程中,执行两次的问题 */} <input ref={ this.saveInputRef } pleaseholder="请输入的内容" /> <br /> <button onClick={this.testRef}>test</button> </> ) } } ReactDOM.render(<Demo />, document.getElementById('root')); /** Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, */
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
28createRef类型
class Demo extends React.Component{ inputRef = React.createRef() testRef = ()=>{ console.log(this.inputRef.current.value) } render (){ return ( <> <h1>Hello, <b>React</b> world!</h1> <input ref={this.inputRef} pleaseholder="请输入的内容" /> <br /> <button onClick={this.testRef}>test</button> </> ) } } ReactDOM.render(<Demo />, document.getElementById('root')); /** Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# function组件
/** React 18.*/
import { useRef } from "react"
function MyApp() {
const inputRef = useRef(null)
const testRef = ()=>{
console.log(inputRef.current.value)
}
return (
<>
<h1>Hello, <b>React</b> world!</h1>
<input ref={inputRef} pleaseholder="请输入的内容" />
<br />
<button onClick={testRef}>test</button>
</>
)
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<MyApp />)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 使用场景
存储 timeout ID;
import { useState, useRef } from 'react'; export default function Stopwatch() { const [startTime, setStartTime] = useState(null); const [now, setNow] = useState(null); const intervalRef = useRef(null); function handleStart() { setStartTime(Date.now()); setNow(Date.now()); clearInterval(intervalRef.current); intervalRef.current = setInterval(() => { setNow(Date.now()); }, 10); } function handleStop() { clearInterval(intervalRef.current); } let secondsPassed = 0; if (startTime != null && now != null) { secondsPassed = (now - startTime) / 1000; } return ( <> <h1>时间过去了: {secondsPassed.toFixed(3)}</h1> <button onClick={handleStart}> 开始 </button> <button onClick={handleStop}> 停止 </button> </> ); }
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存储和操作 DOM 元素;
// 如上为input绑定ref
1存储不需要被用来计算 JSX 的其他对象。
// 后续补充
1
# 其他使用
访问另一个组件的 DOM 节点 ,因为默认情况下,React 不允许组件访问其他组件的 DOM 节点。甚至自己的子组件也不行!
/**
<MyInput ref={inputRef} /> 告诉 React 将对应的 DOM 节点放入 inputRef.current 中。
但是,这取决于 MyInput 组件是否允许这种行为, 默认情况下是不允许的。
MyInput 组件是使用 forwardRef 声明的。 这让从上面接收的 inputRef 作为第二个参数 ref 传入组件,第一个参数是 props 。
MyInput 组件将自己接收到的 ref 传递给它内部的 <input>。
*/
import { forwardRef, useRef } from 'react';
const MyInput = forwardRef((props, ref) => {
return <input {...props} ref={ref} />;
});
export default function Form() {
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus();
}
return (
<>
<MyInput ref={inputRef} />
<button onClick={handleClick}>
聚焦输入框
</button>
</>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<MyInput />)
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
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
编辑 (opens new window)
上次更新: 2023/05/21, 23:27:23