Javascript 动作必须是普通对象。为异步操作使用自定义中间件-此处丢失
痛苦的一周,我不知道为什么会这样:Javascript 动作必须是普通对象。为异步操作使用自定义中间件-此处丢失,javascript,reactjs,react-redux,Javascript,Reactjs,React Redux,痛苦的一周,我不知道为什么会这样:操作必须是普通对象。将自定义中间件用于异步操作 指的是: const login = await container.props().login(email, password) login() 请注意,在我将所有内容更改为异步之前,这项操作最初是有效的,因为我必须将superagent加入到混合中: const login = container.props().login(email, password) login()
操作必须是普通对象。将自定义中间件用于异步操作
指的是:
const login = await container.props().login(email, password)
login()
请注意,在我将所有内容更改为异步之前,这项操作最初是有效的,因为我必须将superagent加入到混合中:
const login = container.props().login(email, password)
login()
我尝试过的其他组合运气不佳:
const login = await container.dive().find(Login).props().login(email, password)
login()
const login = await container.dive().props().login(email, password)
login()
const login = container.props().login(email, password)
login()
现在代码是:
测试
import thunk from 'redux-thunk'
import configureStore from 'redux-mock-store'
import { React, shallow, expect, nock } from '../testImports'
import LoginContainer, { Login } from '../../../client/containers/LoginContainer'
import initStore from '../../../client/store'
describe('Feature: User Authentication', () => {
describe('Scenario: User can Login', () => {
let email, password, store, responseBody
beforeEach(() => {
email = 'someuser@gmail.com'
password = 'password'
responseBody = { session: '05833a20-4035', token: 'pXVCJ9.eyJpYXQ' }
store = initStore({
user: {
requesting: false,
token: null,
session: null
}})
})
it('user can request authentication', async () => {
const test = store.getState()
const container = shallow(<LoginContainer store={store} />)
const login = await container.props().login(email, password)
login()
const state = store.getState()
expect(state.user.requesting).to.be.true
})
})
UserAsyncActions
import ActionsTypes from '../ActionTypes'
export function requestLogin() {
return ActionsTypes.USER_REQUESTED_LOGIN
}
export function loginResponded(token, session) {
return {
type: ActionsTypes.USER_LOGIN_RESPONDED,
token: token,
session: session
}
}
import UserApi from '../../../client/Api/UserApi'
import * as UserActions from './UserActions'
export async function login(email, password) {
return async (dispatch) => {
dispatch(UserActions.requestLogin())
const response = await UserApi.loginUser(email, password),
token = response.body.token,
session = response.body.session
dispatch(UserActions.loginResponded(token, session))
}
}
export default login
initStore
export default (initialState = {}) => {
let middleware = applyMiddleware(thunk)
const store = createStore(reducers, initialState, middleware)
return store
}
请注意,这就是我在测试中创建存储实例的方式:
store = initStore({
user: {
requesting: false,
token: null,
session: null
}}),
调用dispatch(UserActions.requestLogin())
的结果是dispatch(ActionsTypes.USER\u REQUESTED\u LOGIN)
我认为USER\u REQUESTED\u LOGIN
是一个字符串,因为它是一种动作类型,这就是它抱怨的原因。您的requestLogin()
操作创建者应该返回一个对象,例如{type:ActionsTypes.USER\u REQUESTED\u LOGIN}
另一个潜在原因可能来自
export async function login(email, password) { ...
async
函数隐式地将返回的值包装在承诺中,因此login(电子邮件、密码)
返回的是一个包含thunk的承诺,因此thunk中间件将无法处理它。什么是UserActions.requestLogin()
返回的?更新了它,现在看上面,我觉得在LoginContainer中,这是一个同步的非thunk动作。当我试图通过props()调用login时,它不会将其视为thunk操作:export const mapDispatchToProps={login:AsyncActions.login}。因此,当我调用container.props().login()时,我验证了login确实是一个prop,它确实是一个函数,但它并没有像我直接测试AsyncAction creator而不检查container props那样对待它。问题不在于它。那件事已经这样有一段时间了。问题在别处。我总是能够在我的action creator中找到这一点,很好,就像异步实现中更可能出现问题一样。它指向这一行是问题所在,我认为它源于从mapDispatchToProps属性转换的对象类型:container.props().login(电子邮件、密码)啊,我想你的第二件事可能是对的。我尝试删除async,但它破坏了我的一系列其他测试,但让我尝试删除它,让所有测试重新工作。我肯定在别的地方做错了什么
export async function login(email, password) { ...