0

So I am following a tutorial where redux-thunk is implemented, and have done everything as it is in the video, but I still get this error:

Error: Actions must be plain objects. Instead, the actual type was: 'Promise'. You may need to add middleware to your store setup to handle dispatching other values, such as 'redux-thunk' to handle dispatching functions.

Here is how the code looks like:

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
    
import reducers from './reducers';
    
import App from './App';
    
const store = createStore(reducers, applyMiddleware(thunk));
    
ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>, 
    document.getElementById('root')
);

Here is the action

actions/posts.js

export const createPost = (post) => async (dispatch) => {
    try {
        const { data } = await api.createPost(post);

        dispatch({ type: 'CREATE', payload: data });
    } catch (error) {
        console.log(error);
    }
}

The reducer:

const reducer = (posts = [], action) => {
    switch (action.type) {
        case 'FETCH_ALL':
            return action.payload;
        case 'CREATE':
            return [ ...posts, action.payload];
        default:
            return posts;
    }
}

export default reducer;

And the file where the error occurs:

import React, { useState } from 'react';
import { TextField, Button, Typography, Paper } from '@material-ui/core';
import FileBase from 'react-file-base64';
import { useDispatch } from 'react-redux';

import useStyles from './styles';
import { createPost } from '../../api';

export default function Form() {
    const [postData, setPostData] = useState({
        creator: '', 
        title: '', 
        message: '', 
        tags: '', 
        selectedFile: ''
    });
    const classes = useStyles();
    const dispatch = useDispatch();

    const handleSubmit = (e) => {
        e.preventDefault();

        dispatch(createPost(postData));
    }

    const clear = () => {

    }

    return (
        <Paper className={classes.paper}>
            <form autoComplete="off" noValidate className={`${classes.root} ${classes.form}`} onSubmit={handleSubmit}>
            <Typography variant="h6">Creating a Memory</Typography>
            <TextField 
                name="creator"
                variant="outlined"
                label="Creator"
                fullWidth
                value={postData.creator}
                onChange={(e) => setPostData({ ...postData, creator: e.target.value })}
            />
            <TextField 
                name="title"
                variant="outlined"
                label="Title"
                fullWidth
                value={postData.title}
                onChange={(e) => setPostData({ ...postData, title: e.target.value })}
            />
            <TextField 
                name="message"
                variant="outlined"
                label="Message"
                fullWidth
                value={postData.message}
                onChange={(e) => setPostData({ ...postData, message: e.target.value })}
            />
            <TextField 
                name="tags"
                variant="outlined"
                label="Tags"
                fullWidth
                value={postData.tags}
                onChange={(e) => setPostData({ ...postData, tags: e.target.value })}
            />
            <div className={classes.fileInput}>
                <FileBase 
                    type="file"
                    multiple={false}
                    onDone={({base64}) => setPostData({ ...postData, selectedFile: base64 })}
                />
            </div>
            <Button className={classes.buttonSubmit} variant="contained" color="primary" size="large" type="submit" fullWidth>Submit</Button>
            <Button variant="contained" color="secondary" size="small" onClick={clear} fullWidth>Clear</Button>
            </form>
        </Paper>
    )
}

I really can't see the problem here, I'd appriciate if someone could enlighten me! Thanks!!:)

reClicked
  • 15
  • 1
  • 6
  • What is your `./reducers` file? did you use combineReducer? – Tasos Jun 15 '21 at 12:51
  • Yes, this is how it looks like: `import { combineReducers } from "redux"; import posts from './posts'; export default combineReducers({ posts });` – reClicked Jun 15 '21 at 12:58
  • Can you share the code `api.createPost(post)` – Vivek Bani Jun 15 '21 at 13:06
  • It all seems right to me. Does your app use hot-reload? Did you try killing the npm start and start it again? – Tasos Jun 15 '21 at 13:07
  • I think your problem might be a duplicate of this post: https://stackoverflow.com/a/54066862/5605822 – Tasos Jun 15 '21 at 13:09
  • @TasosBu Yes, tried it right now but it is the same – reClicked Jun 15 '21 at 13:12
  • @RajdeepDebnath `export const createPost = (newPost) => axios.post(url, newPost);` this how it looks like – reClicked Jun 15 '21 at 13:12
  • Can you try removing the dispatch from your `handleSubmit` and just do: `createPost(postData)`? – Tasos Jun 15 '21 at 13:16
  • everything looks fine, not sure if `try catch` block in the post.js can be an issue as not all code path are returning expected format. Can you remove and try. May be a silly suggestion. – Vivek Bani Jun 15 '21 at 13:16
  • 1
    @TasosBu I have read that question but my code looks like in the answer that was accepted so I don't know what the problem is – reClicked Jun 15 '21 at 13:17
  • @RajdeepDebnath tried deleting the try catch block but the same error occurs – reClicked Jun 15 '21 at 13:29
  • So what will happen if the try block throws error? console log will happen at catch block and then nothing is being returned. – Vivek Bani Jun 15 '21 at 13:30
  • @reClicked you can `console.log` after this line `const { data } = await api.createPost(post);` to check if you are getting expected data back – Vivek Bani Jun 15 '21 at 13:33
  • Thanks but I found the bug I made. I imported the wrong createPost function, hehe. But thanks for the many tipps! – reClicked Jun 15 '21 at 14:10

2 Answers2

0

There are two mistakes in your createStore method.

  1. The first parameter of createStore is root reducer which is fine. But second parameter should be the initial state and you're passing applyMiddleware instead of initial state
  2. You've to give an array of middlewares to applyMiddleware method
// do like this
const store = createStore(reducers, {}, applyMiddleware([thunk]));

// not like this
const store = createStore(reducers, applyMiddleware(thunk));
Haseeb Anwar
  • 2,438
  • 19
  • 22
0

Thanks for everyone who answered the question! Turns out I imported the wrong createPost function, silly me! Fortunately everything seems to work now!

reClicked
  • 15
  • 1
  • 6