Action Action是store數據的唯一來源。需使用store.dispatch()將所需的action傳到store。Action是把伺服器響應的數據或者用戶輸入的數據、和其他一些非View的數據傳入store的有效載荷。Action實際上是JS的普通對象。示例: 需要註意的是:應該儘可能 ...
Action
Action是store數據的唯一來源。需使用store.dispatch()將所需的action傳到store。Action是把伺服器響應的數據或者用戶輸入的數據、和其他一些非View的數據傳入store的有效載荷。Action實際上是JS的普通對象。示例:
{ type:"ADD_TODO", //type為必須的欄位,值為字元串或存放字元串的變數 text:"我是示例" }
需要註意的是:應該儘可能的減少在action中傳遞的數據。
Action創建函數
Action創建函數只是簡單的返回一個action。示例:
function addTodo(text) { return { type: ADD_TODO, text } }
Redux提供的bindActionCreators()可以自動把多個action創建函數綁定到dispatch()方法上。
Reducer
Reducers 指定了應用狀態的變化如何響應 actions 併發送到 store 的,記住 actions 只是描述了有事情發生了這一事實,並沒有描述應用如何更新 state。
reducer 就是一個純函數,接收舊的 state 和 action,返回新的 state。
(previousState, action) => newState
永遠不要在reducer里做這些操作:
- 修改傳入參數;
- 執行有副作用的操作,如API請求和路由跳轉;
- 調用非純函數,如Data.now()或Math.random();
reducer一定要保持純凈。只要傳入參數相同,返回計算得到的下一個state就一定相同。沒有特殊情況、沒有副作用、沒有API請求、沒有變數修改,單純執行計算
combinerReducers()方法只是生成一個函數,這個函數用來調用你的一系列reducer,每個reducer根據他們的key來篩選出state中的一部分數據並處理,然後這個生成的函數再將所有reducer的結果合成一個大的對象。//ES6的寫法 import { combineReducers } from 'redux' import * as reducers from './reducers' const todoApp = combineReducers(reducers)
Store
Store的職責:
- 維持應用的state;
- 提供 getState() 方法來獲取state;
- 提供 dispatch(action) 方法更新state;
- 通過 subscribe(listener) 註冊監聽器;
- 通過 subscribe(listener) 返回的函數註銷監聽器;
Redux 應用只有一個單一的 store
store的使用示例:
//創建store let store = createStore(todoApp); //列印初始狀態 console.log("初始狀態======》",store.getState()); //每次state更新時,列印日誌 //註意subscribe()返回一個函數用來註銷監聽器 const unsubscribe = store.subscribe(()=>console.log("state有更新=======》",store.getState())) //發起一系列action store.dispatch(addTodo("learn about actions")); store.dispatch(addTodo("learn about reducers")); store.dispatch(addTodo("learn about store")); store.dispatch(toggleTdo(0)); store.dispatch(toggleTdo(1)); store.dispatch(setVisibilityFilter(VisibilityFilters.SHOW_COMPLETED)); //停止監聽 unsubscribe();
數據流
Redux應用中數據的生命周期遵循4個步驟:
- 調用 store.dispatch(action) 。 action 就是一個描述“發生了什麼”的普遍對象,可將其理解為通過 store.dispatch 來告訴reducer發生了什麼
- Redux store調用傳入的reducer函數。根據傳入的action.type來更新state
- 根reducer應該把多個子reducer輸出合併成一個單一的state樹。可使用原生的 combineReducers() 輔助函數,也可自己實現
- Redux store保存了根reducer返回的完整的state樹
React-Redux
connect():生成容器組件;
mapStateToProps():指定如何把當前Redux Store state映射到展示組件的props中。示例:
//VisibleTodoList 需要計算傳到 TodoList 中的 todos,
//所以定義了根據 state.visibilityFilter 來過濾 state.todos 的方法,併在 mapStateToProps 中使用 const getVisibleTodos = (todos, filter) => { switch (filter) { case 'SHOW_COMPLETED': return todos.filter(t => t.completed) case 'SHOW_ACTIVE': return todos.filter(t => !t.completed) case 'SHOW_ALL': default: return todos } } const mapStateToProps = state => { return { todos: getVisibleTodos(state.todos, state.visibilityFilter) } }
mapDispatchToProps():接受dispatch()方法並返回期望註入到展示組件的props中的回調方法。示例:
//VisibleTodoList 向 TodoList 組件中註入一個叫 onTodoClick 的 props ,
//並且onTodoClick 能分發 TOGGLE_TODO 這個 action const mapDispatchToProps = dispatch => { return { onTodoClick: id => { dispatch(toggleTodo(id)) } } }
Redux的整體流程:
- 將action傳入dispatch()來觸發reducer
- reducer響應action,並根據action.type來處理舊的state數據,然後返回新的state數據,將新的state數據發送到store
- store保存reducer返回的新的state,然後所有訂閱 store.subscribe(listener) 的監聽器都將被調用,以此來創建容器組件.(在react-redux中我們使用connect()方法來生成,所以不用手寫 store.subscribe() 來生成容器組件)