如何在Redux Saga文件中使用自定义Hook?API函数存放方式疑问
问题解答
你确实不应该把API函数定义在自定义Hook里——因为Redux Saga的generator函数并不符合React Hook的调用规则(Hook只能在React组件或其他自定义Hook的顶层调用),所以没法直接在Saga里使用useApi这类Hook。
正确的实现方式是把API请求逻辑从Hook中抽离出来,做成独立的可复用模块,这样不管是Hook还是Saga都能调用它:
步骤1:抽离独立的API工具函数
新建apiUtils.js文件,将原本Hook里的API逻辑移至此处:
import axios from 'axios'; // 假设LOGIN是你的登录接口地址常量 const LOGIN = '/api/login'; // 创建axios实例(和你之前useAxios里的配置保持一致) const api = axios.create({ // 可配置baseURL、超时时间、拦截器等 }); export const userLogin = async (body, config = {}) => { const res = await api.post(LOGIN, body, config); return res.data; };
步骤2:修改自定义Hook复用工具函数
useApi现在可以直接调用抽离后的工具函数,无需在Hook内编写请求逻辑:
import { userLogin } from './apiUtils'; export const useApi = () => { // 如果useAxios有其他逻辑(比如全局拦截器),可保留该调用 // const api = useAxios(); return { userLogin, }; };
步骤3:在Redux Saga中调用API函数
Saga里处理异步要使用call effect调用异步函数,同时从dispatch动作中获取请求参数:
import { takeEvery, call, put } from 'redux-saga/effects'; import { userLogin } from './apiUtils'; export function* userLoginFunction(action) { try { // 从action.payload拿到登录所需的参数 const { body, config } = action.payload; // 用call执行异步登录请求 const loginResult = yield call(userLogin, body, config); // 登录成功后派发成功动作 yield put({ type: 'USER_LOGIN_SUCCESS', payload: loginResult }); } catch (e) { // 登录失败派发失败动作 yield put({ type: 'USER_LOGIN_FAILURE', error: e.message }); } } export default function* rootSaga() { // 修正原代码中的函数名错误,绑定对应的saga处理函数 yield takeEvery('USER_LOGIN', userLoginFunction); }
这种方式既遵守了React Hook的规则,又能在Saga中正常调用API请求,同时实现了代码复用。
内容的提问来源于stack exchange,提问作者Madhav mishra
相关产品推荐
相关产品推荐

