Dev

React 공부 정리 #3

August 3, 2016

React 공부 정리 #3

State with React

  • Udemy 강좌의 ‘Section 3: State with React’에 해당하는 내용
  • Redux에 대한 자세한 내용은 Redux를 참고
  • 한글로 번역된 내용은 Dobbit.Co님의 github을 참고

Redux의 특징

Single Source of Truth

  • Redux는 어플리케이션의 state를 위해 단 한개의 store 를 사용하나 하나의 객체 트리를 사용
console.log(store.getState());

{
  visibilityFilter: 'SHOW_ALL',
  todos: [{
    text: 'Consider using Redux',
    completed: true,
  }, {
    text: 'Keep all state in a single tree',
    completed: false
  }]
}

State is read-only

  • 상태를 변화시키는 유일한 방법은 무슨 일이 벌어지는 지를 묘사하는 액션 객체를 전달하는 방법뿐입니다.
store.dispatch({  
  type: 'COMPLETE_TODO',
  index: 1
});

store.dispatch({  
  type: 'SET_VISIBILITY_FILTER',
  filter: 'SHOW_COMPLETED'
});

Changes are made with Pure Functions

  • 액션에 의해 상태 트리가 어떻게 변화하는 지를 지정하기 위해 프로그래머는 순수 리듀서를 작성해야합니다.
function visibilityFilter(state = 'SHOW_ALL', action) {  
  switch (action.type) {
  case 'SET_VISIBILITY_FILTER':
    return action.filter;
  default:
    return state;
  }
}

function todos(state = [], action) {  
  switch (action.type) {
  case 'ADD_TODO':
    return [...state, {
      text: action.text,
      completed: false
    }];
  case 'COMPLETE_TODO':
    return [
      ...state.slice(0, action.index),
      Object.assign({}, state[action.index], {
        completed: true
      }),
      ...state.slice(action.index + 1)
    ];
  default:
    return state;
  }
}

import { combineReducers, createStore } from 'redux';  
let reducer = combineReducers({ visibilityFilter, todos });  
let store = createStore(reducer);  
  • action은 무언가 일어난다는 사실을 기술
  • reducer는 그 결과 애플리케이션의 상태가 어떻게 바뀌는지는 기술
  • reducer에 인수가 주어지면, 다음 상태를 계산해서 반환해야 하며, 예기치 못한 일, 사이드 이펙트는 없어야 되고, API 호출도 안되며, 변경도 안됨! 오직 계산만 가능

Redux 설정

폴더 구조

|----\src
        |----\actions
                |---- index.js
        |----\components
                |---- app.js
        |----\reducers
                |---- index.js
        |---- index.js
|----\style
        |---- style.css
|-- index.html
|-- package.json
|-- webpack.config.js

package.json

{
  "name": "modern_react_with_redux_study",
  "version": "1.0.0",
  "description": "[Modern React with Redux](https://www.udemy.com/react-redux/)를 수강하면서 진행한 예제",
  "main": "index.js",
  "scripts": {
    "start": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js"    
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/sigmadream/modern_react_with_redux_study.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/sigmadream/modern_react_with_redux_study/issues"
  },
  "homepage": "https://github.com/sigmadream/modern_react_with_redux_study#readme",
  "dependencies": {
    "babel-core": "^6.11.4",
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.11.1",
    "babel-preset-stage-1": "^6.5.0",
    "react": "^15.3.0",
    "react-dom": "^15.3.0",
    "react-redux": "^4.4.5",
    "redux": "^3.5.2",
    "webpack": "^1.13.1",
    "webpack-dev-server": "^1.14.1"
  }
}

webpack.config.js

module.exports = {  
  entry: [
    './src/index.js'
  ],  
  output: {
    path: __dirname,
    publicPath: '/',
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      exclude: /node_modules/,
      loader: 'babel',
      query: {
        presets: ['react', 'es2015', 'stage-1']
      }
    }]
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  devServer: {
    historyApiFallback: true,
    contentBase: './'
  }
};

‘Hello World!’

  • Redux가 적용된 프로젝트의 테스트를 위한 ‘Hello World’ 예제를 실행

src\index.js

import React from 'react';  
import ReactDOM from 'react-dom';  
import { Provider } from 'react-redux';  
import { createStore, applyMiddleware } from 'redux';

import App from './components/app';  
import reducers from './reducers';

const createStoreWithMiddleware = applyMiddleware()(createStore);

ReactDOM.render(  
  <Provider store={createStoreWithMiddleware(reducers)}>
    <App />
  </Provider>
  , document.querySelector('.container'));
  • redux의 미들웨어 객체를 생성
  • 미들웨어는 프레임워크가 요청을 받고 응답을 만드는 사이에 놓을 수 있는 코드
  • 미들웨어는 액션을 보내는 순간부터 스토어에 도착하는 순간까지 사이에 서드파티 확장을 사용할 수 있는 지점을 제공

reducers\index.js

import { combineReducers } from 'redux';

const rootReducer = combineReducers({  
  state: (state = {}) => state
});

export default rootReducer;  

components\app.js

import React, { Component } from 'react';

export default class App extends Component {  
  render() {
    return (
      <div>React simple starter</div>
    );
  }
}
Array