prerequisite
+ es6 import
+ es6 export
migration
bootstrap 모듈을 인스톨한다.
1 |
npm i -S bootstrap |
index.js 는 index.jsx로 App.js는 App.jsx로 이름을 수정한다.
페이지 방식의 리액트 소스를 그대로 가져와서 create-reacp-app 에서 구동되도록 마이그레이션부터 해보자.
엔트리포인트인 index.js 에 이미 ReactDOM.render()로 렌더링 하고 있으므로 기존 소스의 app.js에서 렌더링 하고 있는 부분만 제외하고 모두 App.jsx 컴포넌트로 복사한다. 기존 App.jsx에 있는 소스는 모두 삭제하고 복사한다.
그리고, 기존 app.css는 App.css 로 모두 복사한다. bootstrap은 script 태그에서 삭제되었으므로 상단에 bootstrap.css 를 import해야 한다.
App.jsx
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 |
import React from 'react'; import 'bootstrap/dist/css/bootstrap.min.css'; import './App.css'; const Header = (props) => { console.log(props); // props는 read only 이다. 아래와 같이 하면 안된다. // props.totalPlayers = 12; return (<div className="header d-flex justify-content-between align-items-center p-2"> <span>Total Score: 0</span> <h1>{props.title}</h1> <span>players: {props.totalPlayers}</span> </div>) }; const Player = (props) => ( <div className="container"> <div className='player row align-items-center'> <div className="col-1"> <button className="btn btn-danger" onClick={() => props.removePlayer(props.id)}>x</button> </div> <div className="col-8"> <span>{props.name}</span> </div> <div className="col-3 counter"> <Counter score={props.score} /> </div> </div> </div> ); class Counter extends React.Component { state = { score: 0 }; handleScore = (delta) => { console.log(this); // this.state.score += 1; this.setState((prevState) => ({ score: prevState.score + delta})); // this.setState({score: this.state.score +1}); console.log('onIncrease: ', delta); // filter를 이용해서 id가 아닌것은 걸러내기 } render() { return ( <div className='d-flex justify-content-between align-items-center'> <button className='btn btn-info' onClick={(e) => this.handleScore(-1)}> - </button> <span>{this.state.score}</span> <button className='btn btn-info' onClick={(e) => this.handleScore(1)}> + </button> </div> ); } } class App extends React.Component { state = { players: [ {name: 'LDK', id: 1}, {name: 'HONG', id: 2}, {name: 'KIM', id: 3}, {name: 'PARK', id: 4}, ] }; handleRemovePlayer = (id) => { this.setState(prevState => { return { players: prevState.players.filter(item => item.id !== id) } }) } render() { return ( <div className="container p-3"> <Header title="My scoreboard" totalPlayers={this.state.players.length} /> {/*Players List*/} { this.state.players.map(item => <Player name={item.name} key={item.id} removePlayer={this.handleRemovePlayer} id={item.id} />) } </div> ); } } export default App; |
App.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* user defined css */ .header { background-color: #733daa; color: #ffffff; } .player { font-size: 1.2em; border-bottom: solid 2px #EEEEEE; border-left: solid 2px #EEEEEE; border-right: solid 2px #EEEEEE; letter-spacing: 2px; height: 4rem; } .counter { border-left: solid 2px #DDDDDD; } |
npm run start로 구동시 페이지 방식으로 했던 소스가 그대로 보여야 한다.
break into module
App.jsx 안에는 Header 컴포넌트, Player 컴포넌트, Counter 컴포넌트가 모두 같이 들어가 있다. 이제 이 컴포넌트들을 별도의 화일로 분리한다.
먼저 Header 컴포넌트를 분리한다. App.js에 있는 Header 컴포넌트를 잘라내서 src 폴더 아래에 components 폴더를 만들고 Header.jsx 화일을 추가 후 그 안에 복사한다. 그리고, 맨 상단에는 react를 import 한다.
components/Header.jsx
1 2 3 4 5 6 7 8 9 10 |
export const Header = (props) => { console.log(props); // props는 read only 이다. 아래와 같이 하면 안된다. // props.totalPlayers = 12; return (<div className="header d-flex justify-content-between align-items-center p-2"> <span>Total Score: 0</span> <h1>{props.title}</h1> <span>players: {props.totalPlayers}</span> </div>) }; |
아직 에러가 날 것이다. App.jsx에 Header 컴포넌트를 import 한다.
App.jsx
1 |
import Header from './components/Header'; |
Counter.jsx를 추가하고 App.jsx에서 Counter 컴포넌트를 분리해서 넣는다.
components/Counter.jsx
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 |
import React from 'react'; export class Counter extends React.Component { state = { score: 0 }; incrementScore = () => { console.log(this); this.setState(prevState => { return {score: prevState.score + 1} }); } decrementScore = () => { this.setState(prevState => { return {score: prevState.score - 1} }); } render() { return ( <div className='d-flex justify-content-between align-items-center'> <button className='btn btn-info' onClick={this.decrementScore}> - </button> <span>{this.state.score}</span> <button className='btn btn-info' onClick={this.incrementScore}> + </button> </div> ); } } |
Player 컴포넌트도 동일하게 분리한다. src 아래 components 에 Player.jsx를 추가하고 App.jsx에서 Player 컴포넌트를 잘라내서 집어 넣는다.
Counter 컴포넌트가 없어서 컴파일 에러가 Player 컴포넌트에서 발생할것이므로 import 구문을 추가한다.
components/Player.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import {Counter} from "./Counter"; export const Player = (props) => ( <div className="container"> <div className='player row align-items-center'> <div className="col-1"> <button className="btn btn-danger" onClick={() => props.removePlayer(props.id)}>x</button> </div> <div className="col-8"> <span>{props.name}</span> </div> <div className="col-3 counter"> <Counter score={props.score} /> </div> </div> </div> ); |
그리고 App.jsx에 Player 컴포넌트를 import 한다. 다 분리된 App.jsx 는 다음과 같다.
App.jsx
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 |
import React from 'react'; import 'bootstrap/dist/css/bootstrap.min.css'; import './App.css'; import {Header} from "./components/Header"; import {Player} from "./components/Player"; class App extends React.Component { state = { players: [ {name: 'LDK', id: 1}, {name: 'HONG', id: 2}, {name: 'KIM', id: 3}, {name: 'PARK', id: 4}, ] }; handleRemovePlayer = (id) => { this.setState(prevState => { return { players: prevState.players.filter(item => item.id !== id) } }) } render() { return ( <div className="container p-3"> <Header title="My scoreboard" totalPlayers={this.state.players.length} /> {/*Players List*/} { this.state.players.map(item => <Player name={item.name} key={item.id} removePlayer={this.handleRemovePlayer} id={item.id} />) } </div> ); } } export default App; |
이제 화면이 정상적으로 보이는지 확인하자. 만일 webpack-dev-server가 정상 동작 되지 않는다면 리스타트를 한번 시도해보자.
+ quiz
prerequisite
+ es6 import
+ es6 export
migration
먼저 페이지 방식의 소스를 그대로 가져와서 create-reacp-app 에서 구동되도록 마이그레이션부터 해보자.
엔트리포인트인 index.js 에 이미 ReactDOM.render()로 렌더링 하고 있으므로 기존 소스에서 렌더링 하고 있는 부분만 제외하고 모두 App.js 컴포넌트로 복사한다. 기존 App.js에 있는 소스는 모두 삭제하고 복사한다.
그리고, 기존 app.css는 App.css 로 모두 복사한다.
실행해서 기존 화면 그대로 나오는지 확인한다.
break into module
App.js 안에는 Header 컴포넌트, Player 컴포넌트, Counter 컴포넌트가 모두 같이 들어가 있다. 이제 이 컴포넌트들을 별도의 화일로 분리한다.
먼저 Header 컴포넌트를 분리한다. App.js에 있는 Header 컴포넌트를 잘라내서 src 폴더 아래에 components 폴더를 만들고 Header.jsx 화일을 추가 후 그 안에 복사한다. 그리고, 맨 상단에는 react를 import 한다.
1 2 3 4 5 6 7 8 9 10 11 |
import React from 'react'; const Header = (props) => { console.log(props); return ( <header> <h1>{ props.title }</h1> Players: { props.totalPlayers } </header> ) } export default Header; |
아직 에러가 날 것이다. App.js에서 Header 컴포넌트를 인식할 수 없기 때문이다. App.js를 App.jax로 rename 한 후에 App.jsx에 Header 컴포넌트를 import 한다.
1 |
import Header from './components/Header'; |
Counter.jsx를 추가하고 App.jsx에서 Counter 컴포넌트를 분리해서 넣는다.
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 |
import React from "react"; class Counter extends React.Component { state = { score: 0 }; incrementScore = () => { console.log(this); this.setState(prevState => { return {score: prevState.score + 1} }); } decrementScore = () => { this.setState(prevState => { return {score: prevState.score - 1} }); } render() { return ( <button className="counter-action decrement" onClick={this.decrementScore}> - </button> {this.state.score} <button className="counter-action increment" onClick={this.incrementScore}> + </button> ); } } export default Counter; |
Player 컴포넌트도 동일하게 분리한다. src 아래 components 에 Player.jsx를 추가하고 App.jsx에서 Player 컴포넌트를 잘라내서 집어 넣는다.
Counter 컴포넌트가 없어서 컴파일 에러가 Player 컴포넌트에서 발생할것이므로 import 구문을 추가한다.
1 2 3 4 5 6 7 8 9 10 11 |
import React from "react"; import Counter from "./Counter"; const Player = (props) => { console.log(props); return ( <button className="remove-player" onClick={() => props.removePlayer(props.id)}>x</button> {props.name} <Counter /> ); } export default Player; |
그리고 App.jsx에 Player 컴포넌트를 import 한다. 다 분리된 App.jsx 는 다음과 같다.
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 |
import React from 'react'; import './App.css'; import Header from "./components/Header"; import Player from "./components/Player"; class App extends React.Component { state = { players: [ {name: 'LDK', id: 1}, {name: 'HONG', id: 2}, {name: 'KIM', id: 3}, {name: 'PARK', id: 4}, ] }; handleRemovePlayer = (id) => { this.setState(prevState => { return { players: prevState.players.filter(item => item.id !== id) } }) } render() { return ( <Header title="My scoreboard" totalPlayers={this.state.players.length} /> {/*Players List*/} { this.state.players.map(item => <Player name={item.name} key={item.id.toString()} removePlayer={this.handleRemovePlayer} id={item.id} />) } ); } } export default App; |
이제 화면이 정상적으로 보이는지 확인하자. 만일 webpack-dev-server가 정상 동작 되지 않는다면 리스타트를 한번 시도해보자.