skip to Main Content

I am new to React, and have started with the Tic Tak Toe tutorial within the React docs.

I am trying to create 3 boardRows and 3 columns wide of squareButtons.

Please let me know if what I am trying to do is a normal thing, and also if there are better ways of doing it/approaching it.

I would be very grateful, thank you

This is what this code is returning, and below is my code:
Incorrect numbering

import {useState} from "react";

export default function Board() {
    let buttonId = 1;
    let boardRowIndex = 0;

    function SquareButton({ id }) {
        return <button className="square">{id}</button>;
    }
    
    function BoardRow() {
        const squareButtons = [...Array(3).keys()].map(() => {
            const squareButton = <SquareButton key={buttonId - 1} id={buttonId} />;
            
            buttonId++;
            
            return squareButton;
        });
        
        return (
            <div className="board-row">
                { squareButtons }
            </div>
        );
    }
    
    const boardRows = [...Array(3).keys()].map(() => {
        const boardRow = <BoardRow key={boardRowIndex}/>;

        boardRowIndex++;

        return boardRow;
    });
        
    
    // The first squareButton begins at 4 now for some reason, and then skipping out numbers that aren't being displayed
    return (
        <>
            { boardRows }
        </>
    );
}

I have tried debugging in devtools, and this line

const boardRows = [...Array(3).keys()].map(() => {

seems to get hit 2 times.

I am not sure why, but perhaps due to a re-render?

It is supposed to be 3 rows by 3 columns, but the numbering should be 1 – 9.

Thank you

2

Answers


  1. buttonId and boardRowIndex for all the buttons and rows are sam here. When you increment buttonId in one row, it affects the numbering in the another rows.

    Try to create a method which create id for you createId maintain separate buttonId values for each row and calculate the id values accordingly.

    Try below code.

    import React from 'react';
    
    export default function Board() {
      const createId = () => {
        return new Array(3).fill(null).map(() => new Array(3).fill(null));
      };
    
      const ids = createId();
      let currentId = 1;
    
      const SquareButton = ({ id }) => {
        return <button className="square">{id}</button>;
      };
    
      const BoardRow = ({ rowIds }) => {
        const squareButtons = rowIds.map((id) => {
          return <SquareButton key={id} id={id} />;
        });
    
        return (
          <div className="board-row">
            {squareButtons}
          </div>
        );
      };
    
      const boardRows = ids.map((rowIds) => {
        return <BoardRow key={currentId} rowIds={rowIds} />;
      });
    
      return (
        <>
          {boardRows}
        </>
      );
    }
    
    Login or Signup to reply.
  2. The reason why you are getting strange results when mapping over a child component and a parent component in React is because you are recreating the child component on every render of the parent component. This is because you are using the key prop to generate a unique key for each child component, but you are not passing the id prop to the child component.

    To fix this, you can pass the id prop from the parent component to the child component using the key prop. This will ensure that the child component is only recreated when the id prop changes.

    import { useState } from "react";
    
    export default function Board() {
      let buttonId = 1;
      let boardRowIndex = 0;
    
      function SquareButton({ id }) {
        return <button className="square">{id}</button>;
      }
    
      function BoardRow() {
        const squareButtons = [...Array(3).keys()].map((i) => {
          const squareButton = <SquareButton key={i} id={buttonId} />;
    
          buttonId++;
    
          return squareButton;
        });
    
        return (
          <div className="board-row">
            {squareButtons}
          </div>
        );
      }
    
      const boardRows = [...Array(3).keys()].map((i) => {
        const boardRow = <BoardRow key={i} />;
    
        return boardRow;
      });
    
      // The first squareButton begins at 4 now for some reason, and then skipping out numbers that aren't being displayed
      return (
        <>
          {boardRows}
        </>
      );
    }
    

    There are a few other ways to approach this problem. One way is to use a state management library like Redux to manage the state of the board. This would allow you to keep track of the id and other state of the board in a centralized location, and to update the state of the board without having to re-render the entire component tree.

    Another way to approach this problem is to use a virtual DOM library like React Fiber. React Fiber allows you to update the DOM without having to re-render the entire component tree. This can make your application faster and more responsive.

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