【安裝依賴】
npm install --save redux
npm install --save react-redux
npm install --save-dev redux-devtools
【核心概念】
-
state被存放在哪裏?
應用中所有的 state 都以一個對象樹的形式儲存在一個單一的 store 中。
-
怎麼改變state(state裏面的數據)?
不再直接通過選擇器setter來改變state中的數據。唯一改變 state 的辦法是觸發 action,action 是一個用於描述已發生事件的普通對象, 每個狀態state對應不同的action。
-
action怎麼改變state?
編寫專門的函數來決定每個 action 如何改變應用的 state,這個函數被叫做 reducer。
就是這樣!
import { createStore } from 'redux';
/**
* 這是一個 reducer,形式爲 (state, action) => state 的純函數。
* 描述了 action 如何把 state 轉變成下一個 state。
*
* state 的形式取決於你,可以是基本類型、數組、對象、
* 甚至是 Immutable.js 生成的數據結構。惟一的要點是
* 當 state 變化時需要返回全新的對象,而不是修改傳入的參數。
*
* 下面例子使用 `switch` 語句和字符串來做判斷,但你可以寫幫助類(helper)
* 根據不同的約定(如方法映射)來判斷,只要適用你的項目即可。
*/
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
// 創建 Redux store 來存放應用的狀態。
// API 是 { subscribe, dispatch, getState }。
let store = createStore(counter);
// 可以手動訂閱更新,也可以事件綁定到視圖層。
store.subscribe(() =>
console.log(store.getState())
);
// 改變內部 state 惟一方法是 dispatch 一個 action。
// action 可以被序列化,用日記記錄和儲存下來,後期還可以以回放的方式執行
store.dispatch({ type: 'INCREMENT' });
// 1
store.dispatch({ type: 'INCREMENT' });
// 2
store.dispatch({ type: 'DECREMENT' });
// 1
reducer 只是一個接收 state 和 action,並返回新的 state 的函數。
【三大原則】
使用純函數來執行修改
爲了描述 action 如何改變 state tree ,你需要編寫 reducers。
Reducer 只是一些純函數,它接收先前的 state 和 action,並返回新的 state。剛開始你可以只有一個 reducer,隨着應用變大,你可以把它拆成多個小的 reducers,分別獨立地操作 state tree 的不同部分,因爲 reducer 只是函數,你可以控制它們被調用的順序,傳入附加數據,甚至編寫可複用的 reducer 來處理一些通用任務,如分頁器。
function visibilityFilter(state = 'SHOW_ALL', action) {
switch (action.type) {
case 'SET_VISIBILITY_FILTER':
return action.filter
default:
return state
}
}
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
{
text: action.text,
completed: false
}
]
case 'COMPLETE_TODO':
return state.map((todo, index) => {
if (index === action.index) {
return Object.assign({}, todo, {
completed: true
})
}
return todo
})
default:
return state
}
}
import { combineReducers, createStore } from 'redux'
let reducer = combineReducers({ visibilityFilter, todos })
let store = createStore(reducer)