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

在Saga中派发动作后,组件无法获取过滤数据问题排查

Redux获取filteredCourses数据失败排查及修复方案

一、Component.js中的核心问题

1. 未定义变量直接引用

原代码直接使用courses.isLoading,但courses变量从未定义,会抛出ReferenceError。需先通过useSelector获取filteredCourses状态:

// 修复前
if (categories.isLoading || courses.isLoading) { ... }

// 修复后
const filteredCourses = useSelector(state => state.filteredCourses);
if (categories.isLoading || filteredCourses.isLoading) { ... }

2. 无限循环派发Action

直接在组件函数体中调用dispatch(apiRequestFilteredCourses(query)),会导致组件每次渲染都派发Action,触发状态更新后再次渲染,形成无限循环。必须用useEffect包裹并添加依赖控制执行时机:

// 修复前
const query = { category_id: 1 };
dispatch(apiRequestFilteredCourses(query));

// 修复后
import React, { useEffect } from 'react'; // 补充useEffect导入

const Courses = () => {
  const categories = useSelector(state => state.categories);
  const filteredCourses = useSelector(state => state.filteredCourses);
  const dispatch = useDispatch();

  useEffect(() => {
    // 仅当categories加载完成后再请求过滤课程
    if (!categories.isLoading && categories.isLoaded) {
      const query = { category_id: 1 };
      dispatch(apiRequestFilteredCourses(query));
    }
  }, [categories, dispatch]); // 添加依赖项
}

二、Reducer与useSelector匹配问题

filteredCoursesReducer的状态结构是包含filteredCourses数组、isLoading、isLoaded的对象,通过useSelector获取数据时需明确取到数组:

// 错误:直接取整个状态对象
const filteredCourses = useSelector(state => state.filteredCourses);

// 正确:取对象中的filteredCourses数组
const { filteredCourses: courseList, isLoading, isLoaded } = useSelector(state => state.filteredCourses);
// 或分开取
const courseList = useSelector(state => state.filteredCourses.filteredCourses);
const isCourseLoading = useSelector(state => state.filteredCourses.isLoading);

三、Saga中的潜在问题

filteredCoursesSagas最后一行yield put(apiRequestFilteredCourses());会在Saga启动时自动派发空参数请求,导致不必要的API调用,建议移除:

// 修复前
export default function* filteredCoursesSagas() {
  yield takeEvery(API_REQUEST_FILTERED_COURSES, filterCourses);
  yield put(apiRequestFilteredCourses()); // 移除该行
}

四、Api.js的错误处理隐患

当API请求失败时,catch块返回Error对象,Saga中解构data和status会报错,需先判断返回值是否为Error:

// Saga中修复
function* filterCourses(action) {
  const query = new URLSearchParams(action.payload).toString();
  try {
    const response = yield Api.get(`courses?${query}`, false);
    // 先判断是否为Error
    if (response instanceof Error) {
      console.log('API请求失败:', response);
      return;
    }
    const { data, status } = response;
    if (status === 200) {
      yield put(apiReceiveFilteredCourses(data.data));
    } else {
      console.log(`请求失败,状态码: ${status}`);
    }
  } catch (e) {
    console.log('FROM COURSES', e);
  }
}

五、完整修复后的Component.js示例

import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { apiRequestFilteredCourses } from '../../../actions';

const Courses = () => {
  const categories = useSelector(state => state.categories);
  const { filteredCourses: courseList, isLoading: coursesLoading } = useSelector(state => state.filteredCourses);
  const dispatch = useDispatch();

  // 加载状态判断
  if (categories.isLoading || coursesLoading) {
    return (<h1>Loading</h1>);
  }

  useEffect(() => {
    // 确保categories已加载完成再请求
    if (categories.isLoaded) {
      const query = { category_id: 1 };
      dispatch(apiRequestFilteredCourses(query));
    }
  }, [categories, dispatch]);

  // 渲染课程列表
  return (
    <div>
      {courseList.map(course => (
        <div key={course.id}>{course.name}</div>
      ))}
    </div>
  );
};

export default Courses;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:55:22