I am rewriting ReactJS's "starter game" in ES6 with arrow functions (to remove the use of .bind()
, class properties and typescript.
Apparently in my code handleSquareClick
is triggered at rendering time, setState
is hence executed, resulting in error
错误:已超过最大更新深度。当组件重复调用componentWillUpdate或componentDidUpdate内部的setState时,可能会发生这种情况。 React限制了嵌套更新的数量,以防止无限循环。
为什么?
Game.tsx:
import React, { PureComponent } from 'react';
import Board from "../Board";
type State = {
history:
{
squares: Array<number>
}[];
currentStep: number;
xIsNext: boolean;
};
class Game extends PureComponent {
state: State = {
history: [{
squares: Array(9).fill(null)
}],
currentStep: 0,
xIsNext: true
};
calculateWinner(squares: Array<number>) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] !== null && squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
handleSquareClick = (i: any) => {
console.log(i);
// ...more code here
this.setState({
history: [...historyClone, { squares }],
currentStep: historyClone.length,
xIsNext: !xIsNext
});
};
render() {
const { history, currentStep } = this.state;
const current = history[currentStep];
return (
<div>
{ }
<Board
squares={current.squares}
handleSquareClick={this.handleSquareClick}
<
);
}
}
export default Game;
Board.tsx
import React, { PureComponent } from 'react';
import Board from "../Board"
type State = {
history:
{
squares: Array<number>
}[];
currentStep: number;
xIsNext: boolean;
};
class Game extends PureComponent {
state: State = {
history: [{
squares: Array(9).fill(null)
}],
currentStep: 0,
xIsNext: true
};
calculateWinner(squares: Array<number>) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] !== null && squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
handleSquareClick = (i: any) => {
console.log(i);
this.setState({
history: [...historyClone, { squares }],
currentStep: historyClone.length,
xIsNext: !xIsNext
});
};
render() {
const { history, currentStep } = this.state;
const current = history[currentStep];
return (
<div>
<Board
squares={current.squares}
handleSquareClick={this.handleSquareClick}
<
);
}
}
export default Game;