2

So I'm learning react at the moment and I've been struggling with this issue.. I'm trying to do tic-tac-toe so I've got this code:

import './App.css';
import { useState } from "react"

const X = 1;
const O = -1;
const EMPTY = 0;

var Square = ({idx, click}) => 
{
    let [val, setVal] = useState(EMPTY);
    return (
        <button onClick={() => {click(setVal, idx);}}>{val}</button>
    )
}

var Logger = ({state}) =>
{
    return (
        <button onClick={() => {console.log(state);}}>log</button>
    )
}

var App = () =>
{
    let [turn, setTurn] = useState(X);
    let state = new Array(9).fill(EMPTY);
    let squares = new Array(9);

    let click = (setValFunc, idx) => 
    {
        setTurn(-turn);
        setValFunc(turn);
        state[idx] = turn;
    }

    for (let i = 0 ; i < 9 ; i++)
    {
        squares[i] = (<Square click={click} idx={i}/>);
    }

    return (
        <>
        <Logger state={state} />
        <div>
            {squares}
        </div>
        </>
    )
}

export default App;

so the squares ARE changing as I click them, but when I click the log button to log the state array to the console, the state array remains all zeros.

what am I missing here?

yoyobara
  • 101
  • 1
  • 5

2 Answers2

1

Your state has to be a React state again. Otherwise, the state you defined inside the App as a local variable only lasts until the next rerender.

  1. Maintain tic-tac-toe state inside a useState hook
let [state, setState] = useState(new Array(9).fill(EMPTY));
  1. Update the click handler accordingly.
  let click = (setValFunc, idx) => {
    setTurn(-turn);
    setValFunc(turn);
    setState((prevState) =>
      prevState.map((item, index) => (index === idx ? turn : item))
    );
  };

Edit agitated-mountain-cfu7o3

Amila Senadheera
  • 12,229
  • 15
  • 27
  • 43
0

In React, the state concept is important.

In your case, you need to understand what is your state and how you can model it.

If you are doing a Tic-Tac-Toe you will have:

  • the board game: a 3 by 3 "table" with empty, cross or circle signs

This can be modeled by an array of 9 elements as you did.

But then you need to store this array using useState otherwise between -re-renders your state array will be recreated every time.

I advise you to read https://reactjs.org/docs/lifting-state-up.html and https://beta.reactjs.org/learn.

Gabriel Pichot
  • 2,325
  • 1
  • 22
  • 24