我在React状态中嵌套了空字符串数组。
function App() {
const emptyWord = Array(5).fill("");
const initialArr = Array(5).fill(emptyWord);
const [words, setWords] = useState(initialArr);
我试着像这样更新它们(索引只是一个例子):
const handleInput = input => {
const currWords = words;
currWords[0][2] = input;
setCurrLetter(input);
setWords(currWords);
}
在words
中不是只更新索引为0的数组,而是更新每个数组。我尝试了不同的方法,也使用了扩展运算符,但无法使其正常运行。什么好主意吗?
您的代码有几个问题。您面临的问题是,.fill()
为每个索引使用相同的emptyWord
数组引用填充您的数组。您想要更改这一点,以便为每个元素创建一个新的唯一的内部数组,您可以使用Array.from()
及其映射函数:
const [words, setWords] = useState(() => Array.from(
{length: 5}, () => Array(5).fill("")
));
你会注意到我把数组创建逻辑放在useState()
钩子内,这样你就不会在每次App
渲染时不必要地重新创建数组。
现在你有独特的每个索引数组,你不会经历的问题每个数组更新每次更新其中之一。
然而,你的代码仍然有一个问题,你直接改变你的状态,因为const currWords = words;
不复制你的数组。直接修改你的状态可能会导致渲染问题,React不会更新你的UI来反映新的状态。要不可变地更新状态,你应该为想要更新的项创建一个带有新内部元素的新数组,而不是直接更新状态。这可以用.map()
来完成,例如:
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
));
}
您也可以使用JSON.stringify()
+JSON.parse()
1进行深度复制,但它不会像上面显示的.map()
选项那样有效:
const currWords = JSON.parse(JSON.stringify(words));
currWords[0][2] = input;
setCurrLetter(input);
setWords(currWords);
1:如果你可以支持它,你可以使用structuredClone()
代替。