Home > Blockchain >  what is causing this surprising array result in React
what is causing this surprising array result in React

Time:11-14

I'm sure this isn't surprising to some out there, but I am getting something very unexpected in the following component:

const GameBoard = ({
    moves = [[1,2]]
}:Props) => {

    const [sideLength, setSideLength] = useState(3);


    let rows = Array(sideLength).fill(Array(sideLength).fill(''));
    console.log(rows);
    for(let i = 0; i < moves.length; i  ){
        const [y,x] = moves[i];
        const mark:Mark = i % 2 === 0 ? 'X' : 'O';
        rows[y][x] = mark;
    }
    console.log(rows);
    return (
        <div className="game-board">
            { rows.map(row => <Row row={row}/>)};
        </div>
    );
};

This component represents a tic tac toe gameboard. A prop called moves should determine where markings are made on the board. In the following line, I start with a blank board: let rows = Array(sideLength).fill(Array(sideLength).fill('')); And then I populate the rows with markings based on moves. [[1,2]] means that only the first move has been made (X according to the rules), and it was placed one down and 2 over.

I expect the console.log after let rows... to log:

    [ '', '', '']
    ['', '', '']
    ['', '', '']

Instead, both this line and the log after the for loop logs the following: 0 :

['', '', 'X']
['', '', 'X']
['', '', 'X']

So my questions are:

  1. why isn't the first log only full of empty strings?
  2. why is an entire column of the second log filled instead of just one square ([2,1])?

https://codesandbox.io/s/muddy-bash-shdpoi?file=/src/App.js

CodePudding user response:

Re. 1: it actually is! The issue you are probably facing is that you are looking at the console in the browser. There, the content of a printed object may change after the printing to the console. If instead of console.log(rows) you use console.log(JSON.stringify(rows)) you'll see that it actually is what you expected (all empty strings).

Re. 2: This is because you are initializing all three top level array element with the same array (it's a reference!). This is even shown in the MDN documentation of the Array.fill method, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill#using_fill:

// A single object, referenced by each slot of the array:
const arr = Array(3).fill({}); // [{}, {}, {}]
arr[0].hi = "hi";              // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]

You'll need to create three different arrays to fill the top level array with.

  • Related