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

React中使用requestAnimationFrame更新对象属性时列表被清空问题

问题解决:requestAnimationFrame更新时清空humans列表

问题根源

animate函数在组件初始化时被useEffect调用,形成闭包捕获了初始状态的空humans数组。后续每次执行requestAnimationFrame时,都会基于这个空数组调用setHumans,导致新添加的人类被覆盖清空。

修复方案

  1. 使用函数式更新状态:调用setHumans时传入回调函数,直接获取最新的状态值,避免闭包陷阱
  2. 修正类型导入错误:移除错误的import IHuman from './Human',类型已在组件内定义
  3. 移除子组件冗余key:key属性应在父组件的map循环中设置,子组件无需重复定义

修改后的代码

World.tsx

import { useState, useEffect } from 'react'
import Human from './Human'

type IHuman = {
    id: number;
    x: number;
    y: number;
    color: string;
}

export default function World() {
    const [humans, setHumans] = useState<IHuman[]>([])

    const addHuman = () => {
        setHumans(prevHumans => [...prevHumans, {id: Math.random(), x: 0, y: 0, color: 'red'}])
    }

    const animate = () => {
        // 使用函数式更新,获取最新的humans状态
        setHumans(prevHumans => 
            prevHumans.map(human => ({...human, x: human.x + 1}))
        );
        requestAnimationFrame(animate);
    }

    useEffect(() => {
        const animationId = requestAnimationFrame(animate);
        // 组件卸载时取消动画,避免内存泄漏
        return () => cancelAnimationFrame(animationId);
    }, []);

    return (
        <>
            <button onClick={addHuman}>new human</button>
            <main>
                {humans.map(human => (
                    <Human 
                        key={human.id} 
                        x={human.x} 
                        y={human.y} 
                        color={human.color} 
                    />
                ))}
            </main>
        </>
    )
}

Human.tsx

export default function Human(props: {
    id: number;
    x: number;
    y: number;
    color: string;
}) {
    return (
        <div 
            className="human" 
            style={{ 
                top: `${props.y}px`, 
                left: `${props.x}px`, 
                backgroundColor: props.color 
            }}
        >
            {props.id}
        </div>
    )
}

额外优化说明

  • 给Human组件添加了明确的类型定义,替代原有的any类型,提升类型安全性
  • 在useEffect中添加了动画取消逻辑,防止组件卸载后动画继续运行导致内存泄漏
  • addHuman也改用函数式更新,确保在并发更新场景下的状态正确性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 14:15:41