0

I'm a beginner at React and I wanna go step by step using official tutorial: create Tic Tac Toe game. I have a hard time because I learn using functions, not Classes. When i try to implement it i get an error " Line 7:5: 'setSquares' is not defined". I think i need to pass some data from RenderSquare function to handleClick but i don't know how to do it..This is official example provided by React people:

enter image description here

My dumb code:

import Square from './Square';
import { useState } from 'react';

function handleClick(i) {
     const squares = squares.slice();
     squares[i] = 'X';
     setSquares({ squares });
}

 function RenderSquare(i) {
 const [squares, setSquares] = useState(Array(9).fill(null));

return (
    <>
        <Square
            value={squares[i]}
            onClick={() => {
                handleClick(i);
            }}
        />
        ;
    </>
   );
 }
1
  • 1
    you need to put the handleClick function inside the RenderSquare functional component. Currently, the handleClick function is outside of scope of RenderSquare. Commented May 29, 2021 at 17:38

1 Answer 1

1

Define handleClick in the body of the component, so that handleClick will have scope of setSquares.

setSquares({ squares }); should also be setSquares(squares);, since the state is an array, not an object.

function RenderSquare(i) {
    const [squares, setSquares] = useState(Array(9).fill(null));
    function handleClick(i) {
        const squares = squares.slice();
        squares[i] = 'X';
        setSquares(squares);
    }
    return (
        <>
            <Square
                value={squares[i]}
                onClick={() => {
                    handleClick(i);
                }}
            />
       ;
        </>
    );
}

I think the const [squares, setSquares] = useState line should also be in the parent component and passed down to the child - you don't want an array of squares for every square rendered, you want only a single array of squares.

const App = () => {
    const [squares, setSquares] = useState(Array(9).fill(null));
    return squares.map((val, i) => <Square {...{ i, squares, setSquares }} />);
};
function RenderSquare({ i, squares, setSquares }) {
    function handleClick() {
        const squares = squares.slice();
        squares[i] = 'X';
        setSquares(squares);
    }
    return (
        <>
            <Square
                value={squares[i]}
                onClick={() => {
                    handleClick(i);
                }}
            />
       ;
        </>
    );
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much! But i have a question, if i would need to pass these data, like having 2 separate .js files, how would i do it?
Through the props, usually - like in the second snippet in the answer, I'm passing i, squares, setSquares as props from the parent to the child.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.