0

I've read multiple sources about this error but I cannot figure out what I'm doing incorrectly here. I'm using custom middleware already and I believe that I'm returning the action correctly. Any advice?

app.js

import React from "react";
import ReactDOM from "react-dom";
import { renderToString } from "react-dom/server";
import { Provider } from "react-redux";
import { createStore, applyMiddleware, compose } from "redux";
import thunk from 'redux-thunk';

import rootReducer from '../reducers';
import DataProvider from "./DataProvider";
import QuestionContainer from "./QuestionContainer";
import * as actions from "../actions";

const App = () => <QuestionContainer />;
const store = createStore(
    rootReducer,
    applyMiddleware(thunk)),
);

store
    .dispatch(actions.fetchQuestions())
    .then(() => response.send(renderToString(<Provider store={ store }><App /></Provider>)))

Then in actions.js

export function fetchQuestions() {
    return (dispatch) => {
        return fetch('/api/questions')
            .then(response => response.json())
            .then(data => dispatch(loadRequestData(data)),
        )
    }
}

The error showing in browser console:

redux.js:208 Uncaught (in promise) Error: Actions must be plain objects. Use custom middleware for async actions.
    at dispatch (redux.js:208)
    at eval (index.js:12)
    at dispatch (redux.js:571)
    at eval (actions.js:35)
0

1 Answer 1

1

I think there's something's wrong in this part of code:

store
.dispatch(actions.fetchQuestions())
.then(() => response.send(renderToString(<Provider store={ store }><App /></Provider>)))

When you're creating async calls you want to do this only in action, not reducer/store.

So you need to delete this line .then(() => response.send(renderToString(<Provider store={ store }><App /> and instead of that just make:

const app = (
        <Provider store={store}>
            <App />
        </Provider>
)

ReactDOM.render(app, document.getElementById('root'));

Additionally make some actions which will be kind of helper for updating store in your reducer. Something like this:

export const fetchBegin = () => ({
    type: 'FETCH_BEGIN'
})

export const fetchSuccess = (payload) => ({
    type: 'FETCH_SUCCESS'
    payload
})

export const fetchQuestions = () => {
    return (dispatch) => {
        dispatch(fetchBegin())
        return fetch('/api/questions')
            .then(response => response.json())
            .then(data => dispatch(fetchSuccess(data))
        )
    }
}

Then in the reducers make:

const initialState = {
    call: [],
    loading: false
}

const reducer = (state = initialState, action){
    switch(action.type){
        case 'FETCH_BEGIN:
            return{
            ...state,
            loading: true,
        case 'FETCH_SUCCESS':
            return{
            ...state,
            call: action.payload,
            loading: false,
        }
        default:
            return state
    }
}

This should work imho.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.