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
銆�
鎬荤粨
濂戒簡锛屽氨鍟板棪杩欎箞澶氫簡锛屾渶鍚庯紝澶氳涔︼紝澶氱湅鎶ワ紝灏戝悆闆堕锛屽鐫¤馃槳馃槳馃挙