如何使用Redux+Saga请求API并在home.js中获取返回数据?
问题根因
你读不到接口返回数据是三个核心问题:
- Reducer处理
SESSION_FETCH_SUCCESS动作时,没有把API返回结果写入Redux全局状态 - home.js组件没有订阅Redux store中对应分片的状态,无法感知状态更新
- 前置校验项:Saga请求成功后派发的success动作,必须携带接口返回的完整数据,否则reducer拿不到要存的值
第一步:修正Saga逻辑,确保成功动作携带接口返回数据
先确认你的Saga监听和请求处理逻辑符合以下写法,接口返回结果必须通过success action的payload传递给reducer:
// 对应saga文件 import { call, put, takeLatest } from 'redux-saga/effects'; import { fetchSessionData } from './你的api请求文件路径'; import Action from './你的action常量定义路径'; function* handleFetchSession(action) { try { // 调用接口拿到返回结果,参数和你action里传的结构对齐 const res = yield call(fetchSessionData, action.payload.data); // 关键:成功动作必须携带接口返回数据 yield put({ type: Action.SESSION_FETCH_SUCCESS, payload: res }) } catch (err) { yield put({ type: Action.SESSION_FETCH_ERROR, error: err }) } } // 监听发起请求的action export function* watchSessionSaga() { yield takeLatest(Action.SESSION_DATA, handleFetchSession); }
第二步:修改Reducer,把接口数据存入全局状态
你当前的SESSION_FETCH_SUCCESS分支仅更新了加载状态,没有存储返回数据,补充对应字段即可:
// 先给初始状态加专门存接口数据的字段 const sessionState = { isLoading: false, sagaerror: null, sessionInfo: null // 存储session接口返回数据 } export const SessionData = (state = sessionState, action) => { console.log('inside session reducer', JSON.stringify(action)); switch (action.type) { case Action.SESSION_FETCH_SUCCESS: return { ...state, isLoading: false, sessionInfo: action.payload, // 存入接口返回数据 sagaerror: null // 成功后清空历史错误 }; case Action.SESSION_FETCH_ERROR: return { ...state, sagaerror: action.error, isLoading: false, }; case Action.SESSION_DATA: return { ...state, isLoading: true, sagaerror: null }; default: return state; } };
第三步:在home.js中订阅Redux状态,拿到更新后的数据
根据你用的组件类型选对应写法即可:
函数组件(React-Redux Hooks写法)
用useSelector直接订阅store中的对应状态:
import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { fetchSession } from './你的action文件路径'; const Home = () => { const dispatch = useDispatch(); // 注意:state.SessionData的key要和你combineReducers里注册该reducer的key完全一致 const { isLoading, sessionInfo, sagaerror } = useSelector(state => state.SessionData); const fetchSessionData = () => { dispatch( fetchSession({ token: token // 你本地存储的token变量 }) ) } // 组件挂载时触发请求 useEffect(() => { fetchSessionData(); }, []) // 直接使用sessionInfo即可,请求完成前值为null,更新后会自动触发组件重渲染 console.log('home页拿到的session数据:', sessionInfo); return ( <div> {isLoading ? '数据加载中...' : JSON.stringify(sessionInfo)} </div> ) } export default Home;
类组件(connect写法)
通过connect方法做状态和派发方法的映射:
import React from 'react'; import { connect } from 'react-redux'; import { fetchSession } from './你的action文件路径'; class Home extends React.Component { componentDidMount() { this.props.fetchSessionData(); } render() { const { isLoading, sessionInfo, sagaerror } = this.props; console.log('home页拿到的session数据:', sessionInfo); return ( <div> {isLoading ? '数据加载中...' : JSON.stringify(sessionInfo)} </div> ) } } // 把store中的状态映射到组件props const mapStateToProps = (state) => { return { isLoading: state.SessionData.isLoading, sessionInfo: state.SessionData.sessionInfo, sagaerror: state.SessionData.sagaerror } } // 把action派发方法映射到组件props const mapDispatchToProps = (dispatch) => { return { fetchSessionData: () => dispatch(fetchSession({token: token})) } } export default connect(mapStateToProps, mapDispatchToProps)(Home);
避坑提醒
- 取状态时的key必须和
combineReducers注册reducer的key完全一致,比如注册时写的是combineReducers({ session: SessionData }),取的时候就要写state.session - 不要在
dispatch请求动作后立刻同步读取数据,Redux状态更新是异步的,必须通过订阅方式(useSelector/connect)拿到更新后的值 - 可以安装Redux DevTools工具直接查看全局状态变化,快速定位数据有没有成功存入store
内容的提问来源于stack exchange,提问作者Shesh Narayan Deshmukh
相关产品推荐
相关产品推荐

