Home > database >  React setStates only updates state once and resets it
React setStates only updates state once and resets it

Time:12-22

Hello im kinda new to React im trying to make a kinda snake game, but im struggling at the movement.

the x and y value are never realy changed he is only able to move a like 1 gridcell but when i press another key he jsut goes to the starting position and goes 1 cell in the other direction.. what am i missing?

function App() {

    const [_x, setX] = useState(0);
    const [_y, setY] = useState(0);

    let lastPressedKey = '';
    let gameTicker = null;


    function triggerMovement(x, y) {
        if (lastPressedKey === 100)
            move(10, 0);

        if (lastPressedKey === 97)
            move(-10, 0);

        if (lastPressedKey === 119)
            move(0, 10);

        if (lastPressedKey === 155)
            move(0, -10);
    }

    function move(x, y){
        console.log(lastPressedKey);
        console.log(x, _x, y, _y);
        setX(_x   x);
        setY(_y   y);
    }

    function handleKeyEvent(event) {
        lastPressedKey = event.keyCode;
    }

    function startTimer() {
        gameTicker = setInterval(triggerMovement, 1000);
    }

    function clearTimer() {
        clearInterval(gameTicker)
    }

    const element = (
        <div>
            <Screen farbe="darkslategray">
                <Snake x={_x} y={_y} farbe="red"/>
            </Screen>
            <button onClick={startTimer} style={{
                bottom: 5,
                position: 'absolute'
            }}>
                Start Game
            </button>
            <button onClick={clearTimer} style={{
                bottom: 5,
                left: 625,
                position: 'absolute'
            }}>
                StopGame
            </button>
        </div>
    )

    window.addEventListener('keypress', handleKeyEvent, true);

    return element;
}

function Snake(props){

    const [x, setX] = useState(250);
    const [y, setY] = useState(250);
    let speed = props.speed;

    const element = (
        <div style={{
            width: 10,
            height: 10,
            backgroundColor: props.farbe,
            position: 'absolute',
            left: props.x,
            bottom: props.y
        }}>

        </div>
    )
    return element;
}

Really trying to get behind this, but I'm trying to get this snake to move since this morning idk what I'm missing here.

The console logs are always

10, 0 , 0 , 0
10, 0 , 0 , 10
10, 0 , 0 , 0 ... 

CodePudding user response:

It is because of stale closures.

Here

function move(x, y){
    console.log(lastPressedKey);
    console.log(x, _x, y, _y);
    setX(_x   x);
    setY(_y   y);
}

_x and _y are referencing values from the render in which you called the startTimer function.

You can use functional form of setState to avoid this problem:

setX(ps => ps x)
  • Related