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

Redux-Saga中takeEvery与put触发无限循环,原因是什么?

Redux Saga无限循环:控制台重复打印'getInitList'

问题场景

运行Web应用时,控制台持续输出getInitList,应用陷入无限循环,相关代码如下:

import {takeEvery, put} from 'redux-saga/effects';
import {INIT_LIST_DATA} from './actionTypes'
import "./actionTypes";
import axios from "axios";

function *getList() {
    console.log('getInitList')
    const res = yield axios.get('/todolist.json');
    const data = res.data
    yield put({
        type: INIT_LIST_DATA,
        value: data
    })
}

// generator 函数
function *mySaga() {
    console.log('mySaga')
    yield takeEvery(INIT_LIST_DATA, getList)
}

export default mySaga;

原因分析

这是典型的循环触发闭环问题:

  • 你用takeEvery(INIT_LIST_DATA, getList)监听了INIT_LIST_DATA类型的action,只要这个action被派发,就会执行getList函数。
  • 但getList在获取数据后,又通过put派发了一个INIT_LIST_DATA类型的action。
  • 这个新的action立刻被takeEvery捕获,再次调用getList,如此反复就形成了无限循环,导致控制台不断打印getInitList。

修复方案

打破闭环的关键是把触发请求的action和更新数据的action分开:

  1. 先在actionTypes.js里新增一个用于触发请求的action类型:
// actionTypes.js
export const GET_INIT_LIST = 'get_init_list'; // 新增:触发请求的类型
export const INIT_LIST_DATA = 'init_list_data'; // 原:更新数据的类型
  1. 修改saga代码,让takeEvery监听新增的GET_INIT_LIST,而getList完成请求后依然派发INIT_LIST_DATA来更新状态:
import {takeEvery, put} from 'redux-saga/effects';
import {GET_INIT_LIST, INIT_LIST_DATA} from './actionTypes'
import axios from "axios";

function *getList() {
    console.log('getInitList')
    const res = yield axios.get('/todolist.json');
    const data = res.data
    yield put({
        type: INIT_LIST_DATA,
        value: data
    })
}

function *mySaga() {
    console.log('mySaga')
    yield takeEvery(GET_INIT_LIST, getList) // 改为监听GET_INIT_LIST
}

export default mySaga;
  1. 之后在需要初始化列表数据的地方(比如组件挂载时),派发GET_INIT_LIST类型的action即可触发请求,不会再出现循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 03:10:23