React-Redux: 操作必须是普通的对象。对异步操作使用自定义中间件

未处理的拒绝(错误) : 操作必须是普通对象。使用自定义中间件进行异步操作。

我想在每个帖子中添加评论。所以当提取文章运行时,我想为所有文章调用提取注释 API。

export function bindComments(postId) {
return API.fetchComments(postId).then(comments => {
return {
type: BIND_COMMENTS,
comments,
postId
}
})
}
274888 次浏览

如果没有中间件,就不能在操作中使用提取。操作必须是普通对象。您可以使用像 redux-thunk 或 redux-saga 这样的中间件来执行提取和分派另一个操作。

下面是一个使用 redux-thunk 中间件进行异步操作的示例。

export function checkUserLoggedIn (authCode) {
let url = `${loginUrl}validate?auth_code=${authCode}`;
return dispatch => {
return fetch(url,{
method: 'GET',
headers: {
"Content-Type": "application/json"
}
}
)
.then((resp) => {
let json = resp.json();
if (resp.status >= 200 && resp.status < 300) {
return json;
} else {
return json.then(Promise.reject.bind(Promise));
}
})
.then(
json => {
if (json.result && (json.result.status === 'error')) {
dispatch(errorOccurred(json.result));
dispatch(logOut());
}
else{
dispatch(verified(json.result));
}
}
)
.catch((error) => {
dispatch(warningOccurred(error, url));
})
}
}

必须在异步请求结束后进行分派。

这种方法可行:

export function bindComments(postId) {
return function(dispatch) {
return API.fetchComments(postId).then(comments => {
// dispatch
dispatch({
type: BIND_COMMENTS,
comments,
postId
});
});
};
}

利用箭头函数,提高了代码的可读性。 在 API.fetchComments中不需要返回任何东西,Api 调用是异步的,当请求完成时,then会得到响应,在那里你只需要 dispatch类型和数据。

下面的代码通过使用 Arrow 函数完成相同的工作。

export const bindComments = postId => {
return dispatch => {
API.fetchComments(postId).then(comments => {
dispatch({
type: BIND_COMMENTS,
comments,
postId
});
});
};
};

对于像我这样可能丢弃了简单细节的未来搜索者,在我的例子中,我只是忘记用括号调用 action 函数。

Actions.js:

export function addNewComponent() {
return {
type: ADD_NEW_COMPONENT,
};
}

我的组件 js:

import React, { useEffect } from 'react';
import { addNewComponent } from '../../redux/actions';


useEffect(() => {
dispatch(refreshAllComponents); // <= Here was what I've missed.
}, []);

我忘记使用 ()调度动作函数了,所以这样做解决了我的问题。

  useEffect(() => {
dispatch(refreshAllComponents());
}, []);

再一次,这可能与 OP 的问题没有任何关系,但我希望我能帮助与我有同样问题的人。

这个错误只是要求您插入一个中间件,这个中间件可以帮助处理异步操作。

你可以这样做:

Npm 我重复一下

        Inside index.js


import thunk from "redux-thunk"
import { createStore, applyMiddleware } from 'redux';
        

...createStore(rootReducers, applyMiddleware(thunk));

现在,异步操作将在函数内部工作。

我有同样的问题,因为我错过了加入作曲增强剂。一旦设置完成,您就可以查看操作创建器了。如果没有设置,也会出现这个错误。

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;


const store = createStore(
rootReducer,
composeEnhancers(applyMiddleware(thunk))
);

行动定义

const selectSlice = () => {
return {
type: 'SELECT_SLICE'
}
};

行动指挥中心

store.dispatch({
type:'SELECT_SLICE'
});

确保定义的动作对象结构与分派的动作相同。在我的例子中,在分派操作时,类型没有分配给属性 type

改变:

export const <youractionName> = async (dispatch) => {}

到,

export const <youractionName> = () => async (dispatch) => {}

这解决了我的问题。遗漏了一个’() = >’

如果您正在使用 redux 可观察值,请检查您的操作是否返回可观察值。我有这个问题,因为我使用的是地图,而不是合并地图

