state和ref

发布于:2025-09-09 ⋅ 阅读:(16) ⋅ 点赞:(0)

在 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;


网站公告

今日签到

点亮在社区的每一天
去签到