Redux-Saga引发网站无限重渲染问题求助
Redux-Saga 导致无限重渲染的解决方法
问题根源
你的代码形成了无限循环:
- Saga 通过
takeEvery(GET_EMPLOYEE_LIST, workEmployeeList)监听GET_EMPLOYEE_LIST类型的 action - 在请求完成后,
workEmployeeList又通过yield put({type: GET_EMPLOYEE_LIST, ...})再次触发同一个 action - 这会导致 Saga 反复执行请求逻辑,不断触发状态更新,最终引发组件无限重渲染
解决步骤
核心是拆分 action 类型,将触发请求和更新状态的操作分离:
- 新增区分用途的 action 类型
在EmployeeActions.js里定义两个不同的 action 类型:
export const GET_EMPLOYEE_LIST_REQUEST = 'GET_EMPLOYEE_LIST_REQUEST'; // 触发请求 export const GET_EMPLOYEE_LIST_SUCCESS = 'GET_EMPLOYEE_LIST_SUCCESS'; // 请求成功后更新状态 // 可选:新增失败类型用于错误处理 // export const GET_EMPLOYEE_LIST_FAILURE = 'GET_EMPLOYEE_LIST_FAILURE';
- 修改 Saga 逻辑
让 Saga 监听请求触发的 action,成功后派发状态更新的 action:
import { call, put, takeEvery } from 'redux-saga/effects' import axios from 'axios' import { GET_EMPLOYEE_LIST_REQUEST, GET_EMPLOYEE_LIST_SUCCESS } from './actions/EmployeeActions' import ConstantList from '../../app/appConfig' const API_PATH = ConstantList.API_ENPOINT + "/employees" export function* getEmployeeList() { // 改为监听请求触发类型的 action yield takeEvery(GET_EMPLOYEE_LIST_REQUEST, workEmployeeList) } export function* workEmployeeList() { console.trace("hello"); try { const url = API_PATH + '/search' const response = yield call(axios.post, url, {}) // 派发状态更新类型的 action,不再复用请求触发类型 yield put({ type: GET_EMPLOYEE_LIST_SUCCESS, payload: response.data.data }) } catch (error) { console.log("Request failed!") // 可选:派发失败类型 action 处理错误状态 // yield put({type: GET_EMPLOYEE_LIST_FAILURE, error: error}) } }
- 修改 Reducer 处理状态更新
在EmployeeReducer.js中处理成功类型的 action 来更新状态:
import { GET_EMPLOYEE_LIST_SUCCESS } from '../actions/EmployeeActions' const initialState = { employeeList: [] }; export default function EmployeeReducer(state = initialState, action) { switch(action.type) { case GET_EMPLOYEE_LIST_SUCCESS: return { ...state, employeeList: action.payload }; // 可选:处理失败状态 // case GET_EMPLOYEE_LIST_FAILURE: // return {...state, error: action.error}; default: return state; } }
- 组件中触发请求
在需要获取员工列表的组件里,派发请求触发类型的 action:
import { useDispatch } from 'react-redux' import { useEffect } from 'react' import { GET_EMPLOYEE_LIST_REQUEST } from './path/to/EmployeeActions' function EmployeeList() { const dispatch = useDispatch(); useEffect(() => { // 触发请求 dispatch({type: GET_EMPLOYEE_LIST_REQUEST}); }, [dispatch]); // ...其他渲染逻辑 }
内容的提问来源于stack exchange,提问作者trungvs
相关产品推荐
相关产品推荐

