over 3 years ago

reselect 官方範例

import { createSelector } from 'reselect'

// 建立取出某個 state 的函數
const shopItemsSelector = state => state.shop.items
const taxPercentSelector = state => state.shop.taxPercent

// 利用 createSelector 傳入 shopItemsSelector 函數物件
// items => shopItemsSelector return 的 物件
const subtotalSelector = createSelector(
  shopItemsSelector,
  items => items.reduce((acc, item) => acc + item.value, 0)
)

// 利用 createSelector 傳入 shopItemsSelector, taxPercentSelector 函數物件
// subtotal => shopItemsSelector return 的 物件
// taxPercent => taxPercentSelector return 的 物件
const taxSelector = createSelector(
  shopItemsSelector,
  taxPercentSelector,
  (subtotal, taxPercent) => subtotal * (taxPercent / 100)
)

// 可傳入上述利用 createSelector 所產生的 subtotalSelector, taxSelector 函數物件
// subtotal => subtotalSelector return 的 物件
// tax => taxSelector return 的 物件
export const totalSelector = createSelector(
  subtotalSelector,
  taxSelector,
  (subtotal, tax) => ({ total: subtotal + tax })
)

// 測試用的 state
let exampleState = {
  taxPercent: 8,
  items: [
    { name: 'apple', value: 1.20 },
    { name: 'orange', value: 0.95 },
  ]
}

// 執行上面所寫好 Selector 函數
console.log(subtotalSelector(exampleState)) // 2.15
console.log(taxSelector(exampleState))      // 0.172
console.log(totalSelector(exampleState))    // { total: 2.322 }

React Redux 實作

建立 selectors.js
參考 https://github.com/reactjs/reselect#sharing-selectors-with-props-across-multiple-components

import { createSelector } from 'reselect';
// 設定某模組所要用的 state 名稱
import { NAME } from './constants';

// 取出 redux 配置 store 的 state 
const getAllState = (state, props) => state[NAME];

// 利用 return function 消除 cached 
const makeGetAllState = () => {
  return createSelector(
    getAllState,
    allState => {
      return {
        key: allState.get("key"),
        isLoading: allState.get("isLoading"),
        userlist: allState.get("userlist"),
        totalSize : allState.get("totalSize"),
        currentPage: allState.get("currentPage"),
        listSize: allState.get("listSize"),
      }
    }
  )
}

export default makeGetAllState;

於要執行 Redux 的 connect 內配置所建立好的 selectors
參考範例

import makeGetAllState from '../selectors';
...
..
const makeMapStateToProps= () => {
  const mapStateToProps = (state, props) => {
    return {
      // 使用建立好的 selectors 函數運算取出所要的 store state
      state: makeGetAllState()(state, props) 
    }
  }
  return mapStateToProps;
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(actions, dispatch)
  }
}

export default connect(makeMapStateToProps, mapDispatchToProps)(Main)

搭配使用 redux-thunk 執行 Redux Async Actions

import makeGetAllState from '../selectors';
...
..
export function loadUserList() {
  return function(dispatch, getState) {
  const state = getState();
  const {key, currentPage, listSize} =  makeGetAllState()(state, null);
  ...
  ..
  .
}

使用 reselect 建立 selectors 抽出 Redux store 指定的 state
來更進一步於外部集中管理 state 內的資料
並減少 Component 內對 state 的邏輯運算

來源
https://github.com/reactjs/reselect

← Object.assign React Redux 自訂 Middleware →
 
comments powered by Disqus