reselect鏄�庢牱鎻愬崌react缁勪欢娓叉煋鎬ц兘鐨勶紵

reselect鏄粈涔堬紵

reselect鏄厤鍚�redux浣跨敤鐨勪竴娆捐交閲忓瀷鐨勭姸鎬侀�夋嫨搴擄紝鐩殑鍦ㄤ簬褰搒tore涓殑state閲嶆柊鏀瑰彉涔嬪悗锛屼娇寰楀眬閮ㄦ湭鏀瑰彉鐨勭姸鎬佷笉浼氬洜涓烘暣浣撶殑state鍙樺寲鑰屽叏閮ㄩ噸鏂版覆鏌擄紝鍔熻兘鏈夌偣绫讳技浜庣粍浠朵腑鐨勭敓鍛藉懆鏈熷嚱鏁�shouldComponentDidUpdate锛屼絾鏄畠浠苟涓嶆槸涓�涓笢瑗裤�備笅闈㈡槸瀹樻柟鐨勪竴浜涚畝浠嬶細

  • Selectors can compute derived data, allowing Redux to store the minimal possible state.
  • Selectors are efficient. A selector is not recomputed unless one of its arguments changes.
  • Selectors are composable. They can be used as input to other selectors.

[娉╙锛氬苟涓嶆槸reselect闈炶鍜宺edux缁戝畾浣跨敤涓嶅彲锛屽彲浠ヨreselect鍙槸涓�涓猠nhancement锛屽苟涓嶄唬琛ㄥ己鑰﹀悎銆�

浠�涔堟椂鍊欑敤reselect?

  • store鐘舵�佹爲搴炲ぇ涓斿眰娆¤緝娣�
  • 缁勪欢涓殑state闇�瑕佺粡杩囧鏉傜殑璁$畻鎵嶈兘鍛堢幇鍦ㄧ晫闈笂

涓汉璁や负绗﹀悎杩欎袱鐐瑰氨鍙互浣跨敤reselect锛屼负浠�涔堬紵绠�鍗曠殑state鎴栬鏍规湰瀹屽叏娌℃湁蹇呰寮曞叆redux锛岀姸鎬佺鐞嗙粍浠跺唴閮ㄥ氨鍙互娑堝寲锛屽啀鑰卹eselect鍙槸鍦ㄥ弬鏁扮骇鍒殑缂撳瓨锛屽鏋滅粍浠剁姸鎬侀�昏緫骞朵笉鏄壒鍒鏉傦紝鍙槸绠�鍗曠殑getter锛岄偅涔熷彲涓嶅繀寮曞叆reselect銆�

[寤鸿]锛氬缓璁紩鍏ヤ簡redux灏卞彲浠ュ紩鍏eselect锛屽幓鐪嬪畼鏂圭殑婧愮爜锛屾�诲叡鍔犺捣鏉ユ墠鐭煭鐨�108琛屼唬鐮侊紝瀵规祴璇曞苟娌℃湁浠�涔堟垚鏈紝鍚屾椂鍔犲叆涔熶笉浼氬鎵撳寘浣撶Н閫犳垚浠�涔堝奖鍝嶏紝浣嗘槸鏈変簺鏃跺�欏缁勪欢娓叉煋鐨勬�ц兘鍗存湁寰堝ぇ鐨勬敼鍠勩��

鍩烘湰鐢ㄦ硶

杩欓噷鏄洿鎺opy鐨勫畼鏂逛粨搴撲腑鐨勪唬鐮�

import { createSelector } from 'reselect'

const shopItemsSelector = state => state.shop.items
const taxPercentSelector = state => state.shop.taxPercent

const subtotalSelector = createSelector(
  shopItemsSelector,
  items => items.reduce((acc, item) => acc + item.value, 0)
)

const taxSelector = createSelector(
  subtotalSelector,
  taxPercentSelector,
  (subtotal, taxPercent) => subtotal * (taxPercent / 100)
)

export const totalSelector = createSelector(
  subtotalSelector,
  taxSelector,
  (subtotal, tax) => ({ total: subtotal + tax })
)

let exampleState = {
  shop: {
    taxPercent: 8,
    items: [
      { name: 'apple', value: 1.20 },
      { name: 'orange', value: 0.95 },
    ]
  }
}

console.log(subtotalSelector(exampleState)) // 2.15
console.log(taxSelector(exampleState))      // 0.172
console.log(totalSelector(exampleState))    // { total: 2.322 }

reselect鏄�庝箞浼樺寲浠g爜鎬ц兘鐨勶紵

  • 鏁翠綋store灞傜骇state鐨勭紦瀛�
  • 缁勪欢绾у埆state鐨勭紦瀛�
const selector = memoize(function () {
  const params = []
  const length = dependencies.length

  for (let i = 0; i < length; i++) {
    // apply arguments instead of spreading and mutate a local list of params for performance.
    params.push(dependencies[i].apply(null, arguments))
  }

  // apply arguments instead of spreading for performance.
  return memoizedResultFunc.apply(null, params)
})

selector.resultFunc = resultFunc
selector.dependencies = dependencies
selector.recomputations = () => recomputations
selector.resetRecomputations = () => recomputations = 0
return selector

鍑芥暟鏁翠綋杩斿洖鐨勫氨鏄繖涓�selector锛屽洜涓烘垜浠皟鐢�createSelector锛屽叾瀹炶繑鍥炵殑鏄竴涓嚱鏁帮紝鎵�浠�memoize杩斿洖鐨勫叾瀹炰篃鏄竴涓嚱鏁帮紝閭d箞selector涓仛浜嗕粈涔堬紵

export function defaultMemoize(func, equalityCheck = defaultEqualityCheck) {
  let lastArgs = null
  let lastResult = null
  // we reference arguments instead of spreading them for performance reasons
  // 杩欓噷浣滀负杩斿洖鐨勫嚱鏁帮紝浼犲叆鐨勫弬鏁板嵆涓簊tate
  return function () {
    if (!areArgumentsShallowlyEqual(equalityCheck, lastArgs, arguments)) {
      // apply arguments instead of spreading for performance.
      lastResult = func.apply(null, arguments)
    }

    lastArgs = arguments
    return lastResult
  }
}

memoize鏄痳eselect涓彁渚涚殑榛樿缂撳瓨鍑芥暟锛屽彲浠ョ殑寰楃煡鎵ц杩欎釜鍑芥暟鐨勬椂鍊欙紝杩斿洖鐨勫嚱鏁板嵆涓轰笂闈唬鐮佷腑鐨�selector锛岄偅涔�arguments鍗充负浼犲叆鐨剆tate锛岄�氳繃areArgumentsShallowlyEqual姣旇緝涓ゆ浼犲叆鐨勫弬鏁版槸鍚︾浉绛夛紝娉ㄦ剰锛岃繖閲屾槸娴呮瘮杈冿紝鍗崇涓�灞傚紩鐢ㄧ殑姣旇緝

function defaultEqualityCheck(a, b) {
  return a === b
}

褰撲袱娆′紶鍏ョ殑鍊煎瓨鍦ㄥ彉鍖栫殑鏃跺�欙紝閭d箞灏变細鎵ц

func.apply(null, arguments)

杩欓噷浼氳绠楀緱鍒版墍鏈夌殑渚濊禆锛岀劧鍚庡緱鍒颁笅涓�杞紦瀛樺嚱鏁扮殑params銆�

灏眗edux鐨剅educer鏉ヨ锛岃繖灞傜紦瀛樺苟娌℃湁浠�涔堜綔鐢紝鐪嬬湅reducer浠g爜锛�

function reducer(state, action) {
  switch (action.type): 
    case REQUEST_TODO_PENDING:
        return { ...state, loading: true };
    case REQUEST_TODO_LIST_SUCCESS:
        return { ...state, list: ['todo'], loading: false };
    // ...
    // default
}

redux绀惧尯鎺ㄥ磭鎵�鏈夌殑state閮芥槸涓嶅彲鍙樼殑锛屾墍浠ュ彧瑕乨ispatch浜嗕竴涓猘ction锛屾瘡娆¤繑鍥炵殑state蹇呯劧浼氭槸涓�涓柊鐨勫璞★紝瀵逛簬娴呮瘮杈冩瘡娆¤繑鍥炵殑缁撴灉蹇呯劧鏄�true;

鎵�浠ワ紝缂撳瓨鐨勫叧閿繕鍦ㄧ浜屽眰momoize锛屽洜涓鸿繖閲岀殑state骞朵笉鏄瘡涓�娆¢兘蹇呴』鍙樺寲锛�

const resultFunc = funcs.pop()
const dependencies = getDependencies(funcs)

const memoizedResultFunc = memoize(
  function () {
    recomputations++
    // apply arguments instead of spreading for performance.
    return resultFunc.apply(null, arguments)
  },
  ...memoizeOptions
)

鐪熸浠g爜鐨勬墽琛屽湪resultFunc.apply(null, arguments)锛岃繖閲岀紦瀛樼殑閫昏緫璺熶笂闈㈡病浠�涔堝尯鍒紝杩欓噷灏变笉鍦ㄨ瑙d簡銆�resultFunc鏄�createSelector涓殑鏈�鍚庝竴涓弬鏁�

const shopItemsSelector = state => state.shop.items
const taxPercentSelector = state => state.shop.taxPercent

const subtotalSelector = createSelector(
  shopItemsSelector,
  items => items.reduce((acc, item) => acc + item.value, 0)
)

澶у鍙互鑷瀵圭収涓�涓嬩笂闈㈢殑杩欎釜渚嬪瓙锛岄偅涔�arguments灏辨槸绗簩涓嚱鏁扮殑鍙傛暟锛屼篃灏辨槸绗竴姝ョ紦瀛樺嚱鏁颁腑鐨�params銆�

鎬荤粨

濂戒簡锛屽氨鍟板棪杩欎箞澶氫簡锛屾渶鍚庯紝澶氳涔︼紝澶氱湅鎶ワ紝灏戝悆闆堕锛屽鐫¤馃槳馃槳馃挙

你可能感兴趣的:(reselect鏄�庢牱鎻愬崌react缁勪欢娓叉煋鎬ц兘鐨勶紵)