// error
export const myEpic = (action$: any) =>
action$.pipe(
ofType('...'),
map((x => x.payload),
map((x) => callAPi(x)),
)
    

// success
export const myEpic = (action$: any) =>
action$.pipe(
ofType('...'),
map((x => x.payload),
mergeMap((x) => callAPi(x)),
)

使用 redux-thunk,设置 redux & 创建这样的动作

export const actionName = (data) => dispatch => {
dispatch({
type:"ACTION_TYPE"
payload:"my payload"
})
}

只是来分享我的案子。 我有一个 setLoading动作,同时也有

const [loading, setLoading] = useState(false)

上面的我没有删除。所以它基本上不是从 redux 发送 setLoading,而是从 useState 发送 setLoading。删除/重命名这个函数可以解决这个问题。

如果这段代码正常工作,并且这是一个新的迭代,请检查以确保您的变量的顺序正确(这是我的错误)

也就是说。 得到这个错误的代码

export const fetchProjects = newPage => (getState, dispatch) => NOPE


export const fetchProjects = newPage => (dispatch, getState) => OK YEAH

在我的例子中,我只是想将一些值发送到服务器,而不将它们保存到 redux 存储中,所以我没有使用类型,也没有在最后分派任何内容。但我已经下令行动了。所以我所要做的,就是删除调度,因为这不是一个真正的行动。那只是个活动。

您可能也像我一样忘记了在中间件的数组中获取 DefaultMiddleware () ,不需要进一步的安装:

export const store = configureStore({
reducer: GlobalReducer,
middleware: (getDefaultMiddleware) => [
...getDefaultMiddleware(),
mainMiddleware,
],
});

对我来说,解决方案是添加 redux-thunk作为中间件,因此在我的商店配置文件中,我将 redux-thunk 作为中间件传递。

控制台内部:

enter image description here

import reducerData from './store-reducer';
import {applyMiddleware, compose, createStore} from 'redux';
import ReduxThunk from 'redux-thunk';


const middlewares = [ReduxThunk];


const store = createStore(
reducerData,
compose(applyMiddleware(...middlewares)),
);
export default store;

箭头函数语法

export const bindComments = (postId) => dispatch => {
return API.fetchComments(postId).then(comments => {
// dispatch
dispatch({
type: BIND_COMMENTS,
comments,
postId
})
})}

此错误主要发生在您正在分派一个操作并且您的操作没有返回一个对象的情况下。例如,这里有一个增量函数,当点击增量按钮时,我用它来增加数值。 这是我的调度函数 onClick={() => dispatch(increment)},因为省略了括号 ()内部调度功能现在在您的终端会出现同样的错误出现。调度函数需要一个对象而不是函数名的原因..。

当你在动作创建器中调用 异步的 api 时,你需要将动作创建器从同步动作创建器转换为异步动作,如果我们使用中间件,这种转换是可能的,所以让我来详细解释一下 没有中间件的复制

两种类型的操作创建器 同步动作创建器 VS 异步动作创建器。您需要将同步操作更改为异步操作,以消除此错误,这可以通过中间件完成

带中间件的复制版 在此输入图像描述

所以现在的解决办法是: 在异步请求完成后进行分派。

export function bindComments(postId) {
return function(dispatch) {
return API.fetchComments(postId).then(comments => {
// dispatch
dispatch({
type: BIND_COMMENTS,
comments,
postId
});
});
};
}

在没有中间件的情况下,redux 只支持同步数据流。如果您需要发出 ajax 请求并分派此请求的结果,那么您需要使用处理异步操作的中间件,如 redux-promiseredux-thunkredux-saga。或者你可以编写自己的中间件:

export default ({ dispatch }) =>
(next) =>
(action) => {
// check if there is payload in  action. if not send it to the next middleware
if (!action.payload || !action.payload.then) {
return next.action;
}
// if we are here means we have action.payload. now check if it is promise
// wait for the promise to be resolved
action.payload.then(function (response) {
// overwrite the action
const newAction = { ...action, payload: response };
dispatch(newAction);
});
};

我已经解决了我的问题:

导出 const = 异步(分派) = > {}

到,

导出 const = () = > 异步(分派) = > {}

每当您希望执行 async操作与 redux 岸您必须使用中间件,例如 redux-thunk

错误:

Action Js

export const login = () => async (dispatch, getState) => {}

酸痛

import reducerData from './store-reducer';
import {createStore} from 'redux';


const middlewares = [ReduxThunk];


const store = createStore(
reducerData,
);
export default store;

解决方案:

import reducerData from './store-reducer';
import {applyMiddleware, compose, createStore} from 'redux';
import ReduxThunk from 'redux-thunk';


const middlewares = [ReduxThunk];


const store = createStore(
reducerData,
compose(applyMiddleware(...middlewares)),
);
export default store;

这个让我措手不及的错误的原因ー

即使动作创建器是同步的,调度在测试中也会失败。原来我是在嘲笑动作制作者,这是它没有返回的时候出现的错误。