記住派生資料

在你的 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,你應該只儲存商店中的資料列表和過濾條件,這意味著你需要在讀取時間內獲取資料(就像我們在上面的示例中所做的那樣)。

獲取有關讀取時間的資料會帶來兩個問題:

  1. 如果多次匯出相同的資料,則可能會影響效能。
  2. 如果不同元件中需要相同的資料,你可能會發現要複製程式碼以獲取資料。

解決方案是使用僅定義一次的 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)
    };
}

請注意,兩個第一選擇器 getStringListgetSearchString 沒有被記憶,因為它們非常簡單,不會提供任何效能提升。它們仍然需要建立,因為我們需要將它們作為依賴項傳遞給 createSelector,以便它知道何時重用 memoized 結果以及何時計算新結果。

memoized 選擇器將使用傳遞給 createSelector 的最後一個引數傳遞的函式來計算派生資料(在我們的示例中,返回過濾後的字串列表的函式)。每次呼叫 memoized 選擇器時,如果從上次呼叫依賴項後沒有更改(在我們的示例中 stringListsearchString),memoized 選擇器將返回先前的結果,從而節省重新計算它的時間。

你可以將選擇器(memoized 或 not memoized)視為商店狀態的 getter,就像 action-creators 是 setter 一樣。

你可以在 Redux 文件的配方部分找到有關計算派生資料的更多示例。