【发布时间】:2021-03-02 00:13:12
【问题描述】:
所以我开始学习 React,在做了一些基础知识(计数器、待办事项列表)之后,我决定做一些更具挑战性的事情;一个棋盘,棋子可以通过点击来移动。我的主要组件是Chessboard。然后它呈现可能包含Piece 的Tiles。游戏信息存储在Chessboard's 状态,如下所示:
interface State {
board: Record<string, pieceInterface>;
isPieceMoving: boolean;
movingPieceId: string;
}
我在Chessboard's 方法onTileClick(id: string) 中处理移动件。它作为道具传递给Tile,当点击一个图块时,它会用一个图块ID(如“a4”、“f6”、“h3”)调用。它具有以下逻辑。游戏可以处于两种状态:我当前正在移动一个棋子,或者我当前什么都不做,然后通过单击它开始移动棋子。当我开始移动一块时,我将它的 ID(或者更确切地说是女巫架上的瓷砖的 ID)存储在 state.movingPieceId 中。当我尝试放置它时,我会检查磁贴是否为空,然后相应地更改state.board。这是我的代码:
onTileClick = (id: string): void => {
if (!this.state.isPieceMoving) {
if (this.state.board[id]) {
this.setState({
isPieceMoving: true,
movingPieceId: id,
});
}
} else {
if (!this.state.board[id]) {
this.setState((state) => {
let board: Record<string, pieceInterface> = state.board;
const piece: pieceInterface = board[state.movingPieceId];
delete board[state.movingPieceId];
board[id] = piece;
// console.log(board[id]);
// console.lob(board);
const isPieceMoving: boolean = false;
const movingPieceId: string = "";
return { board, isPieceMoving, movingPieceId };
});
}
}
};
第一部分工作得很好。但是在第二个中有一些错误,我找不到。当我取消注释此控制台日志时,输出如下所示(我想将一块从“a2”移动到“a3”):
Object { "My piece representation" }
Object {
a1: { "My piece representation" },
a3: undefined,
a7: { "My piece representation" },
...
}
我的代码正确地从“a2”中“获取”点击的部分(板没有“a2”属性),但它显然没有将其放回原处。即使打印board[id] 也会给出正确的对象!我正在移动日志行 console.log(board) 以查看错误发生的位置。即使我把它直接放在 else 后面,它仍然说“a3”是undefined。
我花了几个小时试图了解发生了什么。我试图在控制台中模拟这段代码,但它总是有效!谁能向我解释我做错了什么?这是我还没学过的奇怪的 React 的 setState 机制吗?还是我不知道的一些基本的javascript东西?任何帮助我们都会很高兴,因为我被困在这里无法继续前进并做任何其他事情。
编辑#1
好的。所以我能够通过深度复制 state.board 到board 来修复这个错误(灵感来自@Linda Paiste 的评论)。我只是使用了简单的 JSON stringify/parse hack:
let board: Record<string, pieceInterface> = JSON.parse(JSON.stringify(state.board));
这修复了错误,但我不知道为什么。我会保持这个问题的开放,所以也许有人会向我解释 what 和 为什么 我以前的代码有问题。
编辑#2
好的。感谢@Linda 的解释和阅读the docs 我终于明白我做错了什么。琳达在下面的答案(接受的答案)中做了详细的解释。非常感谢大家!
【问题讨论】:
-
执行控制台日志记录时 id 是否等于“a3”?你能验证一下吗?
-
@ViktorW 是的。
-
delete board[state.movingPieceId]; -
您的别名
board变量与state.board引用同一个对象,因此您不能以任何方式对其进行变异。 -
他们删除了board中的字段“a2”,并设置了字段“a3”。 a2 确实丢失了,这是应该的,但 a3 也是未定义的。
标签: javascript reactjs typescript setstate