You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写自定义React Hook:仅在值变化时更新状态

实现带自定义比较逻辑的useState Hook

下面是一个符合需求的自定义Hook,它和原生useState用法一致,但会先通过比较函数判断新旧值是否相等,只有当值真正变化时才更新状态:

import { useState, useRef, useCallback } from 'react';

function useCompareState(initialValue, compareFn = (a, b) => a === b) {
  const [state, setState] = useState(initialValue);
  const prevValueRef = useRef(initialValue);

  const setCompareState = useCallback((newValue) => {
    // 兼容useState的函数式更新写法
    const resolvedValue = typeof newValue === 'function' ? newValue(state) : newValue;
    // 调用比较函数判断新旧值是否相等
    const valuesEqual = compareFn(prevValueRef.current, resolvedValue);
    
    if (!valuesEqual) {
      prevValueRef.current = resolvedValue;
      setState(resolvedValue);
    }
  }, [compareFn, state]);

  return [state, setCompareState];
}

核心逻辑说明

  • 初始值:第一个参数initialValue和原生useState完全一致,可以是直接值,也可以是返回初始值的函数(用于复杂初始化场景)
  • 自定义比较:第二个可选参数compareFn默认用===做浅比较;你可以传入自定义函数,只要函数返回true就认为新旧值相等,不触发状态更新
  • 状态缓存:用useRef存储上一次的状态值,确保每次比较时能拿到准确的旧值
  • 函数稳定性:用useCallback包裹更新函数,避免因依赖变化以外的原因导致函数重新创建,减少不必要的组件重渲染
  • 兼容函数式更新:支持像原生useState那样传入函数作为更新参数,比如setCompareState(prev => prev + 1)

使用示例

场景1:默认浅比较

适合基础类型(数字、字符串、布尔值)的状态判断:

function Counter() {
  const [count, setCount] = useCompareState(0);

  const handleClick = () => {
    setCount(0); // 和当前值相等,不会触发更新
    setCount(count + 1); // 值变化,触发更新
  };

  return (
    <div>
      <p>当前计数:{count}</p>
      <button onClick={handleClick}>更新计数</button>
    </div>
  );
}

场景2:自定义对象比较

当状态是对象时,可以通过比较特定字段判断是否需要更新:

function UserCard() {
  const [user, setUser] = useCompareState(
    { id: 1, name: '张三' },
    (prevUser, newUser) => prevUser.id === newUser.id
  );

  const updateUser = () => {
    // 相同id,不触发更新
    setUser({ id: 1, name: '张三(更新)' });
    // 不同id,触发更新
    setUser({ id: 2, name: '李四' });
  };

  return (
    <div>
      <p>用户信息:{JSON.stringify(user)}</p>
      <button onClick={updateUser}>更新用户</button>
    </div>
  );
}

内容的提问来源于stack exchange,提问作者McKrus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 11:50:46