Dev

React 공부정리 #4

August 26, 2016

React 공부정리 #4

Redux Exmaple

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

Reducers, Containers & Implementation of a Container Class

reducers\reducer_books.js

export default function() {  
  return [
    { title: 'Javascript: The Good Parts', pages: 101 },
    { title: 'Harry Potter', pages: 39 },
    { title: 'The Dark Tower', pages: 85 },
    { title: 'Eloquent Ruby', pages: 1 }
  ];
}
  • 앞에서 설명했듯이 리듀서(Reducers)는 애플리케이션의 상태가 어떻게 바뀔지를 설명하는 것으로 상태를 관리, 전달함
  • Redux의 가장 눈에 띄는 특징은 ‘단일 스토어, 다수의 리듀서(reducer)’ 정책임
  • Flux의 경우 시스템의 도메인 레이어(비지니스 문제를 코드로 나타내며 해당 도메인의 비지니스 규칙도 포함)라 할 수 있는 store에서 state, props를 관리하는 Flux의 경우 store도 쉽게 비대해지고 이런 상황에서 다수의 store형태로 분리
  • Redux의 경우 단일 store를 유지하되, 상태 처리에 대한 책임을 store의 하위에 있는 Reducer에게 ‘단일 스토어, 다수의 리듀서’ 전략을 사용,

containers\book-list.js

import React, { Component } from 'react';  
import { connect } from 'react-redux';

class BookList extends Component {  
  renderList() {
    return this.props.books.map((book) => {
      return (
        <li
          key={book.title}
          className="list-group-item">
          {book.title}
        </li>
      );
    });
  }

  render() {
    return (
      <ul className="list-group col-sm-4">
        {this.renderList()}
      </ul>
    )
  }
}

function mapStateToProps(state) {  
  return {
    books: state.books
  };
}

export default connect(mapStateToProps)(BookList);  
  • 컨테이너 컴포넌트는 리덕스 시스템 사이의 연결 고리로 하위 컴포넌트에서 올라오는 요청을 해석해서 mapStateToProps는 실제 데이터의 렌더링을 담당하는 부분으로 전체 시스템의 상태 트리를 스토어로부터 넘겨받아 하위 컴포넌트로 전달
    • containersreducers를 결합해서 화면에 출력하기 위한 ‘View’를 생성
    • Redux와 연결하고 싶은 컴포넌트를 react-redux의 connect 함수로 연결
    • connect 함수의 경우 될 수 있으면 최상위 컴포넌트, 라우트 핸들러(route handler)에 연결할 것
    • 기술적으로는 모든 컴포넌트와 store에 연결(connect) 할 수 있지만 너무 과도하게 연결하면 데이터 흐름을 추적하기가 어려워짐

components\app.js

import React from 'react';  
import { Component } from 'react';  
import BookList from '../containers/book-list';

export default class App extends Component {  
  render() {
    return (
      <div>
        <BookList />
      </div>
    );
  }
}

reducers\index.js

import { combineReducers } from 'redux';  
import BookReducer from './reducer_books';

const rootReducer = combineReducers({  
  books: BookReducer
});

export default rootReducer;  
  • combineReducers 는 여러개의 reducer를 한개로 합칠 때 사용 되는 redux 내장 메소드로 차후에 여러 reducers를 합쳐서 사용하게 될 때 사용 됨
  • reducer를 합치는 일은 매우 빈번하게 해야하는 작업, 여러 리듀서를 합치는 작업을 하다보면 예상치 못한 휴먼에러가 발생, 그래서 combineReducers 라는 메서드를 통해서 한번에 모든 reducer를 합쳐주는 작업

Actions and Action Creators

actions\index.js

export function selectBook(book) {  
  return {
    type: 'BOOK_SELECTED',
    payload: book
  }
}
  • action creatorsaction을 만드는 함수
  • actionaction creators는 혼용하기 쉬운 용어이니 적절하게 사용하도록 신경써야 함
  • actionstore로 보내는 데이터 묶음
  • action은 반드시 어떤 형태로 실행될지 나타내는 type 속성을 가져야 함
  • 주의점은 Reduxaction creatrs'에서action`만 반환함

Binding Action Creators

containers\book-list.js

  • 실제로 action을 보내려면 결과값을 dispatch 함수에 넘김
  • dispatch 함수를 store에서 store.dispatch로 바로 접근가능
  • 하지만 react-reduxconnect과 같은 헬퍼를 통해 접근할 것임
  • action creatorsdispatch에 연결(bind)하기 위해 bindActionCreators를 사용

Creating an Action

containers\book-list.js

Flux

Consuming Actions in Reducers

reducers\reduceractivebook.js

store

reducers\index.js

store
* activeBookreducers에 추가

Conditional Rendering

containers\book-details.js

import React, { Component } from 'react';  
import { connect } from 'react-redux';

class BookDetail extends Component {  
  render() {
    if (!this.props.book) {
      return <div>Select a book to get started.</div>;
    }

    return (
      <div>
        <h3>Details for:</h3>
        <div>Title: {this.props.book.title}</div>
        <div>Pages: {this.props.book.pages}</div>
      </div>
    );
  }
}

function mapStateToProps(state) {  
  return {
    book: state.activeBook
  };
}

export default connect(mapStateToProps)(BookDetail);  
Array