はじめに
昨日書いたReduxのAction、Reducer、Storeの(個人的な)整理メモの続き的な立ち位置の記事です。
基本的にはReduxの本家サイトのhttp://redux.js.org/docs/basics/UsageWithReact.html の内容をかいつまんだ内容になります。間違いなどございましたら、コメントにてご指摘お待ちしておりますm(_ _)m
Presentational and Container Components
ReduxではPresentational ComponentsとContainer Componentsで分けるという考え方を採用しています。
Presentational Components : どのように見えるか
Container Components : どのように働くか
で分ける考え方のようで、乱暴な言い方を恐れなければ、Presentational ComponentsがReactパートで、このContainer ComponentsこそがReduxの担当パートになります。
もう少し詳しく知りたい場合には原文のこちらを
http://redux.js.org/docs/basics/UsageWithReact.html#presentational-and-container-components
Presentational Components
Presentational ComponentsはReactのComponentそのものと考えても良いでしょう。
(私が前にReactを触ったときはES6じゃなかったので、アローファンクションで書いてあるこのサンプルは全く別物に見えてました・・・)
補足:Stateless な React Component の記法をまとめてみた
import React, { PropTypes } from 'react'
const Todo = ({ onClick, completed, text }) => (
<li
onClick={onClick}
style={{
textDecoration: completed ? 'line-through' : 'none'
}}
>
{text}
</li>
)
Todo.propTypes = {
onClick: PropTypes.func.isRequired,
completed: PropTypes.bool.isRequired,
text: PropTypes.string.isRequired
}
export default Todo
Container Components
技術的な説明としては、Containter Componentsでは(store.subscribe()を使って)をReduxのStateの一部を読み取って、レンダリングするPresentational Componentsにpropsを供給するReactコンポーネントです。
react-redux libraryを使っていれば、connect()関数を(store.subscribe()の代わりに)使うことが出来ます。
mapStateToProps()
connect()関数を使うためにはmapStateToProps()という特別な関数を定義する必要があります。
このmapStateToProps()を使うことによって、Presentational Componentsへ現在のReduxが保持しているstateをどう利用するか教えることが出来ます。
例:
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case 'SHOW_ALL':
return todos
case 'SHOW_COMPLETED':
return todos.filter(t => t.completed)
case 'SHOW_ACTIVE':
return todos.filter(t => !t.completed)
}
}
const mapStateToProps = (state) => {
return {
todos: getVisibleTodos(state.todos, state.visibilityFilter)
}
}
mapDispatchToProps()
加えて、connect()関数を使う際にはmapDispatchToProps()を使うことで、Container ComponentsはActionへのdispatchを定義することが出来ます。
mapStateToProps()と似たような形でdispatch()メソッドを受け取るmapDispatchToProps()を定義し、
Presentational Componentsに注入(inject)したいコールバックpropsを返すことが出来ます。
const mapDispatchToProps = (dispatch) => {
return {
onTodoClick: (id) => {
dispatch(toggleTodo(id))
}
}
}
最終的に、これらを組み合わせてconnect()を利用すると下記のようになります。
import { connect } from 'react-redux'
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
export default VisibleTodoList
Passing the Store
ReduxのStoreをComponentsにごそっと渡す方法のもう一つのオプションです。
react-reduxのための特別なProviderというものがあります。
アプリケーションのroot componentsをレンダリングするときには、一度だけ使用する必要があります。
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App'
let store = createStore(todoApp)
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)