[Redux] Redux store 介紹
Store
Redux 的 store
主要就是所謂的 store tree
,集中管理了整個 app 的狀態資訊。整個 Redux 就是以 store
為核心來運作,所以 store
只會且只能有一個,而且所有東西都會被包在裡面(reducer
和middleware
等等)
引入 createStore
createStore
顧名思義就是拿來建立 store
的玩意兒。以下三種方法都可以建立 createStore
,端看你是用哪種方式引進 redux 的:
const { createStore } = Redux; // ES 6 include redux.js in HTML
var createStore = Redux.createStore; // ES 5 include redux.js in HTML
import { createStore } from 'redux'; // with webpack and babel
建立 store
store
需包含 reducer
,如此才知道在發生某些 action
時,該怎麼做動得到目前該有的狀態(state)。所以將 reducer
引入 createStore
後,即可建立 store
:
const store = createStore(reducers);
store 的方法
store 有以下三個最主要的方法:
store.getState()
: 顧名思義就是可以得到目前的狀態state
store.dispatch(action);
:發送一個行為,會找到對應的reducer
執行後,得到新的state
store.subscribe(render);
:向store
訂閱dispatch
事件,當dispatch
發生時會執行訂閱的 callback (render
)
所以如果自己寫一個 createStore
的話,大概是長這樣:
const createStore = (reducer) => {
let state;
let listeners = [];
const getState = () => state;
const dispatch = (action) => {
state = reducer(state, action);
listeners.forEach(listener => listener());
};
const subscribe = (listener) => {
listeners.push(listener);
return () => {
listeners = listeners.filter(l => l !== listener);
};
};
dispatch({}); // to initial state
return { getState, dispatch, subscribe };
};
這邊需要特別強調的是,dispatch
在核心概念中,是唯一可以改變 state
的方法。一開始會先 dispatch({})
讓 state 獲得初始值。
Store 應用例子
以計數器為例子:
const { createStore } = Redux;
// var createStore = Redux.createStore;
// import { createStore } from 'redux';
// reducer
const counter = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
// create a store
const store = createStore(counter);
console.log(store.getState()); // 0
// dispatch an action
store.dispatch({ type: 'INCREMENT' });
console.log(store.getState()); // 1
// subscribe a callback function
store.subscribe(() => {
document.body.innerText = store.getState();
});
// dispatch an action due to event(click)
document.addEventListener('click', () => {
store.dispatch({ type: 'INCREMENT' });
});