為什麼我們需要reselect

2021-09-14 06:24:45 字數 4212 閱讀 2964

先看下下面的乙個元件

import react,  from 'react'

import from 'react-redux'

class unusedcomp extends component = this.props

return ()}

}function f(x, y)

function h(x, y)

function g(x, y)

function u(x, y, z)

這個unusedcomp 元件關心這樣的幾個props: a, b, c, f(a,b), h(b, c), g(a, c), u(a, b, c), 其中f, h, g, u分別是乙個函式。 關於這幾個計算的值, 我們應該怎麼處理呢?

第一種, 我們把所有值存在redux, 所有store的結構大概是這樣的:

store =
這樣我們的元件簡單了, 只需要直接取值渲染就好const = this.props。 那麼問題來了, reducer的函式應該怎麼處理呢? 對應的如下:

switch(action.type) 

}case 'changeb':

case 'changec':

}

我們的reducer 函式非常複雜了, 我們每更新乙個狀態值。 都得維護與這個值相關的值, 不然就會有資料不一致。

為了保證資料流的清晰, 更新的簡單。 我們只把最基本的狀態儲存在redux。store的結構和redcuer函式如下:

store = 

...switch(action.type)

}...

}

此刻元件可能是這樣的:

class unusedcomp extends component  = this.props

const fab = f(a, b)

const hbc = h(b, c)

const gac = g(a, c)

const uabc = u(a, b, c)

return ()}

}

或者這樣的:

class unusedcomp extends component  = this.props

this.fab = f(a, b)

this.hbc = h(b, c)

this.gac = g(a, c)

this.uabc = u(a, b, c)

}render() = this.props

return ()}

}

對於第一種情況, 當元件ownprops(元件自身屬性, 非redux傳遞), 或者setstate 的時候 都會執行計算。

對於第二鐘情況, 當元件ownprops 變化的時候, 會執行計算。

而且這兩種都違背了 我們的基本原則:保持元件邏輯簡單

讓資料邏輯離開元件!

// 可以寫成函式式元件

class unusedcomp extends component = this.props

return ()}

}function mapstatetoprops(state) = state

return

}unusedcomp = connect(mapstatetoprops)(unusedcomp)

元件很簡單, 接收資料展示就可以了。 看似很美好! 我們知道當store資料被改變的時候, 會通知所有connect的元件(前提是沒被銷毀)。

所有假設頁面上還有 a, b, c三個元件, 這三個元件任意狀態(存在redux的狀態)的改變, 都會出發這裡的 f, h, g, u的執行。。。聽起來很扯!!!的確很扯!(在redner裡面, willreciveprops裡面計算是這裡是不會引起函式執行的)。 但是這通常不是問題, 因為我們一般每個頁面只有乙個 容器元件 和redux互動, 其他子元件通過props的方式獲取資料和action。 而且react-router在切換路由的時候, 是會銷毀掉前乙個路由的元件。 這樣同乙個時間只會有 乙個 容器元件。

在考慮一種情況, 假設unusedcomp還有 x, y, z 狀態屬性, 存在redux。 這3個屬性就是簡單的3個值, 只用來展示。 可是當x, y, z改變的時候,也會觸發計算。 這裡發生的計算不管是在render裡面計算, 還是willreciveprops, 還是mapstatetoprops裡 都無法避免。

彷彿我們依據找到了 方法:

redux只存基本狀態

react-router + 單 容器元件 元件

現實很殘酷! 實際上x, y, z這種屬性, 一定大量存在。 光是這一點就會導致大量的無效計算。 之前討論的3種方式 (render, willrecive,mapstatetoprops)無法避免這種計算。

另外mapstatetoprops 還會被其他store的值改變影響 ,畢竟react-router + 單 容器元件 元件 這種組織方式只是最美好的情況。 我們有些業務就是處於效能的考慮,沒有銷毀之前路由的元件, 用我們自己的路由。有些頁面也不是 單容器元件,尷尬!!

明顯的, 我們是知道 x, y, z的變化是不需要計算的, 而a,b, c變化是需要計算的。 如何描述給程式呢?另外 mapstatetoprops 這種方式還帶來了好處, 我們在描述的時候,不會侵入元件!!。

最原始的描述:

let memoizestate = null

function mapstatetoprops(state) = state

if (!memoizestate)

} else

if (!(b === memoizestate.b && c === memoizestate.c) )

if (!(a === memoizestate.a && c === memoizestate.c) )

if (!(a === memoizestate.a && b === memoizestate.b && c === memoizestate.c) )

memoizestate.a = a

memoizestate.b = b

memoizestate.c = c

}return memoizestate

}

首選, 我們知道fab的值與a,b 有關, 所以當a, b 有變化的時候,f需要重新執行。 其他同理, 這樣的話函式一定是只在必要的時候執行。

reselect 解決了我們上面的那個問題, 我們也不必每次用這個最原始的描述了, 對應的reselect描述是這樣的

import  from 'reselect'

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) = state

return

}

在 createselector 裡面我們先定義了 input-selector 函式, 最後定義了 值是如何計算出來的。 selector保證了,當input-selector 返回結果相等的時候,不會計算。

如果 你是react-router 並且是 單 容器元件。 那麼可能在 mapstatetoprops裡面計算,效能問題並不大。 而且效能不應該是我們第一要考慮的東西, 我們首先要考慮的是簡單性,尤其是元件的簡單性。 當我們的業務複雜到需要考慮效能的時候, reselect是我們不錯的選擇!

我們為什麼需要睡眠

隨著時光的消逝,你是否發覺眼角的皺紋逐漸加深?變得越來越粗糙黯淡?記憶力也開始衰退?這個時候很多人都會感慨 時光易逝,容顏易老 並且開始習慣接受自己已慢慢變老,提前加入老人的行列。其實,這一切也許只是因為你長時間睡眠不足造成的。如果能夠早些了解這些常識,並引起足夠重視,你的青春也許還能保留十年。睡眠...

我們為什麼需要睡眠

隨著時光的消逝,你是否發覺眼角的皺紋逐漸加深?變得越來越粗糙黯淡?記憶力也開始衰退?這個時候很多人都會感慨 時光易逝,容顏易老 並且開始習慣接受自己已慢慢變老,提前加入老人的行列。其實,這一切也許只是因為你長時間睡眠不足造成的。如果能夠早些了解這些常識,並引起足夠重視,你的青春也許還能保留十年。睡眠...

我們為什麼需要Map Reduce?

在討論我們是否真的需要map reduce這一分布式計算技術之前,我們先面對乙個問題,這可以為我們討論這個問題提供乙個直觀的背景。我們先從最直接和直觀的方式出發,來嘗試解決這個問題 先偽一下這個問題 select count distinct surname from big name file 我...