如何跨多个 React Redux 组件使用 requestAnimationFrame 实现游戏循环?

2024-06-02

努力思考最好的解决办法。我可以使用递归调用requestAnimationFrame有一个游戏循环:

export interface Props {
    name: string;
    points: number;
    onIncrement?: () => void;
    onDecrement?: () => void;
}

class Hello extends React.Component<Props, object> {

    constructor(props: Props) {
        super(props);
    }

    render() {
        const { name, points, onIncrement, onDecrement } = this.props;

        return (
            <div className="hello">
                <div className="greeting">
                    Hello {name + points}
                </div>
                <button onClick={onDecrement}>-</button>
                <button onClick={onIncrement}>+</button>
            </div>
        );
    }

    componentDidMount() {
        this.tick();
    }

    tick = () => {
        this.props.onIncrement();
        requestAnimationFrame(this.tick)
    }

}

但是如果我想要每一帧怎么办:

  • 组件 1 执行 X
  • 组件 2 执行 Y
  • Component3 做 Z

我可以在每个组件中再有一个循环,但是我的理解是,有多个循环是不好的做法requestAnimationFrame循环进行,这对性能有很大影响。

所以我在这里迷路了。如何让另一个组件使用相同的循环? (如果这是最好的方法的话!)


您需要一个调用的父组件requestAnimationFrame并迭代数组refs https://reactjs.org/docs/refs-and-the-dom.html需要在每个周期更新的子组件的数量,调用其update(或者你想怎么称呼它)方法:

class ProgressBar extends React.Component {

  constructor(props) {
    super(props);
    
    this.state = {
      progress: 0,
    };
  }
  
  update() {
    this.setState((state) => ({
      progress: (state.progress + 0.5) % 100,
    }));
  }  

  render() {
    const { color } = this.props;
    const { progress } = this.state;
    
    const style = {
      background: color,
      width: `${ progress }%`,
    };
    
    return(
      <div className="progressBarWrapper">
        <div className="progressBarProgress" style={ style }></div>
      </div>
    );  
  }
}

class Main extends React.Component {

  constructor(props) {
    super(props);
    
    const progress1 = this.progress1 = React.createRef();
    const progress2 = this.progress2 = React.createRef();
    const progress3 = this.progress3 = React.createRef();
    
    this.componentsToUpdate = [progress1, progress2, progress3];
    this.animationID = null;    
  }
  
  componentDidMount() {  
    this.animationID = window.requestAnimationFrame(() => this.update());  
  }
  
  componentWillUnmount() {
    window.cancelAnimationFrame(this.animationID);
  }
  
  update() {
    this.componentsToUpdate.map(component => component.current.update());
  
    this.animationID = window.requestAnimationFrame(() => this.update());  
  }
  
  render() {
    return(
      <div>
        <ProgressBar ref={ this.progress1 } color="magenta" />
        <ProgressBar ref={ this.progress2 } color="blue" />     
        <ProgressBar ref={ this.progress3 } color="yellow" />       
      </div>
    );
  }
}

ReactDOM.render(<Main />, document.getElementById('app'));
body {
  margin: 0;
  padding: 16px;
}

.progressBarWrapper {
  position: relative;
  width: 100%;
  border: 3px solid black;
  height: 32px;
  box-sizing: border-box;
  margin-bottom: 16px;
}

