首页 > 解决方案 > 动作必须是普通对象。使用自定义中间件进行异步操作 Saga thunk 到目前为止我的商店中确实有

问题描述

问题是:

我试图在我的反应应用程序中使用 redux-saga,但我仍然有这个错误:动作必须是普通对象。使用自定义中间件进行异步操作。代码看起来是正确的,但不知道为什么会出现这个错误。我会很高兴所有的帮助。我与它战斗了大约两天,但仍然没有解决方案。我试图查找,但我仍然有这个错误。

action...
import { GET_DISTRICTS} from '../../constants';

const getAdres = async (url) => {
    let response = await fetch(url);
    let data = await response.json();
    let list = [];
    data.AdresList.Adresler.Adres.forEach((item) => {
        console.info(item);
        list.push({
            label: item.ADI,
            value: item.ID
        });
    });
    return list;
};

export const actions = {
    handleGetDistrictsData: async () => {
        let districts = await getAdres(`url is here`);

        return {
            type: GET_DISTRICTS,
            payload: districts
        };
    },

reducer...
import { GET_DISTRICTS } from '../../constants';

export const initialState = {
    districts: [],
    quarters: [],
    streets: [],
    doors: [],
    districtSelected: false,
    districtSelectedID: null,
    quarterSelected: false,
    quarterSelectedID: null,
    streetSelected: false,
    streetSelectedID: null,
    doorSelected: false,
    doorSelectedID: null
};

export default (state = initialState, action) => {
    switch (action.type) {
        case GET_DISTRICTS:
            return {
                ...state,
                districts: action.payload
            };
        default:
            return state;
    }
};


component...
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { actions as addressActions } from '../../../../redux/actions/address';

import Select from 'react-select';

const Districts = (props) => {
    let [ fetchedData, setFetchedData ] = useState(false);

    useEffect(() => {
        props.handleGetDistrictsData();
        setFetchedData(true);
    });

    return (
        <React.Fragment>
            <Select
                name='adresSelect'
                options={props.address.districts}
                onChange={props.handleDistrictChange}
                placeholder='Please Select'
            />
        </React.Fragment>
    );
};

const mapStateToProps = (state) => ({
    address: state.address
});

const mapDispatchToProps = function(dispatch) {
    return bindActionCreators({ ...addressActions }, dispatch);
};

export default connect(mapStateToProps, mapDispatchToProps)(Districts);

-------------

import React from 'react';

import Districts from './Districts';

const AddressSearchWidget = (props) => {
    return (
        <React.Fragment>
            <Districts />
        </React.Fragment>
    );
};

export default AddressSearchWidget


store...
import { applyMiddleware, combineReducers, compose, createStore } from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootSaga from './sagas/index';

import * as reducers from './';

export function initStore() {
    const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

    const rootReducer = combineReducers(reducers);
    const sagaMiddleware = createSagaMiddleware();

    const store = createStore(rootReducer, composeEnhancer(applyMiddleware(sagaMiddleware)));

    // Run sagas
    sagaMiddleware.run(rootSaga);

    return store;
}

标签: reactjsreduxredux-saga

解决方案


handleGetDistrictsData返回一个承诺(所有异步函数都返回承诺)。你不能在普通的 redux saga 中发送 promise,redux-saga 不会改变这一点。相反,调度一个正常的动作,并让该动作运行一个传奇。然后 saga 可以执行异步操作,并在完成后调度另一个操作。reducer 只监听第二个动作。

// Actions:
export const getDistrictsData = () => ({
  type: GET_DISTRICTS,
})

export const districtsDataSuccess = (districts) => ({
  type: DISTRICTS_DATA_SUCCESS,
  payload: districts
})

// Sagas:
export function* watchGetDistricts () {
  takeEvery(GET_DISTRICTS, getDistricts);
}

function* getDistricts() {
    let response = yield fetch(url);
    let data = yield response.json();
    let list = [];
    data.AdresList.Adresler.Adres.forEach((item) => {
        console.info(item);
        list.push({
            label: item.ADI,
            value: item.ID
        });
    });
    yield put(districtsDataSuccess(list));
}

// reducer:
export default (state = initialState, action) => {
    switch (action.type) {
        case DISTRICTS_DATA_SUCCESS:
            return {
                ...state,
                districts: action.payload
            };
        default:
            return state;
    }
};

推荐阅读