[React] React 시작하기

1. Nodejs 설치 및 최신 버전 확인(6버전 이상)

  • https://nodejs.org/ko/ 여기서 최신 nodejs를 설치한다.
  • 콘솔 창(window + R -> cmd 검색) 에서 아래와 같이 명령어를 입력하면 내 pc에 깔린 nodejs버전이 나온다.
    1
    node -v

2. 프로젝트를 생성할 폴더 위치로 이동하여 다음과 같이 프로젝트를 시작한다.

아래 명령어로 폴더에 이동후

1
cd d:\dev\react\tutorial

아래 명령어로 프로젝트를 시작한다.

1
2
$ npm install -g create-react-app   
$ create-react-app my-app

3. my-app/src 하위의 파일들을 삭제한다.

1
2
$ cd my-app
$ rm -f src/*

4. my-app/src/index.css 파일을 만들어 아래 내용을 복사한다.

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
body {
font: 14px "Century Gothic", Futura, sans-serif;
margin: 20px;
}

ol, ul {
padding-left: 30px;
}

.board-row:after {
clear: both;
content: "";
display: table;
}

.status {
margin-bottom: 10px;
}

.square {
background: #fff;
border: 1px solid #999;
float: left;
font-size: 24px;
font-weight: bold;
line-height: 34px;
height: 34px;
margin-right: -1px;
margin-top: -1px;
padding: 0;
text-align: center;
width: 34px;
}

.square:focus {
outline: none;
}

.kbd-navigation .square:focus {
background: #ddd;
}

.game {
display: flex;
flex-direction: row;
}

.game-info {
margin-left: 20px;
}

5. my-app/src/index.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
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';


class Square extends React.Component {
render() {
return (
<button className="square">
{/* TODO */}
</button>
);
}
}

class Board extends React.Component {
renderSquare(i) {
return <Square />;
}

render() {
const status = 'Next player: X';

return (
<div>
<div className="status">{status}</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 {
render() {
return (
<div className="game">
<div className="game-board">
<Board />
</div>
<div className="game-info">
<div>{/* status */}</div>
<ol>{/* TODO */}</ol>
</div>
</div>
);
}
}

// ========================================

ReactDOM.render(
<Game />,
document.getElementById('root')
);

6. 아래 명령어로 시작한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

$ npm start
```

## 7. localhost:3000 으로 아래와 같은 화면이 뜬다.

## 8. my-app/src/index.js파일을 열어보면 아래 세가지 컴포넌트로 구성되어 있다.

- Square : 하나의 <button>을 렌더링함
- Board : 9개의 사각형을 랜더링함
- Game : 공백있는 하나의 보드를 랜더링함

## 9. Board 컴포넌트에서 Square 컴포넌트로 데이터(숫자 0~9) 전달하기

### 9.1 index.js파일의 Board클래스 부분을 아래와 같이 변경한다.
```js
class Board extends React.Component {
renderSquare(i) {
return <Square value={i} />;
}

9.2 Square클래스 render 메서드를 아래와 같이 변경한다.

1
2
3
4
5
6
7
8
9
class Square extends React.Component {
render() {
return (
<button className="square">
{this.props.value}
</button>
);
}
}
  • 이렇게 변경해서 저장 후 npm start로 실행해보면 비어있던 9개 사각형 칸에 0~8까지 숫자가 입력되서 나온다.

10. 대화형 컴포넌트 : 빈 사각형을 클릭하면 X표시가 되게 변경하기

10.1 Sqare의 render()함수를 아래와 같이 변경한다.

Square클래스의 생성자에서 this.state을 설정하여 상태(초기값 null)를 가질 수 있게 한다.

1
2
3
4
5
6
7
8
class Square extends React.Component {
constructor(props) {
super(props);
this.state = {
value: null,
};
}
}

아래와 같이 render()함수를 변경하면 사각형을 클릭하면 클릭한 빈 사각형안의 값이 X로 바뀐다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

class Square extends React.Component {
constructor(props) {
super(props);
this.state = {
value: null,
};
}

render() {
return (
<button className="square" onClick={() => this.setState({value: 'X'})}>
{this.state.value}
</button>
);
}
}

11 State에 저장하기

클릭 할때마다 o,x 번갈아 나오게 하고, 승자를 가리기 위해 9개 블럭의 상태를 동시에 확인해야함.
여러 하위 컴포넌트로 부터 데이터를 모으거나, 하위 컴포넌트들이 서로 통신하기 원하면 상위컴포넌트로 state를 이동시킴.
상위 컴포컨트는 props를 통해 하위 컴포넌트로 state를 전달해 줄 수 있다.

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
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: Array(9).fill(null),
};
}

renderSquare(i) {
return <Square value={i} />;
}

render() {
const status = 'Next player: X';

return (
<div>
<div className="status">{status}</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>
);
}
}

지금 board의 renderSquare매서드는 아래와 같다.

1
2
3
4
renderSquare(i) {
return <Square value ={i} />;

}

Square에 value prop를 전달하도록 수정한다

1
2
3
renderSquare(i) {
return <Square value={this.state.squares[i]} />;
}

1
2
3
4
5
6
7
8
renderSquare(i) {
return (
<Square
value={this.state.squares[i]}
onClick={() => this.handleClick(i)}
/>
);
}
1
2
3
4
5
6
7
8
9
class Square extends React.Component {
render() {
return (
<button className="square" onClick={() => this.props.onClick()}>
{this.props.value}
</button>
);
}
}
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
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: Array(9).fill(null),
};
}

handleClick(i) {
const squares = this.state.squares.slice();
squares[i] = 'X';
this.setState({squares: squares});
}

renderSquare(i) {
return (
<Square
value={this.state.squares[i]}
onClick={() => this.handleClick(i)}
/>
);
}

render() {
const status = 'Next player: X';

return (
<div>
<div className="status">{status}</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>
);
}
}
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

function Square(props) {
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
);
}

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(props) {
super(props);
this.state = {
history: [
{
squares: Array(9).fill(null)
}
],
stepNumber: 0,
xIsNext: true
};
}

handleClick(i) {
const history = this.state.history.slice(0, this.state.stepNumber + 1);
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
}
]),
stepNumber: history.length,
xIsNext: !this.state.xIsNext
});
}

jumpTo(step) {
this.setState({
stepNumber: step,
xIsNext: (step % 2) === 0
});
}

render() {
const history = this.state.history;
const current = history[this.state.stepNumber];
const winner = calculateWinner(current.squares);

const moves = history.map((step, move) => {
const desc = move ?
'Go to move #' + move :
'Go to game start';
return (
<li key={move}>
<button onClick={() => this.jumpTo(move)}>{desc}</button>
</li>
);
});

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>{moves}</ol>
</div>
</div>
);
}
}

// ========================================

ReactDOM.render(<Game />, document.getElementById("root"));

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 squares[a];
}
}
return null;
}

댓글

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×