异步等待在反应中获取api数据

时间:2018-12-07 13:14:48

标签: reactjs

我正在尝试在React项目中的组件加载时从api中获取数据并应用redux-thunk,但是在尝试进行异步等待api调用时出现错误uncaught Error: Actions must be plain objects. Use custom middleware for async actions.

有没有办法检查redux-thunk是否正确应用?

如何在不引发错误的情况下使用async / await?

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 个答案:

答案 0 :(得分:1)

由于您正在使用thunk,因此可以返回一个函数

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}})
  }
}