記住派生資料
在你的 redux 商店中,你可以儲存原始資料。有時原始資料就是你所需要的,但有時你需要從原始資料中獲取新資料,通常是通過組合部分原始資料。
用於匯出資料的常見用例是基於標準過濾資料列表,其中列表和標準都可以被改變。
以下示例實現 mapStateToProps 並過濾字串列表以保留與搜尋字串匹配的字串,從而生成可由 React 元件呈現的新 prop filteredStringList
。
// Example without memoized selectors
const mapStateToProps(state) => {
const {stringList, searchString} = state;
return {
filteredStringList: stringList
.filter(string => string.indexOf(searchString) > -1)
};
}
為了簡化 Reducer,你應該只儲存商店中的資料列表和過濾條件,這意味著你需要在讀取時間內獲取資料(就像我們在上面的示例中所做的那樣)。
獲取有關讀取時間的資料會帶來兩個問題:
- 如果多次匯出相同的資料,則可能會影響效能。
- 如果不同元件中需要相同的資料,你可能會發現要複製程式碼以獲取資料。
解決方案是使用僅定義一次的 memoized 選擇器。React 社群建議使用 npm 庫重新選擇來建立 memoized 選擇器。在下面的示例中,我們獲得與第一個示例中相同的結果,僅使用 memoized 選擇器。
// Create memoized selector for filteredStringList
import {createSelector} from 'reselect';
const getStringList = state => state.stringList;
const getSearchString = state => state.searchString;
const getFilteredStringList = createSelector(
getStringList,
getSearchString,
(stringList, searchString) => stringList
.filter(string => string.indexOf(searchString) > -1)
);
// Use the memoized selector in mapStateToProps
const mapStateToProps(state) => {
return {
filteredStringList: getStringList(state)
};
}
請注意,兩個第一選擇器 getStringList
和 getSearchString
沒有被記憶,因為它們非常簡單,不會提供任何效能提升。它們仍然需要建立,因為我們需要將它們作為依賴項傳遞給 createSelector
,以便它知道何時重用 memoized 結果以及何時計算新結果。
memoized 選擇器將使用傳遞給 createSelector
的最後一個引數傳遞的函式來計算派生資料(在我們的示例中,返回過濾後的字串列表的函式)。每次呼叫 memoized 選擇器時,如果從上次呼叫依賴項後沒有更改(在我們的示例中 stringList
和 searchString
),memoized 選擇器將返回先前的結果,從而節省重新計算它的時間。
你可以將選擇器(memoized 或 not memoized)視為商店狀態的 getter,就像 action-creators 是 setter 一樣。
你可以在 Redux 文件的配方部分找到有關計算派生資料的更多示例。