You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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实现:

  1. 创建维护排序字段的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;
  1. 修改action,只传递排序字段:
export const changeSort = (category) => ({
  type: CHANGE_SORT,
  category,
});
  1. 创建选择器计算排序结果:
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
    );
  }
);
  1. 在组件中使用选择器获取排序后的书籍:
import { selectSortedBooks } from '../selectors';

const mapStateToProps = (state) => ({
  books: selectSortedBooks(state),
});

这种方式符合Redux"单一数据源"和"衍生数据用选择器"的最佳实践,避免维护重复状态。


内容的提问来源于stack exchange,提问作者user3458749

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 22:57:22