[英]Actions must be plain objects while using redux-thunk
我正在使用react-redux和redux-thunk實現異步動作創建者。 但是,我收到以下錯誤消息:未捕獲的錯誤:操作必須是普通對象。 使用自定義中間件進行異步操作。
我知道動作應該是普通的對象,而像thunk這樣的中間件應該負責處理不是它們的情況。 我已經閱讀了幾本教程,並研究了在此上可以找到的每個 SO問題,但是我仍然無法弄清楚哪里出了問題。 我是否錯誤地設置了thunk,或者我以錯誤的方式使用動作創建者? 這可能是webpack或其他錯誤嗎?
在下面,我包括了我認為相關的代碼片段。 請讓我知道是否需要其他信息。
index.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'));
reducers / order.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
}
}
動作/price-fetch.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
}
相關的容器/order.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);
在此先感謝您的幫助!
如果有人遇到相同的問題。 問題不在於上面顯示的代碼,也不在於我如何調度動作。 我在另一個文件中有一個關於redux-store的重復定義,這用中間件覆蓋了該定義。
如果有人在使用ImmutableJS + Typescript時不知所措,那么事實證明您必須為實際應用的中間件定義“ initialState”。
export const store = createStore(
combineReducers({APIReducer}),
{},
applyMiddleware(thunk.withExtraArgument(api))
);
我懷疑這可能是因為您具有async (dispatch)
功能。 那將導致它返回一個Promise
,這甚至可能使thunk
感到困惑。
在正常情況下,函數本身將返回另一個函數, thunk
將注入dispatch
並再次調用,您將在函數內部調用dispatch
:
arg => dispatch => dispatch({ type: arg });
當您添加async
,它基本上與此相同:
arg => dispatch => Promise.resolve(dispatch({ type: arg }));
您可能不得不在其中拋棄async/await
,而只是將axios
用作常規Promise
,或添加一些額外內容以確保它不返回任何內容而不是Promise
。
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
}
}
因此,當價格表為空且承諾未解決/被拒絕時,您可以顯示“正在加載,請稍候”
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.