Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Reagent port of official React tutorial code for the Storing a History section https://facebook.github.io/react/tutorial/tutorial.html#storing-a-history
(defn Board [squares click-fn]
(let [renderSquare (fn [i]
[Square (get squares i) #(click-fn i)])]
[:div
[:div.board-row
[renderSquare 0]
[renderSquare 1]
[renderSquare 2]]
[:div.board-row
[renderSquare 3]
[renderSquare 4]
[renderSquare 5]
[:div.board-row
[renderSquare 6]
[renderSquare 7]
[renderSquare 8]]]))
(defn Game []
(let [history (r/atom [{:squares (apply vector (repeat 9 nil))}])
xIsNext (r/atom true)
handle-click
(fn [i]
(let [squares (:squares (last @history))]
(if-not (or (calculateWinner squares)
(squares i))
(let [next-move (if @xIsNext "X" "O")
next-squares (assoc squares i next-move)
next-step {:squares next-squares}]
(do (swap! history #(conj % next-step))
(swap! xIsNext not))))))]
(fn []
(let [squares (:squares (last @history))
status (if-some [winner (calculateWinner squares)]
(str "Winner: " winner)
(str "Next player: " (if @xIsNext "X" "O")))]
[:div.game
[:div.game-board
[Board squares handle-click]]
[:div.game-info
[:div status]
[:ol]]]))))
class Board extends React.Component {
renderSquare(i) {
return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />;
}
render() {
return (
<div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
class Game extends React.Component {
constructor() {
super();
this.state = {
history: [{
squares: Array(9).fill(null)
}],
xIsNext: true
};
}
handleClick(i) {
const history = this.state.history;
const current = history[history.length - 1];
const squares = current.squares.slice();
if (calculateWinner(squares) || squares[i]) {
return;
}
squares[i] = this.state.xIsNext ? 'X' : 'O';
this.setState({
history: history.concat([{
squares: squares
}]),
xIsNext: !this.state.xIsNext,
});
}
render() {
const history = this.state.history;
const current = history[history.length - 1];
const winner = calculateWinner(current.squares);
let status;
if (winner) {
status = 'Winner: ' + winner;
} else {
status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
}
return (
<div className="game">
<div className="game-board">
<Board
squares={current.squares}
onClick={(i) => this.handleClick(i)}
/>
</div>
<div className="game-info">
<div>{status}</div>
<ol>{/* TODO */}</ol>
</div>
</div>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment