我同意 Dan Abramov 的观点:如果文本和类别在您的界面中高度耦合,只需FETCH_RESULTS
将文本和类别作为动作负载触发即可。
如果文本输入和类别选择小部件不共享关闭的父组件,则触发FETCH_RESULTS
包含文本和类别的a 很复杂(除非将大量props传递到树下......):然后您需要动作粒度。
当需要这种粒度时,我发现一种有用的模式是Saga / Process manager 模式。我在这里写了一点:https : //stackoverflow.com/a/33501899/82609
基本上,在 redux 上实现它意味着有一种非常特殊的减速器可以触发副作用。这个reducer不是纯粹的,但没有触发React渲染的目的,而是管理组件的协调。
这是我将如何实现您的用例的示例:
function triggerSearchWhenFilterChangesSaga(action,state,dispatch) {
var newState = searchFiltersReducer(action,state);
var filtersHaveChanged = (newState !== state);
if ( filtersHaveChanged ) {
triggerSearch(newFiltersState,dispatch)
}
return newState;
}
function searchFiltersReducer(action,state = {text: undefined,categories: []}) {
switch (action.type) {
case SEARCH_TEXT_CHANGED:
return Object.assign({}, state, {text: action.text});
break;
case CATEGORY_SELECTED:
return Object.assign({}, state, {categories: state.categories.concat(action.category) });
break;
case CATEGORY_UNSELECTED:
return Object.assign({}, state, {categories: _.without(state.categories,action.category) });
break;
}
return state;
}
请注意,如果您使用任何时间旅行(记录/重播/撤消/重做/任何)调试器,则在重播操作时应始终禁用 saga,因为您不希望在重播期间分派新操作。
编辑:在 Elm 语言(Redux 的灵感来源)中,我们可以通过“减少”效果,然后应用它们来执行此类效果。看到那个签名:(state, action) -> (state, Effect)
关于subjet的讨论也很长。
编辑:
我以前不知道但在 Redux 中动作创建者可以访问状态。因此,Saga 应该解决的大多数问题通常可以在动作创建器中解决(但它会与 UI 状态产生更多不必要的耦合):
function selectCategory(category) {
return (dispatch, getState) => {
dispatch({type: "CategorySelected",payload: category});
dispatch({type: "SearchTriggered",payload: getState().filters});
}
}