0

I am trying to fetch data from an api on component load in my React project and have redux-thunk applied but I am getting the error uncaught Error: Actions must be plain objects. Use custom middleware for async actions. when trying to make an async await api call

Is there a way to check if redux-thunk is being applied correctly?

How can I use async/await without it throwing an error?

component.js

import React from 'react'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import { TransitionGroup, CSSTransition } from "react-transition-group";
import { connect } from "react-redux";
import styled from 'styled-components'
import ScrollToTop from '../atoms/ScrollToTop'
import Header from '../Header'
import Footer from '../Footer'
import Home from '../Home'
import * as actionCreators from './actions'
import media from '../atoms/Media'
import BreadCrumbs from '../Breadcrumbs'
import Category from '../Category'
import ProductsList from '../ProductsList'
import Product from '../Product'
import Alert from '../atoms/Alert'


class Main extends React.Component {

  componentDidMount() {
    this.props.fetchCategories()
    this.props.fetchSubCategories()
    this.props.fetchProducts()
  }

 handleHideAlert() {
    setTimeout(() => {
      this.props.hideAlert()
    }, 1000)
  }

  render() {
    const {alert, categories, filteredColors, filteredSizes, language, products,  showAlert, subCategories} = this.props
    const e = language === 'english'
    const p = language === 'polish'
    return(
      <Router>
        <Wrap>
        {alert && <div><Alert />{this.handleHideAlert()}</div>}
        <Header e={e} p={p} categories={categories} subCategories={subCategories} language={language} />
          {/* <BreadCrumbs /> */}
          <Route style={{ flex: 1 }} render={({ location }) =>
            <TransitionGroup>
              <CSSTransition
                key={location.key}
                timeout={500}
                classNames="page"
                mountOnEnter={true}
                unmountOnExit={true}
              >
                <Switch location={location}>
                  <MainWrap>
                  <Route exact path="/" render={props => <Home e={e} p={p} categories={categories} subCategories={subCategories} products={products} language={language} {...props} />} />
                  <Route exact path="/:catId" render={props => <Category e={e} p={p} categories={categories} subCategories={subCategories} language={language} {...props} />} />
                  <Route exact path="/:catId/:subCatId" render={props => <ProductsList  e={e} p={p} filteredColors={filteredColors} filteredSizes={filteredSizes} categories={categories} subCategories={subCategories} products={products} language={language} {...props} />} />
                  <Route exact path="/:catId/:subCatId/:productId" render={props => <Product categories={categories} subCategories={subCategories} products={products} showAlert={showAlert} language={language} {...props} />} />
                  </MainWrap>
                </Switch>
              </CSSTransition>
            </TransitionGroup>
          } />
  { e ? ADD_TO_CART_E : ADD_TO_CART_P}
          <Footer />
        </Wrap>
      </Router>
    )
  }
}

const mapStateToProps = state => ({
  alert: state.ui.alert,
  language: state.language,
  categories: state.data.categories.categories,
  subCategories: state.data.subCategories.subCategories,
  products: state.data.products.products,
  filteredColors: state.filters.colors,
  filteredSizes: state.filters.sizes
});

export default connect(mapStateToProps, actionCreators)(Main);

actions.js

export const fetchProducts = async () =>
  await (await fetch('https://api.github.com')).json()

configureStorejs

import { createStore, applyMiddleware } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import thunk from 'redux-thunk';

import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
import rootReducer from './Reducers/rootReducer'; // the value from combineReducers

const persistConfig = {
 key: 'root',
 storage: storage,
 stateReconciler: autoMergeLevel2, // see "Merge Process" section for details.
 whitelist: 'language'
};

const pReducer = persistReducer(persistConfig, rootReducer);

export const store = createStore(pReducer,
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
  applyMiddleware(thunk)
)
export const persistor = persistStore(store);

index.js

import React from 'react'
import { render } from 'react-dom'
import App from './App'
import { Provider } from 'react-redux'
import { PersistGate } from 'redux-persist/integration/react'

import { persistor, store } from './configureStore';

const renderApp =
  render(
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <App />
    </PersistGate>
  </Provider>, root)

module.hot.accept(renderApp)

1 Answer 1

1

Since you are using thunk you could return a function

export const fetchProducts = () => async(dispatch) => {
  try {
   const data = await (await fetch('https://api.github.com')).json()
   dispatch({ type: 'FETCH_SUCCESS', payload: {data}})
  } catch (error) {
   dispatch({ type: 'FETCH_FAIL', payload: {error}})
  }
}
Sign up to request clarification or add additional context in comments.

4 Comments

i also get the same error running this so maybe something isn't configured correctly
Hmm, how do you bind fetchProducts action creator? Plz add container code.
@tomharrison It should be ` () => async(dispatch) => ` notice arrow not equal sign. Also remove the rest of your calls fetchCategories etc the error might be comming from those calls.
thanks you so much, now working export const fetchProducts = () => async(dispatch) => { dispatch({ type: 'FETCH_PRODUCTS_REQUEST'}) try { const data = await (await fetch('http://localhost:3000/products')).json() dispatch({ type: 'FETCH_PRODUCTS_SUCCESS', payload: {data}}) } catch (error) { dispatch({ type: 'FETCH_FAIL', payload: {error}}) } }

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.