除了前面提到的 useStateuseEffectuseContextuseReducer 之外,React 还提供了一些常用的内置 Hooks,用于处理性能优化、DOM 操作、状态缓存等场景。以下是一些重要的常用 Hooks:

1. useCallback - 缓存函数引用

用于缓存函数的引用,避免在组件重新渲染时创建新的函数实例,从而优化子组件的性能(尤其适合传递给子组件的回调函数)。

import { useCallback, useState } from 'react';function Parent() {const [count, setCount] = useState(0);// 缓存函数:仅当依赖项变化时才重新创建const handleClick = useCallback(() => {console.log('点击了按钮');}, []); // 空依赖数组:函数永远不会重新创建return <Child onClick={handleClick} />;
}function Child({ onClick }) {// 只有当 onClick 引用变化时,Child 才会重新渲染return <button onClick={onClick}>点击我</button>;
}

2. useMemo - 缓存计算结果

用于缓存昂贵的计算结果,避免在组件重新渲染时重复计算,提升性能。

import { useMemo, useState } from 'react';function ExpensiveComponent({ list }) {// 缓存计算结果:仅当 list 变化时才重新计算const sortedList = useMemo(() => {// 模拟昂贵的排序操作return [...list].sort((a, b) => a - b);}, [list]); // 依赖项:list 变化时重新计算return <div>{sortedList.join(', ')}</div>;
}

注意useMemo 是用于性能优化的,不要滥用(简单计算无需缓存)。

3. useRef - 保存可变值/访问DOM

  • 用于在组件多次渲染之间保存一个可变值(不会触发组件重新渲染)。
  • 最常见的用途是访问 DOM 元素。
import { useRef, useEffect } from 'react';function InputFocus() {// 创建 ref 对象const inputRef = useRef(null);useEffect(() => {// 访问 DOM 元素并聚焦inputRef.current.focus();}, []);return <input ref={inputRef} placeholder="自动聚焦" />;
}// 保存可变值(不会触发重渲染)
function Counter() {const [count, setCount] = useState(0);const prevCount = useRef(0); // 保存上一次的 countuseEffect(() => {prevCount.current = count; // 更新 ref 的值}, [count]);return <div>当前: {count}, 上一次: {prevCount.current}</div>;
}

4. useImperativeHandle - 自定义暴露给父组件的实例值

配合 forwardRef 使用,自定义子组件通过 ref 暴露给父组件的方法或属性,避免暴露整个 DOM 实例。

import { useImperativeHandle, forwardRef, useRef } from 'react';// 子组件
const CustomInput = forwardRef((props, ref) => {const inputRef = useRef(null);// 自定义暴露给父组件的方法useImperativeHandle(ref, () => ({focus: () => {inputRef.current.focus();},clear: () => {inputRef.current.value = '';}}));return <input ref={inputRef} />;
});// 父组件
function Parent() {const inputRef = useRef(null);return (<div><CustomInput ref={inputRef} /><button onClick={() => inputRef.current.focus()}>聚焦</button><button onClick={() => inputRef.current.clear()}>清空</button></div>);
}

5. useLayoutEffect - 同步执行DOM操作

useEffect 类似,但它会在 DOM 更新完成后同步执行(而 useEffect 是异步的),适合需要在 DOM 变更后立即读取或修改布局的场景(如测量元素尺寸)。

import { useLayoutEffect, useRef, useState } from 'react';function MeasureElement() {const [size, setSize] = useState({ width: 0, height: 0 });const divRef = useRef(null);useLayoutEffect(() => {// DOM 更新后同步执行:立即获取元素尺寸const { width, height } = divRef.current.getBoundingClientRect();setSize({ width, height });}, []); // 组件挂载后执行一次return <div ref={divRef}>尺寸: {size.width}x{size.height}</div>;
}

注意useLayoutEffect 会阻塞浏览器渲染,优先使用 useEffect,仅在必要时使用。

6. useDebugValue - 自定义Hook的调试信息

用于在 React DevTools 中显示自定义 Hook 的标签和值,方便调试。

import { useDebugValue, useState, useEffect } from 'react';// 自定义Hook:获取在线状态
function useOnlineStatus() {const [isOnline, setIsOnline] = useState(true);useEffect(() => {const handleOnline = () => setIsOnline(true);const handleOffline = () => setIsOnline(false);window.addEventListener('online', handleOnline);window.addEventListener('offline', handleOffline);return () => {window.removeEventListener('online', handleOnline);window.removeEventListener('offline', handleOffline);};}, []);// 在DevTools中显示自定义标签和值useDebugValue(isOnline ? '在线' : '离线');return isOnline;
}

总结

这些 Hooks 覆盖了 React 开发中的常见场景:

  • 性能优化:useCallbackuseMemo
  • DOM 操作:useRefuseLayoutEffect
  • 组件通信:useImperativeHandle
  • 调试:useDebugValue

合理组合使用这些 Hooks 可以让组件逻辑更清晰、性能更优。实际开发中,还可以基于这些基础 Hooks 封装自定义 Hooks(如 useFetchuseLocalStorage 等),进一步复用逻辑。