There are a few issues with your code. The issue you're facing is that .fill()
populates your array with the same emptyWord
array refrence for each index. You want to change this so that you create a new unique inner arrays for each element, which you can do with Array.from()
and it's mapping function:
const [words, setWords] = useState(() => Array.from(
{length: 5}, () => Array(5).fill("")
));
You'll notice that I've put the array creation logic inside of useState()
hook so that you don't recreate your array needlessly every time App
rerenders.
Now that you have unique arrays in each index, you won't experience the issue of having each array updated each time you update one of them.
However, your code still has an issue where you are mutating your state directly, as const currWords = words;
doesn't make a copy of your array. Modifying your state directly can cause rendering issues where React doesn't update your UI to reflect the new state. To immutably update your state you should be creating a new array with a new inner element for the item you want to update, and not updating your state directly. This can be done with .map()
for example:
const handleInput = input => {
const outerIdx = 0, innerIdx = 2;
setCurrLetter(input);
setWords(currWords => currWords.map((inner, i) => i === outerIdx
? inner.map((val, j) => j === innerIdx ? input : val)
: inner
));
}
You could also make a deep copy with JSON.stringify()
+ JSON.parse()
1, but it wouldn't be as efficient as the .map()
option shown above:
const currWords = JSON.parse(JSON.stringify(words));
currWords[0][2] = input;
setCurrLetter(input);
setWords(currWords);
1: If you can support it, you can use structuredClone()
instead.