React Hooks 系列 之 useRef
useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传递的参数(initialValue)。返回的对象将在组件的整个生命周期内保持不变。
返回一个持久的对象
demo 代码
jsx
import { useRef, useState, useEffect } from "react";
import { Card, Button, Space } from "antd";
function Timer() {
const [isRunning, setIsRunning] = useState(false);
const count = useRef(0);
const intervalRef = useRef(null);
useEffect(() => {
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
};
}, []);
const startTimer = () => {
if (!isRunning) {
setIsRunning(true);
intervalRef.current = setInterval(() => {
count.current += 1;
console.log(`Timer has run ${count.current} times.`);
}, 1000);
}
};
const stopTimer = () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
setIsRunning(false);
}
};
return (
<Card title="案例 demo">
<p>Check the console to see the timer count:{count.current}</p>
<Space>
<Button onClick={startTimer} type="primary" disabled={isRunning}>
开始
</Button>
<Button onClick={stopTimer} disabled={!isRunning}>
停止
</Button>
</Space>
</Card>
);
}
export default Timer;
import { useRef, useState, useEffect } from "react";
import { Card, Button, Space } from "antd";
function Timer() {
const [isRunning, setIsRunning] = useState(false);
const count = useRef(0);
const intervalRef = useRef(null);
useEffect(() => {
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
};
}, []);
const startTimer = () => {
if (!isRunning) {
setIsRunning(true);
intervalRef.current = setInterval(() => {
count.current += 1;
console.log(`Timer has run ${count.current} times.`);
}, 1000);
}
};
const stopTimer = () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
setIsRunning(false);
}
};
return (
<Card title="案例 demo">
<p>Check the console to see the timer count:{count.current}</p>
<Space>
<Button onClick={startTimer} type="primary" disabled={isRunning}>
开始
</Button>
<Button onClick={stopTimer} disabled={!isRunning}>
停止
</Button>
</Space>
</Card>
);
}
export default Timer;
上述的 demo 展示了 useRef
的以下特性:
持久性:
useRef
返回的 ref 对象在组件的整个生命周期内都是持久的。不会引起组件重新渲染:与
useState
不同,修改useRef
的.current
属性不会引起组件重新渲染。在 demo 中,即使我们增加了count.current
的值,组件也没有重新渲染。
与 DOM 交互
demo 代码
jsx
import { useRef } from "react";
import { Card, Input, Button, Space } from "antd";
function TextInputWithFocus() {
const inputEl = useRef(null);
const onButtonClick = () => {
inputEl.current.focus();
};
return (
<Card title="案例 demo">
<Space>
<Input ref={inputEl} placeholder="click button" />
<Button onClick={onButtonClick} type="primary">
Focus the input
</Button>
</Space>
</Card>
);
}
export default TextInputWithFocus;
import { useRef } from "react";
import { Card, Input, Button, Space } from "antd";
function TextInputWithFocus() {
const inputEl = useRef(null);
const onButtonClick = () => {
inputEl.current.focus();
};
return (
<Card title="案例 demo">
<Space>
<Input ref={inputEl} placeholder="click button" />
<Button onClick={onButtonClick} type="primary">
Focus the input
</Button>
</Space>
</Card>
);
}
export default TextInputWithFocus;
这个 demo 主要展示了 useRef 如何在 React 中用于直接与 DOM 元素交互。
保存上一次的值
demo 代码
jsx
import { useRef, useState, useEffect } from "react";
import { Card, Button } from "antd";
function PreviousValueComponent() {
const [count, setCount] = useState(0);
const prevCountRef = useRef();
useEffect(() => {
prevCountRef.current = count;
}, [count]);
return (
<Card title="案例 demo">
<p>Current count: {count}</p>
<p>Previous count: {prevCountRef.current}</p>
<Button onClick={() => setCount(count + 1)} type="primary">
Increment
</Button>
</Card>
);
}
export default PreviousValueComponent;
import { useRef, useState, useEffect } from "react";
import { Card, Button } from "antd";
function PreviousValueComponent() {
const [count, setCount] = useState(0);
const prevCountRef = useRef();
useEffect(() => {
prevCountRef.current = count;
}, [count]);
return (
<Card title="案例 demo">
<p>Current count: {count}</p>
<p>Previous count: {prevCountRef.current}</p>
<Button onClick={() => setCount(count + 1)} type="primary">
Increment
</Button>
</Card>
);
}
export default PreviousValueComponent;
这个 demo 主要展示了 useRef 如何在 React 中用于跟踪上一次的值。