.progressBarProgress {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="app"></div>

但请记住,如果您尝试做的事情过于复杂并且想要击中60 fps,React 可能不是合适的工具。

Also, setState是异步的 https://medium.com/@wereHamster/beware-react-setstate-is-asynchronous-ce87ef1a9cf3,因此在调用它时,您只是将更新推送到 React 将在某个时刻处理的队列,这实际上可能会在下一帧或更晚的时间发生。

我分析了这个简单的例子,看看情况是否如此,实际上并非如此。更新被添加到队列中(enqueueSetState),但工作立即完成:

然而,我怀疑在实际应用程序中,React 有更多更新需要处理,或者在 React 的未来版本中,具有时间切片、具有优先级的异步更新等功能……渲染实际上可能发生在不同的帧中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何跨多个 React Redux 组件使用 requestAnimationFrame 实现游戏循环? 的相关文章

随机推荐

  • 如何在 Asp.NET MVC 中使用 RedirectToAction() 传递多个对象?

    我想使用redirectToAction 方法传递多个对象 下面是我重定向到的操作结果 public ActionResult GetEmployees Models Department department Models Categor
  • 如何为 flutter 绘图应用实现橡皮擦功能

    有一个关于通过 flutter 创建绘图应用程序的视频 YouTube https www youtube com watch v yyHhloFMNNA 它支持当用户点击屏幕时绘制线 点 但我找不到像 Android 本机那样擦除用户绘制
  • 分离 Fragment 和删除 Fragment 有什么区别?

    在 Android 文档中碎片交易 http developer android com reference android app FragmentTransaction html我注意到两种非常相似的方法 detach and remo
  • C# 编译器不会优化不必要的强制转换

    前几天 在写答案的时候这个问题 https stackoverflow com questions 2208315 why is any slower than contains在这里 关于溢出 我对 C 编译器感到有点惊讶 它没有按照我的
  • PHP 中正确的存储库模式设计?

    前言 我尝试在具有关系数据库的 MVC 架构中使用存储库模式 我最近开始学习 PHP 中的 TDD 并且我意识到我的数据库与应用程序的其余部分耦合得太紧密 我读过有关存储库并使用国际奥委会容器 http laravel com docs 4
  • 在 Windows 上使用 IPython 笔记本时出现 500 服务器错误

    我刚刚在 Windows 7 Professional 64 位上全新安装了 IPython 笔记本 我采取的步骤是 从以下位置安装 Python 3 4 1http python org http python org gt pip in
  • 为什么 VC++ 编译器 MOV+PUSH args 而不是仅仅 PUSH 它们? x86

    在 VC 的反汇编中 正在进行函数调用 编译器在压入本地指针之前将其 MOV 到寄存器 memcpy nodeNewLocation pNode sizeCurrentNode 0041A5DA 8B 45 F8 mov eax dword
  • “语言‘plpgsql’VOLATILE”是什么意思?

    当我在 Postgres 数据库中创建或更新函数或过程时 我看到LANGUAGE plpgsql VOLATILE在函数结束时 这意味着什么以及其目的是什么 From Postgres 文档 http www postgresql org
  • 配置jmxremote时无法正常停止tomcat

    我添加了一个jmxremotecatalina bat中的配置 set JAVA OPTS Dcom sun management jmxremote port 9004 Dcom sun management jmxremote ssl
  • 如何处理长期运行系统中旧的、过时的数据库数据?

    程序员有哪些可能性来处理很少使用但不能简单删除的数据 因为至少报告仍然需要它 我想到的一些例子 大学老年时期停止的资助类型 未使用的货币 例如意大利里拉 消失国家的名称 例如奥匈帝国 苏联 一些部分解决方案是活动标志 活动周期 可视化优先级
  • Jetty Plugin 9启动不喜欢icu4j-2.6.1.jar

    我对 mortbay 的 Maven jetty 插件 6 有相同的配置
  • 可可:NSView原点x在底部

    我正在以编程方式创建一个NSWindow以及其上的控件 看来原点 0 0 位于左下角 这对我来说很奇怪 来自其他 GUI 工具包 是否有一些标志 以便我可以更改它 使原点位于左上角 在 OS X 上 原点位于左下角 对于屏幕坐标和视图框架来
  • Get-AzureStorageBlob 抛出找不到您的 azure 存储凭据

    我刚刚开始使用 Azure 在使用 PowerShell cmdlet 处理我的存储帐户时遇到问题 我已经创建了一个存储帐户并在该存储帐户中创建了一个容器 接下来 我安装了 Azure Powershell SDK 和命令让等 并导入了pu
  • 无法在 Yahoo! 中输出 pubDate管道?

    在我在 Yahoo 上的 RSS 提要之一中Pipes 我使用 Date Formatter 模块并使用格式 K 来格式化日期 以便它们符合 pubDate 标准 在管道输出中 我的四个日期显示如下 Wed 25 Jul 2012 03 3
  • 将新元素添加到列表中

    我试图将一个新元素添加到列表中 如下所示 iex 8 gt l 3 5 7 7 8 3 3 5 7 7 8 3 iex 9 gt l 3 5 7 7 8 3 为什么我会排在第五位 8 3 它是什么意思 如何将新元素添加到列表中 Update
  • 如何在 OS X 上的旧版 Safari 中测试我的网站?

    苹果似乎不提供旧版本 Safari 的下载 我什至不确定它们是否会安装在 Mac OS X 上 因为 Safari 似乎是操作系统的一部分 就像 Windows 上的 Internet Explorer 一样 有什么方法可以在旧版本的 Sa
  • 更快地评估从右到左的矩阵乘法

    我注意到以二次形式评估矩阵运算右到左明显快于左到右在 R 中 取决于括号的放置方式 显然它们都执行相同的计算量 我想知道为什么会这样 这与内存分配有什么关系吗 A 5000 5000 B 5000 2 A matrix runif 5000
  • Mongoose 总是返回空数组? [复制]

    这个问题在这里已经有答案了 我是nodejs i的新手 我已经有一个名为aqi的数据库 集合名称为pln 我试图在网页上显示集合中的所有记录 但猫鼬总是返回空数组 我已经用其他数据库测试了它 但我可以从它们获取数据 但对于 pln mong
  • 等待异步 grunt 任务完成

    我收到了 grunt 设置 其中一个新任务应该执行 grunt task run 已经存在的任务 要执行的任务是异步的 新任务应该等待异步任务完成 执行此操作的首选方法是什么 grunt 已经涵盖了这一点 你应该将你的任务声明为异步任务 并
  • 如何跨多个 React Redux 组件使用 requestAnimationFrame 实现游戏循环?

    努力思考最好的解决办法 我可以使用递归调用requestAnimationFrame有一个游戏循环 export interface Props name string points number onIncrement gt void o