Reputation: 47
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)
Upvotes: 0
Views: 390
Reputation: 237
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.
Upvotes: 1