LoginSignup
11
10

More than 5 years have passed since last update.

ReduxのPresentational ComponentsとContainer Componentsの役割の(個人的な)整理メモ

Last updated at Posted at 2016-12-24

はじめに

昨日書いた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')
)
11
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10