在 React 中,useRef 是一个多功能hook,允许开发人员与 DOM 交互并管理可变值,而不会触发刷新。当在 TypeScript
中使用时,它将变得更加强大,可提供类型安全并防止常见的运行时错误。在本文中,我们将探讨 React 中 useRef
的各种用例,重点是如何在 TypeScript
项目中有效使用它。
什么是useRef
React 中的 useRef
hook它接受一个参数,即初始参考值,并返回一个可以访问和修改的 ref
对象。该 ref
可以保存对 DOM 元素或任何其他值的引用,并在渲染过程中持续存在。与状态变量不同的是,改变 ref
的值不会触发组件的重新渲染,因此它非常适合某些场景。
基础用法
下面介绍如何在功能组件中使用 useRef
:
ts
import React, { useRef } from 'react';
function MyComponent() {
const myRef = useRef(null);
// Accessing the current value of the ref
console.log(myRef.current);
return <div ref={myRef}>Hello, useRef!</div>;
}
在上面的示例中,创建了一个名为 myRef 的 ref,并使用 ref 属性将其附加到一个 DOM 元素上。可以使用 myRef.current 访问 ref 的当前值。
TS中React useRef的应用
1.访问DOM元素
useRef 最常见的用例之一是直接访问 DOM 元素。这对于input
聚焦输入字段或获得元素尺寸等任务非常有用:
ts
import React, { useRef, useEffect } from 'react';
function AutoFocusInput() {
const inputRef = useRef<HTMLInputElement | null>(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
return <input ref={inputRef} />;
}
在本例中,inputRef 能够在组件挂载时聚焦输入元素,而不需要状态变量来触发重新渲染。
2.变量值缓存
useRef 可用于存储和比较不同渲染中的先前值。这对于检测props
或state
的变化非常有用:
ts
import React, { useRef, useEffect } from 'react';
function ValueChangeDetector(props: { value: number }) {
const prevValueRef = useRef<number | undefined>();
useEffect(() => {
prevValueRef.current = props.value;
if (prevValueRef.current !== undefined && prevValueRef.current !== props.value) {
console.log('Value changed:', prevValueRef.current, '->', props.value);
}
}, [props.value]);
return <div>{props.value}</div>;
}
prevValueRef 保存了props
的前一个值,以便进行比较,并在props
发生变化时处理任务。
3.存储非可控中的值
useRef 可用于存储更改时不会触发重新渲染的值。这对于缓存计算或不属于组件状态的值非常有用:
ts
import React, { useRef, useState } from 'react';
function ExpensiveComponent() {
const expensiveValueRef = useRef<number>(0);
const [count, setCount] = useState<number>(0);
const calculateExpensiveValue = () => {
if (expensiveValueRef.current === 0) {
// Perform expensive calculation
expensiveValueRef.current = /* ... */;
}
return expensiveValueRef.current;
};
return (
<div>
<p>Expensive Value: {calculateExpensiveValue()}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
在本例中,effensiveValueRef 存储了计算结果,确保计算只发生一次。
4.与第三方库交互
在将 React 与依赖于可变值的第三方库或 API 集成时,可以使用 useRef 来维护引用并安全地与这些库进行交互:
ts
import React, { useRef, useEffect } from 'react';
import { Chart } from 'chart.js';
function ChartComponent(props: { data: number[] }) {
const chartRef = useRef<HTMLCanvasElement | null>(null);
const chartInstance = useRef<Chart | null>(null);
useEffect(() => {
if (chartRef.current) {
chartInstance.current = new Chart(chartRef.current, {
type: 'line',
data: {
labels: [...Array(props.data.length).keys()],
datasets: [
{
label: 'Data',
data: props.data,
borderColor: 'blue',
},
],
},
});
}
return () => {
if (chartInstance.current) {
chartInstance.current.destroy();
}
};
}, [props.data]);
return <canvas ref={chartRef} />;
}
chartRef 是对画布元素的引用,chartInstance 是对图表实例的引用。在 useEffect 钩子中安全地创建和销毁图表。
总结
React 中的 useRef
钩子与 TypeScript
结合使用时,是一种强大的工具,可让你处理可变值并高效地与 DOM 交互,同时保持类型安全。了解 useRef
的各种用例和最佳实践将有助于编写更简洁、性能更强的 React 组件。