使用 redux-thunk 时动作必须是普通对象
Actions must be plain objects while using redux-thunk
我正在使用 react-redux 和 redux-thunk 实现异步操作创建器。但是,我收到以下错误消息:未捕获错误:操作必须是普通对象。使用自定义中间件进行异步操作。
我知道动作应该是普通对象,像 thunk 这样的中间件应该处理它们不是的情况。我已经阅读了几个教程并查看了 every SO question I could find on this,但我仍然无法弄清楚我哪里出错了。我是否错误地设置了 thunk,或者我是否以错误的方式使用了 action creators?这可能是 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
}
}
actions/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
}
相关片段containers/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);
在此先感谢您的帮助!
我怀疑这可能是因为你有一个 async (dispatch)
函数。这将导致它 return 变成 Promise
,甚至可能令人困惑 thunk
。
在正常情况下,函数本身会 return 另一个函数,thunk
会注入 dispatch
并再次调用,你会在函数内部调用 dispatch
:
arg => dispatch => dispatch({ type: arg });
加上async
,基本上就变成这样了:
arg => dispatch => Promise.resolve(dispatch({ type: arg }));
您可能不得不放弃其中的 async/await
并仅使用 axios
作为正常的 Promise
,或者添加一些额外的东西以确保它 return 什么都不是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())
得到的不是 普通 对象
的承诺
我做这些事情的方式是把重量留给我的行动;调用异步,当解决调度数据存储和在你的组件中监听和处理数据(价格列表)变化。
const mapDispatchToProps = dispatch => {
return {
fetchPrice
}
}
因此您可以显示 "loading please wait" 而价目表为空且承诺不是 resolved/rejected
以防有人遇到同样的问题。问题不在上面显示的代码中,也不在我如何调度操作中。我在另一个文件中有 redux-store 的重复定义,它用中间件覆盖了定义。
如果有人在使用 ImmutableJS + Typescript 时遇到麻烦,结果是您必须定义 "initialState" 中间件才能实际应用。
export const store = createStore(
combineReducers({APIReducer}),
{},
applyMiddleware(thunk.withExtraArgument(api))
);
在我的例子中,我有如下的动作声明,因此它抛出了这样的错误。
export const withdrawMoney = (amount) => {
return (dispath) => {
dispath({
type: "withdraw",
payload: amount
})
}};
我所做的只是将我的动作定义更改为对象类型
export const depositMoney = (amount) => ({
type: "deposit",
payload: amount
});
而且效果很好!
我正在使用 react-redux 和 redux-thunk 实现异步操作创建器。但是,我收到以下错误消息:未捕获错误:操作必须是普通对象。使用自定义中间件进行异步操作。
我知道动作应该是普通对象,像 thunk 这样的中间件应该处理它们不是的情况。我已经阅读了几个教程并查看了 every SO question I could find on this,但我仍然无法弄清楚我哪里出错了。我是否错误地设置了 thunk,或者我是否以错误的方式使用了 action creators?这可能是 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
}
}
actions/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
}
相关片段containers/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);
在此先感谢您的帮助!
我怀疑这可能是因为你有一个 async (dispatch)
函数。这将导致它 return 变成 Promise
,甚至可能令人困惑 thunk
。
在正常情况下,函数本身会 return 另一个函数,thunk
会注入 dispatch
并再次调用,你会在函数内部调用 dispatch
:
arg => dispatch => dispatch({ type: arg });
加上async
,基本上就变成这样了:
arg => dispatch => Promise.resolve(dispatch({ type: arg }));
您可能不得不放弃其中的 async/await
并仅使用 axios
作为正常的 Promise
,或者添加一些额外的东西以确保它 return 什么都不是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())
得到的不是 普通 对象
我做这些事情的方式是把重量留给我的行动;调用异步,当解决调度数据存储和在你的组件中监听和处理数据(价格列表)变化。
const mapDispatchToProps = dispatch => {
return {
fetchPrice
}
}
因此您可以显示 "loading please wait" 而价目表为空且承诺不是 resolved/rejected
以防有人遇到同样的问题。问题不在上面显示的代码中,也不在我如何调度操作中。我在另一个文件中有 redux-store 的重复定义,它用中间件覆盖了定义。
如果有人在使用 ImmutableJS + Typescript 时遇到麻烦,结果是您必须定义 "initialState" 中间件才能实际应用。
export const store = createStore(
combineReducers({APIReducer}),
{},
applyMiddleware(thunk.withExtraArgument(api))
);
在我的例子中,我有如下的动作声明,因此它抛出了这样的错误。
export const withdrawMoney = (amount) => {
return (dispath) => {
dispath({
type: "withdraw",
payload: amount
})
}};
我所做的只是将我的动作定义更改为对象类型
export const depositMoney = (amount) => ({
type: "deposit",
payload: amount
});
而且效果很好!