prerequisite

+ es6 import

+ es6 export

migration

bootstrap 모듈을 인스톨한다.

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

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

/* 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

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

import Header from './components/Header';

Counter.jsx를 추가하고 App.jsx에서 Counter 컴포넌트를 분리해서 넣는다.

components/Counter.jsx

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

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

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 한다.

import React from 'react';

const Header = (props) => {
  console.log(props);
  return (
    

{ props.title }

Players: { props.totalPlayers }
) } export default Header;

아직 에러가 날 것이다. App.js에서 Header 컴포넌트를 인식할 수 없기 때문이다. App.js를 App.jax로 rename 한 후에 App.jsx에 Header 컴포넌트를 import 한다.

import Header from './components/Header';

Counter.jsx를 추가하고 App.jsx에서 Counter 컴포넌트를 분리해서 넣는다.

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 (
      
{this.state.score}
); } } export default Counter;

Player 컴포넌트도 동일하게 분리한다. src 아래 components 에 Player.jsx를 추가하고 App.jsx에서 Player 컴포넌트를 잘라내서 집어 넣는다.

Counter 컴포넌트가 없어서 컴파일 에러가 Player 컴포넌트에서 발생할것이므로 import 구문을 추가한다.

import React from "react";
import Counter from "./Counter";

const Player = (props) => {
  console.log(props);
  return (
    
{props.name}
); } export default Player;

그리고 App.jsx에 Player 컴포넌트를 import 한다. 다 분리된 App.jsx 는 다음과 같다.

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 (
      
{/*Players List*/} { this.state.players.map(item => ) }
); } } export default App;

이제 화면이 정상적으로 보이는지 확인하자. 만일 webpack-dev-server가 정상 동작 되지 않는다면 리스타트를 한번 시도해보자.

– quiz