Posted at

Reduxさわってみたのでメモ 【middleware, ログ、非同期処理】

More than 3 years have passed since last update.


redux-loggerを使ってみる

https://github.com/fcomb/redux-logger


redux-logger

Stateがどう変わったか、及びどのActionがdispatchされたことによるか、をログとして表示してくれるMiddleware

ソースみてもわかるように、


redux-logger/blob/master/src/index.js

    if (level) {

console[level](`%c prev state`, `color: #9E9E9E; font-weight: bold`, prevState);
console[level](`%c action`, `color: #03A9F4; font-weight: bold`, formattedAction);
console[level](`%c next state`, `color: #4CAF50; font-weight: bold`, nextState);
} else {
console.log(`%c prev state`, `color: #9E9E9E; font-weight: bold`, prevState);
console.log(`%c action`, `color: #03A9F4; font-weight: bold`, formattedAction);
console.log(`%c next state`, `color: #4CAF50; font-weight: bold`, nextState);
}

以下のようなログを表示してくれる

687474703a2f2f692e696d6775722e636f6d2f7168637a314f442e706e67.png


version


  • 2.0.2


install

npm install --save redux-logger


usage


index.js

import createLogger from 'redux-logger';

const logger = createLogger();
const createStoreWithMiddleware = applyMiddleware(logger)(createStore);
const store = createStoreWithMiddleware(reducer);


オプションもいろいろあるようです


index.js

const logger = createLogger({

// 特定の種別のアクション以外のログを表示する
predicate: (getState, action) => action.type !== AUTH_REMOVE_TOKEN,
// ログレベルを指定
level: 'info',
// 一連の処理にかかった時間を表示するか
duration: true
});


memo

普通にREADME.mdみれば問題なく動くはずなのだけど、自分は

https://github.com/rackt/redux/tree/master/examples/async

を参考にしながら実装してしまったのですが、redux-loggerのバージョンが0.0.3とかなり古く、少しハマってしまいました(下のコメント部分)


configureStore.js

import thunkMiddleware from 'redux-thunk';

import loggerMiddleware from 'redux-logger';
import rootReducer from '../reducers';

const createStoreWithMiddleware = applyMiddleware(
thunkMiddleware,
loggerMiddleware // loggerMiddleware() のように関数ではない!!!
)(createStore);

export default function configureStore(initialState) {
const store = createStoreWithMiddleware(rootReducer, initialState);

// ...



isomorphic-fetchを使ってみる

さきほどのサンプルのAsyncでは非同期処理にisomorphic-fetchを使用していたので、それに倣って使ってみた

https://github.com/matthew-andrews/isomorphic-fetch


version


  • isomorphic-fetch => 2.1.1

  • es6-promise => 3.0.2

es6-promisepromise使うためのポリフィル


install

npm install --save isomorphic-fetch es6-promise


usage


SomeComponent.js

  componentDidMount() {

fetch('http://localhost:7000/list')
.then(response => response.json())
.then(json => store.dispatch(Actions.updateList(json)));

// ...


こんな感じで、非同期処理でデータを引っ張ってきて、そのデータを引数にActionをdispatchする、というのは特に迷うことなくできたのですが・・・サンプルではActionの中に非同期処理を入れ込んでいるようです。

ということで、サンプルに倣って新規に追加したActionをdispatchするよう修正してみっところ、


Action.js

export function fetchList = () => {

return dispatch => {
return fetch('http://localhost:7000/list')
.then(response => response.json())
.then(json => dispatch(Actions.updateList(json)));
};
}

以下のエラーがでました


Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.


内容は御尤ものことで、Actionはオブジェクトでないとダメというもの


redux-thunkを使ってみる

https://github.com/gaearon/redux-thunk


version


  • 1.0.0


install

npm install --save redux-thunk


usage

Middlewareに追加する


index.js

import createLogger from 'redux-logger';

import thunk from 'redux-thunk';

const logger = createLogger();
const createStoreWithMiddleware = applyMiddleware(thunk, logger)(createStore);
const store = createStoreWithMiddleware(reducer);



メモ

redux-thunkMiddlewareとして追加することで、さきほどのActions must be plain objectsというエラーはでなくなり、非同期処理・データフローも正しい挙動になりました。

また、このMiddlewareってコードでいうとたったのこれだけなので、アイデアあれば結構簡単にMiddlewareつくれるかなぁと勇気をもらった


redux-thunk/blob/master/src/index.js

export default function thunkMiddleware({ dispatch, getState }) {

return next => action =>
typeof action === 'function' ?
action(dispatch, getState) :
next(action);
}