state和ref

在 React 中,state 的更新机制与 Vue 3 的 ref 确实存在本质区别:

Vue 3 的 ref 会对对象进行响应式代理,因此可以直接修改深层属性(如 obj.value.deep.prop = 123),Vue 能自动检测到变化并触发更新。

React 的 state 则遵循 "不可变性原则",不能直接修改深层属性,必须通过创建新对象的方式更新(表面上看是 "整体修改",实际是替换引用)。

具体对比示例

Vue 3 中可以直接修改深层属性:
复制代码
import { ref } from 'vue';

const user = ref({
  info: {
    name: '张三',
    age: 20
  }
});

// 直接修改深层属性,Vue 能检测到
user.value.info.age = 21; // 有效,视图会更新
React 中直接修改深层属性无效:
复制代码
import { useState } from 'react';

const [user, setUser] = useState({
  info: {
    name: '张三',
    age: 20
  }
});

// 错误做法:直接修改深层属性,React 无法检测
const wrongUpdate = () => {
  user.info.age = 21; // 无效,视图不会更新
  setUser(user); // 引用未变,React 认为状态没变化
};
React 正确的深层更新方式:

必须创建新对象(保持引用变化):

复制代码
const correctUpdate = () => {
  setUser({
    ...user, // 复制外层对象
    info: {
      ...user.info, // 复制内层对象
      age: 21 // 修改目标属性
    }
  });
};

核心原因

  • React 依赖引用变化检测状态更新(新旧状态引用不同才会触发重渲染)
  • Vue 3 基于Proxy 代理,能追踪对象内部属性的变化,不需要依赖引用变化

如果觉得手动处理深层对象麻烦,可以使用 immer 库简化操作,它允许用 "直接修改" 的写法,但内部会自动转换为不可变更新:

复制代码
import { produce } from 'immer';

const updateWithImmer = () => {
  setUser(produce(draft => {
    draft.info.age = 21; // 看似直接修改,实际是安全的
  }));
};

总结:React 中不能像 Vue 3 那样直接修改深层属性,必须通过创建新对象的方式更新,但可以借助工具库简化这个过程。

复制代码
import { useState } from 'react';

function UserProfile() {
  // 定义深层对象状态
  const [user, setUser] = useState({
    name: '张三',
    age: 25,
    address: {
      city: '北京',
      district: '朝阳区',
      street: '建国路88号'
    },
    hobbies: ['读书', '运动']
  });

  // 1. 修改浅层属性(一级属性)
  const updateName = () => {
    // 创建新对象,复制原有属性,只修改需要变更的部分
    setUser({
      ...user,  // 复制原有所有属性
      name: '张三丰'  // 覆盖需要修改的属性
    });
  };

  // 2. 修改深层属性(二级及以上)
  const updateCity = () => {
    setUser({
      ...user,  // 复制一级属性
      address: {
        ...user.address,  // 复制二级属性
        city: '上海'  // 覆盖需要修改的深层属性
      }
    });
  };

  // 3. 向深层数组添加元素
  const addHobby = () => {
    setUser({
      ...user,
      hobbies: [...user.hobbies, '编程']  // 复制原数组并添加新元素
    });
  };

  // 4. 复杂修改:同时修改多个层级的属性
  const complexUpdate = () => {
    setUser({
      ...user,
      age: 26,  // 修改一级属性
      address: {
        ...user.address,
        district: '浦东新区'  // 修改二级属性
      }
    });
  };

  return (
    <div>
      <h3>用户信息</h3>
      <p>姓名:{user.name}</p>
      <p>年龄:{user.age}</p>
      <p>城市:{user.address.city}</p>
      <p>区:{user.address.district}</p>
      <p>爱好:{user.hobbies.join(', ')}</p>

      <button onClick={updateName}>修改姓名</button>
      <button onClick={updateCity}>修改城市</button>
      <button onClick={addHobby}>添加爱好</button>
      <button onClick={complexUpdate}>复杂更新</button>
    </div>
  );
}

export default UserProfile;
相关推荐
QQ1__8115175151 小时前
Spring boot名城小区物业管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot
钛态1 小时前
前端微前端架构:大项目的救命稻草还是自找麻烦?
前端·vue·react·web
一粒黑子1 小时前
【实战解析】阿里开源 PageAgent:纯前端 GUI Agent,一行JS让网页支持自然语言操控
前端·javascript·开源
独角鲸网络安全实验室1 小时前
2026微信小程序抓包全解析:从实操落地到合规风控,解锁前端调试新范式
前端·微信小程序·小程序·抓包·系统代理绕过·https证书严格校验·进程隔离
紫微AI1 小时前
前端文本测量成了卡死一切创新的最后瓶颈,pretext实现突破了
前端·人工智能·typescript
GISer_Jing1 小时前
AI前端(From豆包)
前端·aigc·ai编程
IT枫斗者1 小时前
前端部署后如何判断“页面是不是最新”?一套可落地的版本检测方案(适配 Vite/Vue/React/任意 SPA)
前端·javascript·vue.js·react.js·架构·bug
测试修炼手册1 小时前
[测试技术] 深入理解 JSON Web Token (JWT)
前端·json
AI老李1 小时前
2026 年 Web 前端开发的 8 个趋势!
前端
里欧跑得慢1 小时前
15. Web可访问性最佳实践:让每个用户都能平等访问
前端·css·flutter·web