【发布时间】:2020-02-08 06:23:11
【问题描述】:
我知道 useState 是异步的。请在回答之前阅读完整的问题。
我正在尝试使用useState 修改数组中的一个元素,但它没有按预期工作。
数组和修改它的函数:
const [table, setTable] = useState(['blue', 'blue', 'blue', 'blue', 'blue']);
let currentShapePosition = 2;
function printTable() {
let newTable = [...table];
// let newTable = table;
newTable[currentShapePosition] = 'red';
setTable(newTable);
console.log('printTable newTable', newTable); // <-- the result is as expected
// log => printTable newTable ["blue", "blue", "red", "blue", "blue"]
console.log('printTable table', table); // <--- The problem is here. I don't get why the array never update
// log => printTable newTable ["blue", "blue", "blue", "blue", "blue"]
}
因为useState 是异步的,所以我知道数组可能不会立即更改,但是在printTable 函数内部,console.log 即使经过多次重新渲染,结果也是一样。
当而不是:
let newTable = [...table]
我这样做:let newTable = table
然后在函数中生成的console.log中更新状态,但没有重新渲染/组件更新。
我想了解为什么在第一种情况下newTable = [...table] 函数内部的console.log 结果在多次重新渲染后是相同的。
为什么在第二种情况下newTable = table 尽管setTable(newTable) 没有重新渲染组件。
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "./style.css";
const App = () => {
let currentShapePosition = 2;
const [table, setTable] = useState(["blue", "blue", "blue", "blue", "blue"]);
useEffect(() => {
printTable();
window.addEventListener("keydown", handleKeyPress);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
console.log("render", table);
});
function printTable() {
let newTable = [...table];
// let newTable = table;
newTable[currentShapePosition] = "red";
setTable(newTable);
console.log("printTable newTable", newTable); // <-- the result is as expected
console.log("printTable table", table); // <--- The problem is here. I don't get why the initial value never change
}
function handleKeyPress(event) {
switch (event.key) {
case "Left": // IE/Edge specific value
case "ArrowLeft":
moveShape(-1);
break;
case "Right": // IE/Edge specific value
case "ArrowRight":
moveShape(1);
break;
default:
return;
}
}
function moveShape(direction) {
currentShapePosition += direction;
printTable();
}
return (
<table className="tetris-table">
<tbody>
<tr>
<td className={table[0]} />
<td className={table[1]} />
<td className={table[2]} />
<td className={table[3]} />
<td className={table[4]} />
</tr>
</tbody>
</table>
);
};
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
【问题讨论】:
-
不是重复的,请大家看问题
-
如果不是骗子,那就是缺少minimal reproducible example...
-
它在代码沙箱中有一个例子,我相信它是因为闭包而发生的,但我承认我不是 100% 接受它。
-
我在控制台中看到了这些值:printTable newTable ["blue", "blue", "red", "blue", "blue"] printTable table ["blue", "blue", "blue", "blue", "blue"] 渲染 ["blue", "blue", "red", "blue", "blue"] 我认为在第二种情况下它不应该总是 "blue" .
标签: javascript reactjs react-hooks setstate