如何使用 Redux-Saga 和 Hooks 调用 API
Posted
技术标签:
【中文标题】如何使用 Redux-Saga 和 Hooks 调用 API【英文标题】:How to use Redux-Saga with Hooks to call API 【发布时间】:2020-05-26 05:17:39 【问题描述】:我正在尝试使用 Redux-saga 中间件来避免异步函数错误,我正在使用 React Hooks,我连接了 Redux-Saga 并执行了 function* yield 函数,但我不知道为什么它没有读取我的操作拦截它,它给了我同样的错误:
错误:动作必须是普通对象。使用自定义中间件进行异步操作。
代码: Store.js
import createSagaMiddleware from 'redux-saga';
import rootReducer from './RootReducer'
import watchFetchImages from '../middleware/saga';
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
rootReducer,
applyMiddleware(sagaMiddleware)
);
sagaMiddleware.run(watchFetchImages);
export default store;
Actions.js
import axios from 'axios';
import GetCategories from './actionTypes'
import GetImages from './actionTypes'
export function fetchCategories()
var url = 'http://localhost:4000/all_categories';
return (dispatch) =>
return axios.get(url).then((res) =>
dispatch(
type: GetCategories,
payload: res.data
)
)
export function fetchImages()
var url ='/all_categories';
return(dispatch) =>
return axios.get(url).then((res)=>
dispatch(
type:GetImages,
payload:res.data
)
)
Reducers.js
import GetCategories , GetImages from "../redux/actions/actionTypes"
const initialState =
categories: [],
images:[]
;
const rootReducer = (state = initialState, action) =>
switch (action.type)
case GetCategories:
return ...state, categories: state.categories.concat(action.payload)
case GetImages:
return...state,images:action.payload
default:
return state;
;
export default rootReducer;
Saga.js
import takeEvery,delay from 'redux-saga/effects'
function* getImagesAsync()
yield delay(4000);
console.log('api called')
export function* watchFetchImages()
yield takeEvery("GetImages",getImagesAsync);
Home.js 我在哪里调用 redux 操作
const HomePage = props =>
useEffect(()=>props.getImages())
console.log(props)
const mapStateToProps = (images) => (
images
)
const mapDispatchToProps= dispatch =>(
getImages: () => dispatch(fetchImages())
)
export default connect(mapStateToProps,mapDispatchToProps)(HomePage);
索引.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import Provider from "react-redux";
import store from '../src/redux/store';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<Provider store=store><App /></Provider>, document.getElementById('root'));
任何人都可以帮助我吗??
【问题讨论】:
在将store
传递给它时如何使用<Provider>
?你能分享index.js
吗?谢谢!
@norbitrial 我确实添加了 index.js ,如果您除了我遇到的问题之外还有任何其他 cmets,请通知我,我对 redux 和 hooks 还是新手
在Saga.js
中,您是在导出watchFetchImages
函数还是只是从示例中丢失?
@norbitrial 例子中是导出的,是不是也需要导出其他函数getImagesAsync?
错误说的是真的。我使用 Redux Thrunk 在操作中创建函数。 npmjs.com/package/redux-thunk
【参考方案1】:
几周前我刚刚参与了一个使用 redux-saga 处理 websockets 的项目,我遇到了一个几乎类似的问题。 SageMiddleware 确实适用于 saga 函数,但要将函数用于我使用 redux-thrunk 的操作。小例子:
import
createStore,
applyMiddleware,
compose
from "redux";
import createSagaMiddleware from 'redux-saga';
import thunk from "redux-thunk";
import reducer from '../reducers';
const storeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducer,
(localStorage['storage']) ? JSON.parse(localStorage['storage']) : ,
storeEnhancers(applyMiddleware(sagaMiddleware, thunk))
);
我希望这对您有所帮助。
【讨论】:
谢谢,但我只需要使用 Sagas【参考方案2】:所以我没有看到store
设置有任何问题,applyMiddleware
位于正确的位置。我看到的问题是您可以调用dispatch
的生成器函数,但是这里有几个缺点可以进一步阅读:Dispatching actions to the store。
相反,您可以调用 put
来调度操作。通过创建效果,中间件会处理这些,并将适当的操作发送到商店。因此,作为documentation 的更好解决方案,它指出:
相反,我们需要相同的声明式解决方案。创建一个普通的 javascript 对象来指示中间件我们需要调度一些动作,并让中间件执行真正的调度。这样我们就可以用同样的方式测试 Generator 的 dispatch:检查产生的 Effect 并确保它包含正确的指令。
为此,该库提供了另一个函数 put 来创建调度效果。
在Saga.js
中尝试以下更改:
function* getImagesAsync()
// here you can call your API
const payloadImages = // result from API response
yield put(type: 'GetImages', payloadImages);
export default function* watchFetchImages()
yield takeEvery('GetImages', getImagesAsync);
希望对你有帮助!
【讨论】:
我试图这样做还是一样的错误,我试图在reducer中添加另一个动作案例来处理saga中间件仍然相同的错误,我认为错误来自takeEvery函数无法识别动作'GetImages'所以它没有拦截它,仍然不知道如何修复它我的新代码:Saga.jsfunction* getImagesAsync() const payloadImages = axios.get('/all_images');; yield put(type: 'GetImagesSaga', payload:payloadImages); export function* watchFetchImages() yield takeEvery("GetImages",getImagesAsync);
以上是关于如何使用 Redux-Saga 和 Hooks 调用 API的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 redux-saga 在 API 响应中检查过期的 JWT 令牌?
无法弄清楚如何使用 redux-saga-test-plan 测试 redux-saga 功能