'Why do I have an error: 'Actions must be plain objects. Use custom middleware for async actions.' when using redux?
So I have a movie app, and I have a page for a single movie. I have a section on that page where I display all of the videos from an API related to a certain movie.
So my Videos component looks like this:
const Videos = ({videos} :{videos:IVideos | null}) => {
return (
<div>{videos?.results.map((video, i) =>
<div key={i}>{video.name}</div>
)}</div>
)
}
It's just a basic component which gets props from a higher component. But the main thing is redux slice, which looks like this:
Initial state:
const initialState: IMovieVideosState = {
movieVideos: null,
fetchStatus: null,
}
export interface IMovieVideosState {
movieVideos: IVideos | null;
fetchStatus: FetchStatus | null;
}
And finally slice:
const videosSlice = createSlice({
name:'videos',
initialState,
reducers:{},
extraReducers(builder) {
builder
.addCase(fetchVideos.pending, (state, action) => {
state.fetchStatus = FetchStatus.PENDING
})
.addCase(fetchVideos.fulfilled, (state, action) => {
state.fetchStatus = FetchStatus.SUCCESS
state.movieVideos = action.payload
})
.addCase(fetchVideos.rejected, (state, action) => {
state.fetchStatus = FetchStatus.FAILURE
//state.error = action.error.message
})
}
})
As you see, these are basic reducers, where if promise is successful I assign payload to an existing array.
And also thunk function:
export const fetchVideos = createAsyncThunk('videos/fetchVideos', async (id: number) => {
const response = await axios.get<IVideos>(`${API_BASE}movie/${id}/videos?api_key=${TMDB_API_KEY}`);
console.log(response.data);
return response.data;
})
But in the browser I have the next error:
Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.
And also another one:
A non-serializable value was detected in an action, in the path: `<root>`. Value:
Promise { <state>: "pending" }
Take a look at the logic that dispatched this action:
Promise { <state>: "pending" }
I have no idea why I could have these errors, because my reducer is the same as another one in my project, but this one doesn't work for some reason.
UseEffect for dispatching all reducers:
useEffect(() =>{
dispatch(fetchDetail(Number(id)));
dispatch(fetchCredits(Number(id)));
dispatch(fetchPhotos(Number(id)));
dispatch(fetchRecommended(Number(id)));
dispatch(fetchSimilar(Number(id)));
dispatch(fetchVideos(Number(id))); //dispatching fetchVideos()
}, [dispatch, id])
So in my case, all of the other functions work fine besides fetchVideos().
Another example of a thunk for movie details:
export const fetchDetail = createAsyncThunk('detail/fetchDetail', async (id: number) => {
const response = await axios.get<IMovie>(`${API_BASE}movie/${id}?api_key=${TMDB_API_KEY}`);
console.log(response.data);
return response.data;
})
My store file:
import thunk from "redux-thunk";
export const store = configureStore({
reducer: {
popular,
top_rated,
playing,
upcoming,
detail,
credits,
videos,
photos,
recommended,
similar
},
middleware: [thunk]
})
export type RootState = ReturnType<typeof store.getState>;
Solution 1:[1]
instead of using create Async Thunk method add think malware where you create store of videos then you can pass Async actions into it without nothing.
import { applyMiddleware, combineReducers, createStore } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from "redux-thunk";
// import your videos reducer here from file
export interface State {
videos: IVideos;
}
const rootReducer = combineReducers<State>({
videos: VideosReducer,
});
export const rootStore = createStore(
rootReducer,
composeWithDevTools(applyMiddleware(thunk))
);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | mahdi ashori |
