React

React

简介

做 Next.js 的时候发现基础还是要看看。

初步试用

井字棋练习题完整版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import { useState } from 'react';

function Square({ value, onSquareClick, isWinningSquare }) {
const backgroundColor = isWinningSquare ? 'yellow' : 'white';
return (
<button
className="square"
onClick={onSquareClick}
style={{ backgroundColor }}
>
{value}
</button>
);
}

function Board({ xIsNext, squares, onPlay, winningSquares }) {
function handleClick(i) {
if (calculateWinner(squares) || squares[i]) {
return;
}
const nextSquares = squares.slice();
if (xIsNext) {
nextSquares[i] = 'X';
} else {
nextSquares[i] = 'O';
}
onPlay(nextSquares, i);
}

const winner = calculateWinner(squares)?.winner;
const isDraw = !winner && squares.every(Boolean);

let status;
if (winner) {
status = 'Winner: ' + winner;
} else if (isDraw) {
status = "It's a draw!";
} else {
status = 'Next player: ' + (xIsNext ? 'X' : 'O');
}

return (
<>
<div className="status">{status}</div>
{Array(3).fill(null).map((_, rowIndex) => (
<div className="board-row" key={rowIndex}>
{Array(3).fill(null).map((_, colIndex) => {
const index = rowIndex * 3 + colIndex;
return (
<Square
key={index}
value={squares[index]}
onSquareClick={() => handleClick(index)}
isWinningSquare={winningSquares?.includes(index)}
/>
);
})}
</div>
))}
</>
);
}

export default function Game() {
const [history, setHistory] = useState([{ squares: Array(9).fill(null), position: null }]); // 记录落子位置
const [currentMove, setCurrentMove] = useState(0);
const [isAscending, setIsAscending] = useState(true);
const xIsNext = currentMove % 2 === 0;
const currentSquares = history[currentMove].squares;

function handlePlay(nextSquares, position) {
const nextHistory = [...history.slice(0, currentMove + 1), { squares: nextSquares, position }];
setHistory(nextHistory);
setCurrentMove(nextHistory.length - 1);
}

function jumpTo(nextMove) {
setCurrentMove(nextMove);
}

function toggleSortOrder() {
setIsAscending(!isAscending);
}

const winnerInfo = calculateWinner(currentSquares);
const winningSquares = winnerInfo ? winnerInfo.line : null;

const sortedMoves = isAscending ? history : [...history].reverse();
const moves = sortedMoves.map((entry, move) => {
const totalMoves = history.length - 1;
const adjustedMove = isAscending ? move : totalMoves - move;

let description;
if (adjustedMove === totalMoves && totalMoves !== 0) {
description = `You are at move ${totalMoves}`;
} else if (adjustedMove > 0) {
const row = Math.ceil((entry.position + 1) / 3);
const col = (entry.position + 1) - (row - 1) * 3;
description = `Go to move #${adjustedMove} (row: ${row}, col: ${col})`;
} else {
description = 'Go to game start';
}

return (
<li key={adjustedMove}>
<button onClick={() => jumpTo(adjustedMove)}>{description}</button>
</li>
);
});

return (
<div className="game">
<div className="game-board">
<Board
xIsNext={xIsNext}
squares={currentSquares}
onPlay={handlePlay}
winningSquares={winningSquares}
/>
</div>
<div className="game-info">
<button onClick={toggleSortOrder}>
{isAscending ? 'Sort Descending' : 'Sort Ascending'}
</button>
<ol>{moves}</ol>
</div>
</div>
);
}

function calculateWinner(squares) {
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] && squares[a] === squares[b] && squares[a] === squares[c]) {
return { winner: squares[a], line: lines[i] };
}
}
return null;
}

参考资料

官方网站

井字棋教程

Awesome React

HTML to JSX


React
https://wangqian0306.github.io/2024/react/
作者
WangQian
发布于
2024年10月22日
许可协议