Reduxの基礎を理解するためのメモ.
参照:Redux入門【ダイジェスト版】10分で理解するReduxの基礎
Reduxの概念とデータフローについて学ぶ
#Reduxとは
アプリケーションを作成する際,DB上のデータをpropsでバケツリレーのように受け渡しするのは非効率.加えて,親コンポーネントのstateに子コンポーネントが影響する構造は,全体のstateを把握するのが困難となり,不具合の原因となる.
この問題を解決するのが,ReactJSが扱うUIのstate管理のためのフレームワークであるReduxである.Reduxを用いることでアプリケーション全体(App.js)の状態を管理し,更新,描画することが容易になる.
#Reduxの要素
- ActionCreatorメソッド
- Actionオブジェクト
- Store
- State
- Reducerメソッド
これらの要素が機能することでアプリケーション全体のデータを操作することが可能となる.
##Reduxのフロー
ToDoアプリを例に説明する.
ユーザがtodoのテキストを入力して追加ボタンを押した場合を考える.
###ActionCreator
メソッド
このとき入力されたテキストがActionCreator
メソッドに渡される.
function addTodo(text) {
return {
type: ADD_TODO,
text: `${text}`
}
}
###Action
オブジェクト
Actionオブジェクトは,「何をする」という情報をtypeプロパティに持つ.このActionオブジェクトが,ActionCreatorメソッドにより作成される.
{
type: 'ADD_TODO',
text: 'Build my first Redux app'
}
###dispatch
文
dispatch文によって,ActionCreatorメソッドによって作成されたActionオブジェクトがStoreに渡される.
dispatch(addTodo(text))
###Store
Storeは,アプリケーションの状態(state)を保持している場所.
index.jsに作成され,そこでreducerが適応される.
Storeは,dispatchされると,引数のactionと現在保持するStateを,Reducerへと渡し,新しいStateを作成する.
import { createStore } from 'redux'
import reducer from './reducer'
//Storeの作成とreducerの適応
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
const thunkWithClient = thunk.withExtraArgument(client)
const store = createStore(reducer, composeEnhancers(applyMiddleware(thunkWithClient)))
import { combineReducers } from 'redux'
import todoApp from './reducers'
###State
アプリケーションでの状態.
下記の例では,「現在表示されている表示/非表示」,「todoリスト」をstateとして保持.
{
visibilityFilter: 'SHOW_ALL',
todos: [
{
text: 'Consider using Redux',
completed: true,
},
{
text: 'Keep all state in a single tree',
completed: false
}
]
}
###reducer
メソッド
reducerメソッドは,actionとstateから新しいstateを作成して返すメソッド.
reducerの実装は,actionのtypeに応じて処理を書く.
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
}
}
function visibilityFilter(state = SHOW_ALL, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return action.filter
default:
return state
}
}
function todoApp(state = {}, action) {
return {
visibilityFilter: visibilityFilter(state.visibilityFilter, action),
todos: todos(state.todos, action)
}
}
##アプリケーション全体で見てみると...
App.js/render()
↓
初回はinitialStateを用いてレンダリング
↓
App.js/componentDidMount()
↓
/ActionCreator()呼び出し
↓
todo.js/ActionCreator()
↓
/dispatch
↓
reducers.js
↓
todo.js/reducer
↓
App.jsのstate更新
↓
App.js/render()