Home > Software design >  Can't set state to a string in React
Can't set state to a string in React

Time:11-11

Literally what the title says. I don't know where I'm wrong.


import { useState, useEffect, useRef } from "react";

const Gameboard = () => {
  const [grids, setGrids] = useState([]);
  const [snake, setSnake] = useState([100, 101]);
  const [direction, setDirection] = useState('what');
  const gameBoardRef = useRef(true);
  const gameBoardChildren = grids.map(grid => (
    <div key={ grid }></div>
  ));
  
  const startInterval = () => {
    window.addEventListener('keydown', e => switchDirection(e));
    const gridsArray = Array.from(gameBoardRef.current.children);
    setInterval(() => {
      setSnake(prevState => {
        let temp = [];
        prevState.forEach(piece => {
          piece  ;
          temp.push(piece);
          gridsArray[piece].style.backgroundColor = 'black';
        });
        gridsArray[prevState[0]].style.backgroundColor = '';
        console.log(temp)
        return temp;
      })
    }, 1000);
  };

  const switchDirection = (e) => {
    console.log(e.keyCode);
    if (e.keyCode === 37) {
      console.log(direction);
      return setDirection('left');
    };

    if (e.keyCode === 40) {
      console.log(direction);
      return setDirection('down');
    };

    if (e.keyCode === 39) {
      console.log(direction);
      return setDirection('right');
    };
    
    if (e.keyCode === 38) {
      console.log(direction);
      return setDirection('up');
    };
  }
  
  useEffect(() => {
    let temp = [];
    for (let i = 0; i < 196; i  ) {
      const grid = i;
      temp.push(grid);
    };
    setGrids(temp);
  }, []);
  
  return (
    <div>
      <button onClick={startInterval}>Click me</button>
      <div className="game-board" ref={gameBoardRef}>{ gameBoardChildren }</div>
    </div>
  );
}
 
export default Gameboard;

I've got no error messages. I tried everything literally. Assigning the direction values to a variable then setting the state to that var. I tried this with another state and the same thing happened. It either stays what the initial value was or if there was no value it's unidentified.

CodePudding user response:

I think you're updating with setDirection correctly.

The direction in the event callback however, is always the initial copy of it (the state in the component is updated by React, but the event callback gets its copy of the state when it was created and kept it due to closure), hence the console.log(direction) always print the initial value.

Here is an isolated part of the code for example, or visit the live here: stackblitz you might need to run the live demo in a new tab to see the logs.

import React, { useState } from 'react';

export default function App() {
  const [direction, setDirection] = useState('what');

  const handleStart = () =>
    window.addEventListener('keydown', (e) => switchDirection(e));

  const switchDirection = (e) => {
    console.log(e.keyCode);
    if (e.keyCode === 37) {
      console.log(`Value in the callback is: ${direction}`);
      setDirection('left');
    }

    if (e.keyCode === 40) {
      console.log(`Value in the callback is: ${direction}`);
      setDirection('down');
    }

    if (e.keyCode === 39) {
      console.log(`Value in the callback is: ${direction}`);
      setDirection('right');
    }

    if (e.keyCode === 38) {
      console.log(`Value in the callback is: ${direction}`);
      setDirection('up');
    }
  };

  return (
    <div>
      <h1>switch-direction</h1>
      <p>After click, compare value in the log and in below text</p>
      <button onClick={handleStart}>START</button>
      <p>{`Current direction is: ${direction}`}</p>
    </div>
  );
}

CodePudding user response:

the problem here is that you are creating the function to return set state wich is a function itself that doesnt return anything, Try this instead for switchDirection :

const switchDirection = (e) => {
    console.log(e.keyCode);
    if (e.keyCode === 37) {
       setDirection('left');
       console.log(direction);
    };

    if (e.keyCode === 40) {          
      setDirection('down');
      console.log(direction);
      
    };

    if (e.keyCode === 39) {         
      setDirection('right');
      console.log(direction);
    };
    
    if (e.keyCode === 38) {          
      setDirection('up');
      console.log(direction);
    };
  }

CodePudding user response:

I prefered use a switch-case statement instead of if clause

 const switchDirection = (e) => {
  let newDirection;
  switch (e.keyCode) {
    case 37:
      newDirection = 'left';
      break;
    case 40:
      newDirection = 'down';
      break;
    case 39:
      newDirection = 'right';
      break;
    case 38:
      newDirection = 'up';
      break;
    default:
      newDirection = undefined;
  }
  console.log(e.keyCode, newDirection);
  if (direction) setDirection(newDirection);
};
  • Related