skip to Main Content

I am new to React. My problem is with 2 useStates I have in my program which creates tic-tac-toe field.

import {useState} from "react";

// Fix bug with check and setCheck

export default function FieldCell() {
    const [value, setValue] = useState('');
    const [check, setCheck] = useState(0);

    const handleClick = () => {
        if (check % 2 === 0) {
            setValue('X');
        }
        else {
            setValue('O');
        }
        console.log(check)
        setCheck(check + 1);
    }

    return(
        <td className="field_cell"><button onClick={handleClick}>{value}</button></td>
    );
}

first useState sets the value, either X or O, seconde one should decide order (first X then O). But I faced the issue that it counts clikc on each button seperately. But it should be like ‘global’ for all buttons and change order ( on even check – ‘X’, on odd – ‘O’ ).

I tried to call setcheck in different positions: in if statement, in else statement and in both. It obviously didn’t work.

3

Answers


  1. you need to make sure that you’re using the updated value of check when you decide whether to set ‘X’ or ‘O’, becasue the updates might not be immediately reflected in the multiple calls to handleClick

    import React, { useState } from "react";
    export default function FieldCell() {
      const [value, setValue] = useState("");
      const [check, setCheck] = useState(0);
    
      const handleClick = () => {
        const newCheck = check + 1; // Increment before using the updated value
    
        if (newCheck % 2 === 0) {
          setValue("X");
        } else {
          setValue("O");
        }
    
        setCheck(newCheck);
      };
    
      return (
        <td className="field_cell">
          <button onClick={handleClick}>{value}</button>
        </td>
      );
    }
    
    Login or Signup to reply.
  2. You have to update value and check on the click of the button as:

    Simplest way will be to reset its state, since there gonna be two player and at any time there gonna be a single player whose turn will be. So based on that you can set its state.

    const handleClick = () => {
      const isEven = !check;
      setValue(isEven ? "X" : "O");
      setCheck(isEven ? 1 : 0);
    };
    
    Login or Signup to reply.
  3. You’ve already stated the solution to the problem without realizing it. Like you said the state should be ‘global’.

    The issue is that each button/cell has it’s own independent state because of the way React works, so you need to "lift state up" to a higher component and then pass it down as props to the cells

    Let me show you what I mean:

    //In Table.jsx
    //Ensure Table.jsx and FieldCell.jsx are in the same directory level for the import to work
    import { useState } from "react";
    import FieldCell from "./FieldCell";
    
    export default function Table() {
        const [value, setValue] = useState('');
        const [check, setCheck] = useState(0);
    
        const handleClick = () => {
            if (check % 2 === 0) {
                setValue('X');
            }
            else {
                setValue('O');
            }
            setCheck(check + 1);
        }
    
        return(
            <table>
              <tr>
                <FieldCell handleClick={handleClick} value={value} />
                <FieldCell handleClick={handleClick} value={value} />
                <FieldCell handleClick={handleClick} value={value} />
              </tr>
              <tr>
                <FieldCell handleClick={handleClick} value={value} />
                <FieldCell handleClick={handleClick} value={value} />
                <FieldCell handleClick={handleClick} value={value} />
              </tr>
              <tr>
                <FieldCell handleClick={handleClick} value={value} />
                <FieldCell handleClick={handleClick} value={value} />
                <FieldCell handleClick={handleClick} value={value} />
              </tr>
            </table>
        );
    }
    
    //In FieldCell.jsx
    export default function FieldCell({ handleClick, value }) {
        return(
            <td className="field_cell"><button onClick={handleClick}>{value}</button></td>
        );
    }
    

    Try this and see what happens.
    I recommend going through the wonderful tutorial at https://www.react.dev

    #react.js #javascript

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search