1. 程式人生 > >React Native之Redux使用詳解之Reducers(30)

React Native之Redux使用詳解之Reducers(30)

React Native之Redux使用詳解之Reducers

一. Reducers

Actions 描述發生了什麼,但不能指定響應中state怎麼變化,這是Reducers的工作。

1. 設計State Shape

在Redux中,所有state儲存為一個單一物件。寫任何程式碼之前考慮好它的 Shape是一個好的注意。

對於我們的 todo 應用,我們想去儲存兩種不同事物:

  • 當前所選的可見性過濾器
  • todos 實際列表

你會發現在這個state樹中你需要儲存一些資料,以及一些UI狀態。但是必須保持資料和 UI 狀態分離。

{
    visibilityFilter
: 'SHOW_ALL', todos: [ { text: 'Consider using Redux', completed: true,
}, { text: 'Keep all state in a single tree', completed: false } ] }

【注意 Relationships】
複雜應用中,分離不同實體,各個實體相互依賴。官方建議保持你的 state 儘可能規範沒有任何重疊。保持每個實體儲存在一個帶有ID作為key的物件中,通過IDs關聯其他實體或者列表。可以假定認為app的state作為資料庫。這個方式在

normalizr’s 文件。例如,todosById: { id -> todo }

2. 操作Actions

如果現在已經確定好整個App的state物件, 接下來準備為App寫一個Reducer. 該Reducer 是一個以前一狀態數和一個action作為引數,返回新狀態的純函式.

(previousState,action) => newState

保持reducer純函式是非常重要,我們不應該在一個reducer中做以下操作:

  • 複製傳入的引數
  • 執行副作用操作,如 API 呼叫和路由轉換
  • 呼叫非純函式, 如 Date.now()Math.random()

    .

    我將探索如何執行副作用在advanced walkthrough. 目前,我們只需記住reducer必須純淨. 它應該計算下一個狀態並返回. No surprises. No side effects. No API calls. No mutations. Just a calculation

我們逐漸寫一個reducer, 進而進一步理解之前提到的actions

我們以指定初始化狀態開始寫程式, Redux 第一次將傳入 undefined的state到我們定義的reducer. 這是返回該APP初始化狀態的時機.
Show your code:

import { VisibilityFilter} from './actions'

const initialState={
    visibilityFilter: VisibilityFilter.SHOW_ALL,
    todos:[]
}

function todo(state,action) {
  if(typeof state === 'undefined') {
    return initialState;
}

    // For now, don't handle any actions, and just return the state given us.
return state;

}
function todo(state=initialState,action){
// For now, don't handle any actions,and just return the state given to us.
 return state;
}

現在我們來操作 SET_VISIBILITY_FILTER. 我們需要做的就是改變狀態visibilityFilter

function todo(state=initialState,action) {
  switch(action) {
    case 'SET_VISIBILITY_FILTER':
    return Object.assign({},state,{
    visibilityFilter:action.filter
    })
    default:
      return state;
    }
}

注意:
1. 我們沒有複製state. 而是通過Object.assign()建立一個複製. Object.assign(state, {visibilityFilter: action.filter })是錯誤寫法: 該寫法將會複製第一個引數. 你也能學習object spread operator proposal 去寫這個 {…state, …newState}.

2.我們返回前一狀態在預設case.在一些未知的action情況下,我們需要返回前一狀態.

3.Object.assign()
Object.assign()是ES6語法,但是它仍然沒有被大多數瀏覽器實現, 開發者需要利用polyfill去寫Babel plugin,或者利用其他的庫,如_assign .
4.Note on switch and Boilerplate

The switch statement is not the real boilerplate. The real boilerplate of Flux is conceptual: the need to emit an update, the need to register the Store with a Dispatcher, the need for the Store to be an object (and the complications that arise when you want a universal app). Redux solves these problems by using pure reducers instead of event emitters.

It’s unfortunate that many still choose a framework based on whether it uses switch statements in the documentation. If you don’t like switch, you can use a custom createReducer function that accepts a handler map, as shown in “reducing boilerplate”.