代码之家  ›  专栏  ›  技术社区  ›  maaland

使用redux thunk时,操作必须是普通对象

  •  0
  • maaland  · 技术社区  · 8 年前

    我正在使用react-redux和redux-thunk实现异步动作生成器。但是,我收到以下错误消息:未捕获错误:操作必须是普通对象。对异步操作使用自定义中间件。

    我知道动作应该是普通对象,而像thunk这样的中间件应该在它们不是的情况下处理这些情况。我已经阅读了一些教程,并查看了 每一个 所以我可以在这个问题上找到答案,但我仍然不知道我错在哪里。我是不是设置了thunk错误,还是我使用动作创建者的方式不好?这可能是webpack或其他方面的错误吗?

    下面是我认为相关的代码片段。如果需要其他信息,请告诉我。

    指数js公司

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { Route } from 'react-router';
    import { Provider } from 'react-redux';
    import { createStore, applyMiddleware } from 'redux';
    import thunk from 'redux-thunk';
    
    import rootReducer   from './reducers';
    import Layout    from './components/Layout.js';
    import OrderPage from './containers/order-page';
    
    
    const store = createStore(
        rootReducer,
        applyMiddleware(thunk)
        );
    
    ReactDOM.render(
        <Provider store={store}>
            <App>
                <Route  exact path="/" component={Layout}/>
            </App>
        </Provider>,
        document.querySelector('.app'));
    

    减速器/订单。js公司

    import { FETCH_ERR, FETCH_SUCCESS, START_FETCH } from '../actions/types';
    
    const initialState = {
      fetching: false
    };
    
    export default (state=initialState, action)=>{
      switch (action.type) {
        case START_FETCH: 
          return {
            fetching: true
          }
        case FETCH_ERR:
          return {
            err: action.payload.err,
            fetching: false
          }
        case FETCH_SUCCESS:
          return {
            price: action.payload,
            fetching: false
          }
        default:
            return state
      }
    
    }
    

    操作/取价。js公司

    import axios from 'axios'
    
    const FETCH_ERR = 'FETCH_ERR'
    const FETCH_SUCCESS = 'FETCH_SUCCESS'
    const START_FETCH  = 'START_FETCH'
    
    
    const fetchSucc = (data)=>{
      return{
        type:FETCH_SUCCESS,
        payload:data
      }
    }
    
    const fetchFail = (message)=>{
      return{
        type:FETCH_ERR,
        payload:message
      }
    }
    
    const startFetch = () =>{
      return{
        type: START_FETCH,
        payload:null
      }
    }
    
    const fetchPrices = () =>{
      return async (dispatch) =>{
        try {
          dispatch(startFetch())
          let data = await axios.get('mybackendurl')
          dispatch(fetchSucc(data))
        } catch (error) {
          dispatch(fetchFail({err:'failed to get shit'}))
        }
      }
    }
    
    export {
        FETCH_ERR,
        FETCH_SUCCESS,
        fetchPrices,
        START_FETCH
    }
    

    相关集装箱件/订单。js公司

    import React, { Component }     from 'react';
    
    import { connect }                      from 'react-redux';
    
    import { fetchPrices }          from '../actions/price-fetch';
    
    class Order extends Component {
    
    
    ...
    
    
    
      render() {
        this.props.fetchPrices();
        return ...
    
      }
    
    
    const mapDispatchToProps = dispatch => {
      return {
        fetchPrice: () => {
          dispatch(fetchPrices())
        }
      }
    }
    
    function mapStateToProps(state){
        return {
            prices: state.order
        }
    }
    
    export default connect(mapStateToProps, mapDispatchToProps)(Order);
    

    提前感谢您的帮助!

    5 回复  |  直到 8 年前
        1
  •  2
  •   maaland    8 年前

    以防有人遇到同样的问题。问题不在上面显示的代码中,也不在我如何调度操作中。我在另一个文件中有一个重复的redux存储定义,它使用中间件重写了定义。

        2
  •  2
  •   Bhabadyuti    4 年前

    在我的例子中,我有下面这样的操作声明,因此它抛出了这样的错误。

    export const withdrawMoney = (amount) => {
    return (dispath) => {
        dispath({
            type: "withdraw",
            payload: amount
        })
    }};
    

    我所做的只是将动作定义更改为对象类型

    export const depositMoney = (amount) => ({
       type: "deposit",
       payload: amount
    });
    

    而且它工作得很好!

        3
  •  1
  •   Andrew GS    7 年前

    如果有人在使用ImmutableJS+Typescript时抓住了救命稻草,那么您必须定义“initialState”,以便中间件实际应用。

    export const store = createStore(
      combineReducers({APIReducer}),
      {},
      applyMiddleware(thunk.withExtraArgument(api))
    );
    
        4
  •  0
  •   samanime    8 年前

    我怀疑可能是因为你有 async (dispatch) 作用这会导致它返回 Promise ,这可能会让人困惑 thunk .

    在正常情况下,函数本身将返回另一个函数 砰的一声 将注入 dispatch 再打一次,你就会 派遣 函数内部:

    arg => dispatch => dispatch({ type: arg });
    

    添加时 async ,基本上与此相同:

    arg => dispatch => Promise.resolve(dispatch({ type: arg }));
    

    你可能不得不放弃 async/await 在里面使用 axios 正常情况下 许诺 ,或添加额外的内容以确保返回nothing而不是 许诺 .

        5
  •  0
  •   Femi Oni    8 年前
    const fetchPrices = () =>{`
     return async (dispatch) =>{`
     try {
       dispatch(startFetch())
       let data = await axios.get('mybackendurl')
       dispatch(fetchSucc(data))
     } catch (error) {
       dispatch(fetchFail({err:'failed to get shit'}))
      }
     }
    }
    

    当你这样做的时候

    const mapDispatchToProps = dispatch => {
           return {
        fetchPrice: () => {
          dispatch(fetchPrices())
        }
      }
    }
    

    dispatch(fetchPrices()) 得到承诺不是 平原 对象

    我做这些事情的方式是把沉重的负担留给我的行动;当解析了要存储的调度数据并在组件中侦听和处理数据(价目表)更改时,调用async。

    const mapDispatchToProps = dispatch => {
      return {
        fetchPrice
      }
    }
    

    因此,当价目表为空且承诺未解决/拒绝时,您可以显示“正在加载,请稍候”