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는 실제 데이터의 렌더링을 담당하는 부분으로 전체 시스템의 상태 트리를 스토어로부터 넘겨받아 하위 컴포넌트로 전달containers에reducers를 결합해서 화면에 출력하기 위한 ‘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 creators는action을 만드는 함수action과action creators는 혼용하기 쉬운 용어이니 적절하게 사용하도록 신경써야 함action은store로 보내는 데이터 묶음action은 반드시 어떤 형태로 실행될지 나타내는type속성을 가져야 함- 주의점은
Redux는action creatrs'에서action`만 반환함
Binding Action Creators
containers\book-list.js
- 실제로
action을 보내려면 결과값을dispatch함수에 넘김 dispatch함수를store에서store.dispatch로 바로 접근가능- 하지만
react-redux의connect과 같은 헬퍼를 통해 접근할 것임 action creators를dispatch에 연결(bind)하기 위해bindActionCreators를 사용
Creating an Action
containers\book-list.js
Flux
Consuming Actions in Reducers
reducers\reduceractivebook.js
store
reducers\index.js
store
* activeBook을 reducers에 추가
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