如何通过钩子使用Redux-Saga来调用API

时间:2020-02-10 20:34:56

标签: javascript reactjs redux react-redux react-hooks

我正在尝试使用Redux-saga中间件来避免异步函数错误,我正在使用React Hooks,我连接了Redux-Saga并执行了功能*产生函数,但是我不知道为什么它没有读取我的操作拦截它,它给了我同样的错误:

错误:动作必须是普通对象。使用自定义中间件执行异步操作。

代码: 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);

Index.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'));


任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:0)

几周前,我刚刚完成了一个项目,该项目使用redux-saga处理websockets,而我遇到了一个类似的问题。 SageMidddleware确实适用于传奇功能,但要将功能用于我使用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))
);

希望这对您有所帮助。

答案 1 :(得分:0)

因此,store设置没有任何问题,applyMiddleware在正确的位置。我看到的问题是可以调用dispatch的生成器函数,但是这里有更多缺点:Dispatching actions to the store

相反,您可以调用put来调度操作。通过创造效果中间件将解决这一问题,并将适当的操作发送给商店。因此,documentation提出了更好的解决方案:

相反,我们需要相同的声明性解决方案。创建一个简单的JavaScript对象,以指示中间件我们需要调度某些操作,然后让中间件执行真正的调度。这样,我们可以以相同的方式测试生成器的调度:检查产生的效果并确保其包含正确的指令。

为此,该库提供了另一个功能部件,该功能部件可以创建调度效果。

尝试在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);
}

希望对您有帮助!