未处理的拒绝(错误):操作必须是普通对象。使用自定义中间件进行异步操作。
详细信息:我想在每个帖子中添加评论。因此,当运行获取帖子时,我想为所有帖子调用fetch comment API。
这是我的代码:
export function bindComments(postId) {
return API.fetchComments(postId).then(comments => {
return {
type: BIND_COMMENTS,
comments,
postId
}
})
}
由于
答案 0 :(得分:24)
您必须在异步请求结束后发送。
这样可行:
export function bindComments(postId) {
return function (dispatch){
return API.fetchComments(postId).then(comments => {
// dispatch
dispatch( {
type: BIND_COMMENTS,
comments,
postId
})
})
}
}
答案 1 :(得分:11)
对于那些可能会像我一样遗漏简单细节的未来求职者,就我而言,我只是忘了用括号来调用我的动作函数。
actions.js:
export function addNewComponent() {
return {
type: ADD_NEW_COMPONENT,
};
}
myComponent.js:
import React, { useEffect } from 'react';
import { addNewComponent } from '../../redux/actions';
useEffect(() => {
dispatch(refreshAllComponents); // <= Here was what I've missed.
}, []);
我忘记了用()
分派动作函数。因此,这样做解决了我的问题。
useEffect(() => {
dispatch(refreshAllComponents());
}, []);
同样,这可能与OP的问题无关,但我希望我能帮助遇到与我的问题相同的人。
答案 2 :(得分:6)
错误只是要求您在中间插入一个中间件,以帮助处理异步操作。
您可以通过:
npm i redux-thunk
Inside index.js
import thunk from "redux-thunk"
...createStore(rootReducers, applyMiddleware(thunk));
现在,异步操作将在您的函数中起作用。
答案 3 :(得分:4)
变化:
export const <youractionName> = async (dispatch) => {}
到,
export const <youractionName> = () => async (dispatch) => {}
这解决了我的问题。错过了 '() =>'
答案 4 :(得分:2)
您不能在没有中间件的情况下使用fetch。动作必须是普通对象。你可以使用像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));
})
}
}
答案 5 :(得分:2)
充分利用Arrow函数,可以提高代码的可读性。
无需返回API.fetchComments
中的任何内容,请求完成后then
的Api调用将是异步的,您只需要dispatch
的类型和数据即可。
下面的代码通过使用Arrow函数完成相同的工作。
export const bindComments = postId => {
return dispatch => {
API.fetchComments(postId).then(comments => {
dispatch({
type: BIND_COMMENTS,
comments,
postId
});
});
};
};
答案 6 :(得分:2)
我遇到了与错过添加composeEnhancers相同的问题。设置完成后,您可以查看动作创建者。如果未同时设置,则会出现此错误。
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
rootReducer,
composeEnhancers(applyMiddleware(thunk))
);
答案 7 :(得分:0)
动作定义
const selectSlice = () => {
return {
type: 'SELECT_SLICE'
}
};
动作调度
store.dispatch({
type:'SELECT_SLICE'
});
确保定义的动作的对象结构与分派的动作相同。就我而言,在调度操作时,没有将类型分配给属性type
。
答案 8 :(得分:0)
如果您正在使用 redux-observable,请检查您的操作是否返回了 observable。我遇到了这个问题,因为我使用的是地图而不是合并地图
// 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)),
)
答案 9 :(得分:0)
使用 redux-thunk,使用 redux 进行设置并创建这样的操作
export const actionName = (data) => dispatch => {
dispatch({
type:"ACTION_TYPE"
payload:"my payload"
})
}
答案 10 :(得分:0)
只是在这里分享我的案例。
我有一个 setLoading
操作,同时还有
const [loading, setLoading] = useState(false)
以上我没有删除。所以它基本上不是从 redux 调度 setLoading
而是从 useState 调度。删除/重命名它可以解决问题。