Redux の Store
カウンターで試します。まず、普通のReducerを以下のように作ります。(面倒臭いのでaction関数使わずに)
store.js
import {combineReducers, createStore} from 'redux';
export const counter = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
default:
return state;
}
};
export default createStore(combineReducers({counter}));
各ファイルでこれを読み込んでstore.dispatch
します。
コンポーネントでステートが使えるように
with-state.js
import reduxStore from './store';
export default {
data() {
return {
state: reduxStore.getState(),
}
},
created() {
reduxStore.subscribe(() => {
this.state = reduxStore.getState();
});
}
}
これをmixins
で取り組みます。
取り込んだコンポーネントは、this.state
にその時のステートを持ち、ステートが更新されたら新たなステートでthis.state
が更新されるようになります。
カウンターコンポーネント
components/Counter.vue
<template>
<button @click="increment">{{state.counter}}</button>
</template>
<script>
import withState from '../with-state';
import store from '../store';
export default {
mixins: [withState],
name: 'Counter',
methods: {
increment() {
store.dispatch({type: 'INCREMENT'});
},
}
}
</script>
INCREMENT
アクションを発行すると、counter
ステートが更新されて、mixin
の中のsubscribe
でthis.state
を更新して再レンダリングという感じです。
react-redux
のconnect
みたく
まずwith-state.js
を変えます。やってることはmapStateToProps
みたいな感じです。
with-state.js
import reduxStore from './store';
export default mapState => ({
data() {
return {
...mapState(reduxStore.getState()),
}
},
created() {
reduxStore.subscribe(() => {
const mappingState = mapState(reduxStore.getState());
for (const key in mappingState) {
// 値が変わってなければ再代入してしまっても`updated`されないようなので
// 入れてしまう
this[key] = mappingState[key];
}
});
}
});
コンポーネント側も変えます。
components/Counter.vue
- <button @click="increment">{{state.counter}}</button>
+ <button @click="increment">{{counter}}</button>
==================================================================================
- mixins: [withState],
+ mixins: [withState(state => ({counter: state.counter}))],
counter
が直接使えるようになりました。
Redux Devtools
これはReactで使うのと同じ方法で使えます。
store.js
- export default createStore(combineReducers({counter}));
+ export default createStore(
+ combineReducers({counter}),
+ window.__REDUX_DEVTOOLS_EXTENSION__ &&
+ window.__REDUX_DEVTOOLS_EXTENSION__(),
+ );