Redux中sortReducer始终获取空状态数组问题求助
问题描述
我在学习Redux时给一个项目添加了排序功能,但自定义的sortReducer始终获取到空数组[]作为状态。
我知道可以在booksReducer中实现排序功能,但我希望单独创建一个新的reducer。我无法理解为什么booksReducer能正常获取状态,而sortReducer却不行,恳请帮助。
相关代码
组件 - SortFilter.js
import React from 'react'; import PropTypes from 'prop-types'; const SortFilter = ({ handleSortChange }) => { const categories = ['title', 'category', 'id']; return ( <select className="select-filter" onChange={handleSortChange}> {categories.map((book) => ( <option key={book} value={book}> {book} </option> ))} </select> ); }; SortFilter.propTypes = { handleSortChange: PropTypes.func.isRequired, }; export default SortFilter;
BookList.js集成片段
<div className="float-rit"> <span className="filter"> Sort by <SortFilter handleSortChange={(e) => { sortChange(e); }} /> </span> </div> const sortChange = ({ target: { value } }) => { debugger; changeSort(value, books); }; const mapDispatchToProps = (dispatch) => ({ removeBook: (book) => dispatch(removeBook(book)), changeFilter: (category) => dispatch(changeFilter(category)), changeSort: (category, books) => dispatch(changeSort(category, books)), });
Action - index.js
export const changeSort = (category, books) => ({ type: CHANGE_SORT, category, books, });
Reducer - sort.js
/* eslint-disable */ import { CHANGE_SORT } from '../actions/index'; /* eslint-disable */ const sortReducer = (state = [], action) => { switch (action.type) { case CHANGE_SORT: debugger; const cat = action.category; return state.sort((a, b) => a[cat] > b[cat] ? 1 : b[cat] > a[cat] ? -1 : 0 ); default: return state; } }; export default sortReducer;
参考用booksReducer
import { CREATE_BOOK, REMOVE_BOOK } from '../actions/index'; const booksReducer = (state = [], action) => { switch (action.type) { case CREATE_BOOK: return [...state, action.book]; case REMOVE_BOOK: return state.filter((book) => book.id !== action.id); default: return state; } }; export default booksReducer;
注:忽略changeSort函数中多余的books参数,当时在尝试其他方法。
问题分析与解决
核心原因
sortReducer和booksReducer是Redux store中独立的状态切片维护者,两者的状态完全隔离。booksReducer负责维护书籍数据状态,而sortReducer的初始状态是空数组,且你从未给它同步过书籍数据,所以它的状态一直是空的。Redux中每个reducer只处理自己对应的那部分状态,不会自动共享其他reducer的数据。
两种可行解决方案
方案1:让sortReducer基于传入的书籍数据排序
既然你已经在触发CHANGE_SORT时传入了books参数,直接在sortReducer中使用该数据进行排序即可,注意不要修改原数组(sort方法会修改原数组,需先复制):
const sortReducer = (state = [], action) => { switch (action.type) { case CHANGE_SORT: const cat = action.category; // 复制原数组后再排序,避免修改原始书籍数据 return [...action.books].sort((a, b) => a[cat] > b[cat] ? 1 : b[cat] > a[cat] ? -1 : 0 ); default: return state; } };
方案2:用选择器生成衍生排序结果(更推荐)
排序后的书籍属于衍生数据,不需要单独维护状态,可通过原始书籍数据和排序字段实时计算。用reselect库的createSelector实现:
- 创建维护排序字段的reducer:
import { CHANGE_SORT } from '../actions/index'; const sortCategoryReducer = (state = 'title', action) => { switch (action.type) { case CHANGE_SORT: return action.category; default: return state; } }; export default sortCategoryReducer;
- 修改action,只传递排序字段:
export const changeSort = (category) => ({ type: CHANGE_SORT, category, });
- 创建选择器计算排序结果:
import { createSelector } from 'reselect'; const selectBooks = state => state.books; const selectSortCategory = state => state.sortCategory; export const selectSortedBooks = createSelector( [selectBooks, selectSortCategory], (books, sortCategory) => { return [...books].sort((a, b) => a[sortCategory] > b[sortCategory] ? 1 : b[sortCategory] > a[sortCategory] ? -1 : 0 ); } );
- 在组件中使用选择器获取排序后的书籍:
import { selectSortedBooks } from '../selectors'; const mapStateToProps = (state) => ({ books: selectSortedBooks(state), });
这种方式符合Redux"单一数据源"和"衍生数据用选择器"的最佳实践,避免维护重复状态。
内容的提问来源于stack exchange,提问作者user3458749
相关产品推荐
相关产品推荐

