先看下下面的乙個元件
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 我...