Redux和Reselect:使用派生数据计算状态的一部分

时间:2016-01-20 15:17:17

标签: reactjs memoization redux

使用redux状态树的一部分来更新状态的另一部分的最佳方法是什么。特别是,我在下面有一个简化的flashcard应用程序示例。我们有一个由一个reducer维护的单词列表,然后状态树的另一部分由一个quiz reducer维护,它包含当前选择的单词。我希望测验缩减器能够访问单词列表,甚至可能是单词的计算(memoized)过滤子集。这里最好的方法是什么?

// The reducer that manages a list of words
function wordsReducer(state = [], action) {
  switch(action.type) {
  ...
  default:
    return state;
  }
};

// text to filter words with
function filterReducer(state = '', action) {
  switch(action.type) {
  case SET_FILTER:
    return action.payload;
  default:
    return state:
  }
};

// we have derived data, which is a list of filtered words
const filteredWordsSelector = createSelector(
  (state) => state.words,
  (state) => state.filter,
  (words, filter) => words.filter(word => word.indexOf(filter) >= 0)
);

//return one word randomly.
function chooseWord(words) {
  return words[Math.floor(Math.random()*words.length)];
}

以下是我的困惑。如何在另一个内部访问计算数据 国家的一个分支。此外,我想增加复杂性,如排序 将这些词放入桶中,这就是为什么我认为重新选择(或其他一些备忘录)将是一个很好的方法。

以下答案表明我不应该在我的减速器中使用重新选择,但是我的另一种解决方法是什么? https://stackoverflow.com/a/32922461/2620595

const initialQuizState = {chosenWord: null};

function quizReducer(state = initialQuizState, action, filteredWords) {
  switch(action.type) {
  case CHOOSE_WORD:
    // I want to choose a word at random from filteredWords
    return {...state, chosenWord: chooseWord(filteredWords)};
  default:
    return state;
}

function rootReducer(state, action) {
  return {
    words: wordsReducer(state.words, action),
    filter: filterReducer(state.filter, action),
    quiz: quizReducer(state.quiz, action, filteredWordsSelector(state))
  }
};

组织我的redux减压器有什么好方法?我是否应该将州的另一部分传递到上面的quizReducer,在这种情况下使用reselect真的很糟糕吗?

1 个答案:

答案 0 :(得分:2)

我不认为在你的减速器中使用selectWord违反了丹·阿布拉莫夫的建议,因为它实际上并不是纯粹的选择器。 Math.random()的使用意味着您从以外的状态中获取结果。

更纯粹的方法可能是简单地将Math.random()的结果存储在状态中,并导出其他所有内容。虽然我对提倡这一点犹豫不决,因为它有可能使您的代码更难以理解的缺点。