React issue. Rendering twice with strictMode

254 Views Asked by At

first of all im new in react and i've read the documentation, the rules of hooks. https://reactjs.org/docs/hooks-rules.html#explanation I know the component es mounted and unmounted with the strictMode but i dont understand in this case how can i fix it. Im trying to make a game in react, when you press left or right arrow key the position changes +1/-1 but with the double rendering the movements is being duplicated.

main

import * as React from 'react';
import { usePlayer } from './usePlayer';

import './style.css';

export default function App() {
  const [updatePlayerPos, player] = usePlayer();

  const move = (keyCode) => {
    console.log(keyCode);
    if (keyCode === 37) {
      updatePlayerPos({ x: 1, y: 0 });
    } else if (keyCode === 39) {
      updatePlayerPos({ x: -1, y: 0 });
    }
  };

  return (
    <div
      className="main"
      role="button"
      tabIndex="0"
      onKeyDown={(e) => move(e.keyCode)}
    >
      <h1>Hello StackBlitz!</h1>
      <p>Start editing to see some magic happen :)</p>
      <p>
        {player.pos.x} y {player.pos.y}
      </p>
    </div>
  );
}

my custom hook

import { useState } from 'react';

export const usePlayer = () => {
  const [player, setPlayer] = useState({
    pos: { x: 0, y: 0 },
  });

  const updatePlayerPos = ({ x, y }) => {
    console.log('updatePlayerPos');
    setPlayer((prev) => ({
      ...prev,
      pos: { x: (prev.pos.x += x), y: (prev.pos.y += y) },
    }));
  };

  return [updatePlayerPos, player];
};

i ve tried to re-write the functions but it didnt work. I know i can remove strictMode tag but i would like to understand why is failing and fix it, not just skip the strict mode tag

1

There are 1 best solutions below

1
damonholden On

You are mutating state in your setPlayer state updater function with the addition assignment (+=) operator. You should never mutate state in React:

setPlayer((prev) => ({
    ...prev,
    pos: { x: prev.pos.x + x, y: prev.pos.y + y },
}));