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

ReactJS如何响应React树外的值?求Vue ref()/reactive()替代方案

React处理组件外响应式数据的方案

针对你在React中同步组件外实体数据的需求,有两种主流方案可以替代Vue的ref()/reactive():

1. 自定义订阅-发布模式

给你的Test类添加订阅机制,当数据变化时主动通知订阅的React组件,触发组件重渲染:

class Test {
  private health: number
  private subscribers: Set<(health: number) => void> = new Set()

  constructor() {
    this.health = 100
  }

  tick = () => {
    this.health -= 1
    this.notifySubscribers()
  }

  private notifySubscribers() {
    this.subscribers.forEach(callback => callback(this.health))
  }

  // 提供订阅方法,返回取消订阅的函数
  public subscribe(callback: (health: number) => void) {
    this.subscribers.add(callback)
    callback(this.health) // 订阅时立即同步当前值
    return () => this.subscribers.delete(callback)
  }

  public getHealth = () => this.health 
}

const instance = new Test()

在React组件中使用:

import { useState, useEffect } from 'react'

const Health = () => {
  const [health, setHealth] = useState(0)

  useEffect(() => {
    // 订阅health变化,组件卸载时自动取消订阅
    const unsubscribe = instance.subscribe(setHealth)
    return unsubscribe
  }, [])

  return <p>Health: {health}</p>
}

2. 使用React官方的useSyncExternalStore(React 18+)

这是React专门为同步外部数据源设计的Hook,比自定义订阅更规范,还能自动处理并发模式下的渲染问题:

先适配Test类的接口:

class Test {
  private health: number
  private subscribers: Set<() => void> = new Set()

  constructor() {
    this.health = 100
  }

  tick = () => {
    this.health -= 1
    this.subscribers.forEach(callback => callback())
  }

  public subscribe(callback: () => void) {
    this.subscribers.add(callback)
    return () => this.subscribers.delete(callback)
  }

  // 返回当前数据快照
  public getSnapshot() {
    return this.health
  }
}

const instance = new Test()

组件中使用:

import { useSyncExternalStore } from 'react'

const Health = () => {
  const health = useSyncExternalStore(
    instance.subscribe.bind(instance), // 订阅函数
    instance.getSnapshot.bind(instance), // 获取当前数据
    () => 100 // 服务端渲染时的初始值(可选)
  )

  return <p>Health: {health}</p>
}
大量帧更新场景下React的适用性

React完全适合游戏UI的大量帧更新场景,但需要注意以下优化点:

  • 精准控制重渲染:用上述方案让只有数据变化的组件触发重渲染,避免父组件更新导致所有子组件无意义刷新。
  • 利用批量更新:React 18默认会批量处理状态更新,即使在rAF循环中多次触发状态变化,也会合并为一次重渲染,降低性能开销。
  • 组件缓存:用React.memo包裹接收props的组件,减少不必要的重渲染。
  • 虚拟列表优化:如果需要展示成百上千个实体,使用虚拟列表库只渲染可视区域内的组件,大幅减少DOM操作成本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 01:40:33