【问题标题】:redux-saga: Actions must be plain objectsredux-saga:动作必须是普通对象
【发布时间】:2018-10-12 20:43:55
【问题描述】:

我的传奇有问题,我不知道出了什么问题。我收到一个错误,比如 Actions must be plain objects。在使用 react redux 时使用自定义中间件进行异步操作。这是我的代码。

容器/index.js

class AppContainer extends Component {

    componentDidMount() {
        const { actions: { onFetchPhoto } } = this.props;
        onFetchPhoto();
    }

    render() {
        return (
            <App />
        );
    }
}


const mapDispatchToProps = (dispatch) => ({
    actions: {
        onFetchPhoto: () => dispatch(fetchPhoto())
    }
})


export default connect(null, mapDispatchToProps)(AppContainer);

actions/index.js

export const FETCH_PHOTO_REQUEST = "FETCH_PHOTO_REQUEST";
export const FETCH_PHOTO_SUCCESS = "FETCH_PHOTO_SUCCESS";
export const FETCH_PHOTO_FAILURE = "FETCH_PHOTO_FAILURE";

export function fetchPhoto(payload) {
    return {
        type: FETCH_PHOTO_REQUEST
    }
}
export function fetchPhotoSuccess(payload) {
    return {
        type: FETCH_PHOTO_SUCCESS,
        payload
    }
}
export function fetchPhotoFailure(error) {
    return {
        type: FETCH_PHOTO_SUCCESS,
        payload: {
            error
        }
    }
}

sagas/index.js

function* fetchRandomPhoto() {
    //yield put(fetchPhoto());

    const {
        response,
        error
    } = yield call(fetchRandomPhotoApi)

    if (response) {
        yield put(fetchPhotoSuccess(response))
    } else {
        yield put(fetchPhotoFailure(error))
    }
}

function* watchLoadRandomPhoto() {
    try {
        while (true) {
            yield takeLatest(FETCH_PHOTO_REQUEST, fetchRandomPhoto);
        }
    }
    catch(error) {
        console.error("error in saga", error)
    }
}

export default function* rootSaga() {
    yield fork(watchLoadRandomPhoto)
}

services/index.js

import axios from 'axios';
import {
    URL,
    PUBLIC_KEY
} from 'src/constants/config';

import {
    schema,
    normalize
} from 'normalizr'

export function fetchRandomPhotoApi() {
    return axios({
            url: `${URL}/photos/random`,
            timeout: 10000,
            method: 'get',
            headers: {
                'Autorization': `Client-ID ${PUBLIC_KEY}`
            },
            responseType: 'json'
        })
        .then((response) => {
            const { data } = response.data;
            console.log("d");
            if (data) {
                return ({
                    response: {
                        id: data.id,
                        url: data.urls.full,
                        title: data.location.title
                    }
                })
            }
        })
       .catch(error => error)
}

store/configureStore.js

import rootReducer from 'src/reducers/root';
import rootSaga from 'src/sagas';


export default function configureStore() {
    const logger = createLogger();
    const sagaMiddleware = createSagaMiddleware();
    const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

    const store = createStore(
        rootReducer,
        compose(
            applyMiddleware(
                sagaMiddleware,
                logger,
                composeEnhancers
            ),
        )
    );

    sagaMiddleware.run(rootSaga);

    return store;
}

我浪费了 2 天时间来解决这个问题,但没有结果。 Chrome 向我显示了这个错误:

【问题讨论】:

    标签: reactjs react-redux redux-saga


    【解决方案1】:

    问题的根源在于 fetchRandomPhotoApi 函数。在不知道这是什么样子的情况下,我不能肯定地说,但如果它是一个返回承诺的函数,你应该像这样调用

    const { response, error } = yield call(fetchRandomPhotoApi)
    

    请注意调用中缺少括号。

    更新

    从您的编辑中,我现在可以看到您的 api 调用中没有解决承诺。您希望该函数返回一个对象,而不是传递给您的操作的实际承诺。大概是这样的:

    axios({...etc}).then(response => response).catch(error => error)
    

    【讨论】:

    • 是的,你是对的,它返回承诺。但是还是不行,我加了configureStore和api。我认为当 react 尝试在 componentDidMount 中启动一个函数并说它不是普通对象时会发生这个问题,但我使用 dispatch
    • 从您的编辑看来,您可能需要处理您的 axios 承诺。我不使用 axios,所以我不太确定,但您不需要链接 .then() 来将承诺解析为对象吗?
    • 是的,我需要 .then() 并修复了它。但是这个方法 fetchRandomPhotoApi 没有执行(我在控制台中检查了)。我认为是因为调用 Api 方法之前的错误
    【解决方案2】:

    嗯,我发现了我的问题,但我不明白为什么。我添加了这段代码。

    store/index.js

    export default function configureStore() {
        const logger = createLogger();
        const sagaMiddleware = createSagaMiddleware();
        const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
    
        const store = createStore(
            rootReducer,
            compose(
                applyMiddleware(
                    sagaMiddleware,
                    logger
                ),
                window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : (fn) => fn
            )
        );
    
        store.runSaga = sagaMiddleware.run;
    
        return store;
    }
    

    index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    
    import { Provider } from 'react-redux';
    
    import configureStore from 'src/store/configureStore';
    
    import Routes from 'src/routes/root';
    import rootSaga from 'src/sagas';
    
    const store = configureStore();
    
    store.runSaga(rootSaga);
    
        ReactDOM.render(
            <Provider store={store}>
                    <Routes store={store} />
            </Provider>,
            document.getElementById('root')
        );
    

    这一行也使我的应用程序正常工作。

    window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : (fn) => fn
    

    【讨论】:

      猜你喜欢
      • 2020-06-13
      • 2018-03-23
      • 2017-05-09
      • 1970-01-01
      • 2019-04-26
      • 1970-01-01
      • 2019-11-11
      • 2018-07-08
      相关资源
      最近更新 更多