React × Vue

状态 API:useState 与 ref / reactive

聚焦 React useState 与 Vue ref、reactive 更新数字和对象状态时的 API 写法。

核心结论

React state 是一次 render 的快照,更新时应通过 setter 提交新值;Vue 的 ref 和 reactive 是稳定的响应式容器,可以修改 .value 或对象属性。

对象更新流程

Vue 3 × React

flowchart LR
  event["用户操作"] --> react["React: setState(prev => newValue)"]
  react --> snapshot["下一次 render 的新快照"]
  event --> vue["Vue: ref.value / reactive.key = value"]
  vue --> deps["触发读取该属性的依赖"]

图中实线表示主要数据或处理路径,虚线表示反馈、通知或下一轮更新。

Vue 3 × React 流程图
Vue 3 × React 组件关系与数据流

滚轮缩放 · 按住拖动 · 双击重置 · Esc 关闭

完整 Demo 源码

以下代码直接读取在线 Demo 使用的源文件,没有省略或改写。

React 源码

ReactDemo.tsx
import { useState } from "react";type Profile = {  name: string;  score: number;};export function ReactDemo() {  const [count, setCount] = useState(0);  const [profile, setProfile] = useState<Profile>({    name: "小明",    score: 0,  });  function increment() {    setCount((current) => current + 1);    setProfile((current) => ({      ...current,      score: current.score + 1,    }));  }  function reset() {    setCount(0);    setProfile((current) => ({ ...current, score: 0 }));  }  return (    <div className="demo-stack">      <div className="demo-card">        <span className="demo-tag">useState</span>        <h2>{profile.name}的计数器</h2>        <p>count:{count}</p>        <p>score:{profile.score}</p>      </div>      <div className="demo-actions">        <button className="demo-button" type="button" onClick={increment}>          同时加一        </button>        <button className="demo-button" type="button" onClick={reset}>          重置        </button>      </div>    </div>  );}

Vue 3 源码

VueDemo.vue
<script setup lang="ts">import { reactive, ref } from "vue";const count = ref(0);const profile = reactive({  name: "小明",  score: 0,});function increment() {  count.value += 1;  profile.score += 1;}function reset() {  count.value = 0;  profile.score = 0;}</script><template>  <div class="demo-stack">    <div class="demo-card">      <span class="demo-tag">ref / reactive</span>      <h2>{{ profile.name }}的计数器</h2>      <p>count:{{ count }}</p>      <p>score:{{ profile.score }}</p>    </div>    <div class="demo-actions">      <button class="demo-button" type="button" @click="increment">        同时加一      </button>      <button class="demo-button" type="button" @click="reset">重置</button>    </div>  </div></template>

在线观察

两个计数器维护相同的数字与对象状态。重点观察 React 如何替换对象,Vue 如何修改响应式属性。

React

useState

小明的计数器

count:0

score:0

Vue 3

ref / reactive

小明的计数器

count:0

score:0

常见误区

  • 不要直接修改 React state;旧对象引用可能让 React 无法可靠判断更新边界。
  • 解构 reactive 对象的基本类型属性会失去响应式连接,需要保留对象访问或使用 toRefs。
  • 新值依赖旧值时,React 优先使用函数式 setter,避免闭包中的旧快照。
  • Vue 模板会自动解包 ref,但普通 TypeScript 代码仍需读取 .value。

原理见响应式系统与状态更新模型;需要从现有状态计算新值时继续阅读派生状态。