Home > Enterprise >  Change attribute from object using requestAnimationFrame in React
Change attribute from object using requestAnimationFrame in React

Time:07-30

I trying to update human.x using requestAnimationFrame and useState. I want to add elements called "humans" and use requestAnimationFrame to update the position to humans walk in "world" (using css properties). The method addHumans work but requestAnimationFrame update and empty my list.

World.tsx

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

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

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

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

    const animate = () => {
        setHumans(humans?.map((human, i) => {
            return {...human, x: human.x   1}
        }));
        // console.log(humans)
        requestAnimationFrame(animate);
    }

    useEffect(() => {
        requestAnimationFrame(animate);
    }, []); // run once

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

Human.tsx

export default function Human(props: any) {
    
    return (
        <div key={props.id} className="human" style={{ top: props.y   'px', left: props.x   'px', backgroundColor: props.color }}>{props.id}</div>
    )
}

CodePudding user response:

This is called a stale state. Update your code like this:

setHumans(humans => humans?.map((human, i) => {
  return {...human, x: human.x   1}
}));
  • Related