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:
- why isn't the first log only full of empty strings?
- 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.