reselect的替代者repure
在為什麼我們需要reselect 我們闡述了 reselect的必要性。
簡單回顧一下:
class UnusedComp extends Component {
render() {
const { a, b, c, fab, hbc, gac, uabc } = this.props
return (
<div>
<h6>{a}</h6>
<h6>{b}</h6>
<h6>{c}</h6>
<h6>{fab}</h6>
<h6>{hbc}</h6>
<h6>{gac}</h6>
<h6>{uabc}</h6>
</div>
)
}
}
其中fab = f(a, b), hbc = h(b, c), gac = g(a, c), uabc = u(a, b, c)。 對於這樣的元件,我們只需要儲存狀態a, b, c, 對於fab, hbc, gac, uabc這種可以完全通過現有 狀態推匯出來的,稱為‘衍生屬性’。 我們應該只存最小集合的狀態,這樣方便我們更新狀態, 保證資料層正確性等 很多好處。
也正如為什麼我們需要reselect指出, 這樣容易帶來沒有意義的函式執行(具體看原文)。 解決方法如下:
//
//
import { createSelector } from `reselect`
import { f, h, g, u } from `./xx`
fSelector = createSelector(
a => state.a,
b => state.b,
(a, b) => f(a, b)
)
hSelector = createSelector(
b => state.b,
c => state.c,
(b, c) => h(b, c)
)
gSelector = createSelector(
a => state.a,
c => state.c,
(a, c) => g(a, c)
)
uSelector = createSelector(
a => state.a,
b => state.b,
c => state.c,
(a, b, c) => u(a, b, c)
)
...
function mapStateToProps(state) {
const { a, b, c } = state
return {
a,
b,
c,
fab: fSelector(state),
hbc: hSelector(state),
gac: gSelector(state),
uabc: uSelector(state)
}
}
簡單點。。。
用過mobx的,不會忘記@compute的簡潔, 那麼redux生態下有替代reselct的簡潔的方案嗎? 衍生
屬性是可以通過基本屬性推匯出來的, 並且相同的基本屬性一定推匯出相同的值。
如fab = f(a, b)。 只要a,b相同,那麼fab一定相同。 基於這一點,我們可以有:
function x(func) {
let oldargs = []
let oldresult = null
return function(...args) {
if(equal(oldargs, args)) { // equal?
return oldresult
}
oldargs = args
oldresult = func(...args)
return oldresult
}
}
/// now we use
function f(a, b) {
...
}
export const xf = x(f)
函式x賦予了 衍生函式 記憶的功能,就像reselect一樣, 書寫起來卻方便了很多。
得益於redux在equal(oldargs, args)
的時候, 我們可以直接使用 === 來比較引數
repure
API
repure 提供3個方法 repureCreator(cacheSize, equalityCheck), repure, repureOneCacheCreator(equalityCheck)
repureCreator(cacheSize, equalityCheck)
函式repureCreator 返回一個repure, 可以快取cacheSize個結果。 在判斷入參是否相同的時候使用 equalityCheck。
預設的 equalityCheck 是:
function defaultEqualityCheck(a, b) {
return a === b
}
另外提供一個 shallowEqual: import { shallowEqual } from `repure`
repure
大部分情況下,你應該使用這個方法。 這個和你使用reselct的createSelector的效果是一樣的, 使用===
比較相等, cacheSize是1。
repure接受一個pure function, 返回這個方法的 快取版本
repureOneCacheCreator(equalityCheck)
repureCreator 在cacheSize=1 時的優化版本
另外提供一個 batchRepure(obj, repure) 方法。 可以批量repure。
end
repure重寫開頭的例子
首先安裝npm install repure --save
import repure, { batchRepure } from `repure`
import * as allfunc from `./xx`
const { f, h, g, u } = batchRepure(allfunc, repure)
...
function mapStateToProps(state) {
const { a, b, c } = state
return {
a,
b,
c,
fab: f(a, b),
hbc: h(b, c),
gac: g(a, c),
uabc: u(a, b, c)
}
}