我正在使用 redux、react-redux 和 React 构建一个应用程序。当我与组件连接并进行操作调用时,我收到一个 Uncaught (in Promise) TypeError: sendLoginRequest is not a function
我的代码:
组件/
import React, { useState } from "react";
import { connect } from 'react-redux';
import { sendLogin } from './Login.Action';
import { Google, Microsoft } from "@mui/icons-material";
import { NavLink, useNavigate } from "react-router-dom";
import * as constant from "../../constant/commonString";
const Login = ({
userName,
isError,
loginSuccess,
loginErrorMessage,
triggerLogin
})=> {
const navigate = useNavigate();
const { sendRequest, loading } = useHttpClient();
const [email, setLoginEmail] = useState("");
const [password, setLoginPassword] = useState("");
const handleEmail = (e) => {
setLoginEmail(e.target.value);
};
const handlePassword = (e) => {
setLoginPassword(e.target.value);
};
const handleLogin = (e) => {
e.preventDefault();
try {
const log = triggerLogin({ email, password });
} catch {
console.log('errr');
}
};
return (
<div className="container">
<div className="welcome">
<h1>{constant.WELCOME}</h1>
</div>
<form>
<input
value={email}
onChange={handleEmail}
type="email"
id="emailnote"
name="email"
required
placeholder="Email address"
/>
<input
value={password}
onChange={handlePassword}
type="password"
id="passwordnote"
name="password"
required
placeholder="Password"
/>
<Button
type="submit"
stylx="button_style button-text-design next-button"
text=" Continue"
onClick={handleLogin}
/>
</form>
<div className="details">
<p>
{constant.ACCOUNT_INFO}
<NavLink className="signup" to="/signup">
{constant.SIGNUP}
</NavLink>
</p>
</div>
<div className="login-options">
<button className="google">
<Google color="primary" />
{constant.GOOGLE}
</button>
<button className="microsoft">
<Microsoft color="primary" />
{constant.MICROSOFT}
</button>
</div>
<div className="terms">
<NavLink to="/terms">{constant.TERMS}</NavLink>
<span>|</span>
<NavLink to="/policy">{constant.POLICY}</NavLink>
</div>
</div>
);
};
const mapStateToProps = ({ login }) => ({ ...login });
export default connect(mapStateToProps, {
triggerLogin: sendLogin,
})(Login);
登录.Action.js
/* eslint-disable */
import { createActions, handleActions, combineActions } from 'redux-actions';
import { post, } from '../../utils/api';
import {
SEND_LOGIN_REQUEST,
SEND_LOGIN_SUCCESS,
SEND_LOGIN_FAILED,
SET_TOKEN_ID
} from './Login.Action.constant';
const sendLoginRequest = createActions(SEND_LOGIN_REQUEST);
const sendLoginSuccess = createActions(SEND_LOGIN_SUCCESS);
const sendLoginFailed = createActions(SEND_LOGIN_FAILED);
export const setToken = createActions(SET_TOKEN_ID);
const API_URL = {
LOGIN: 'users/login',
LOGOUT: 'user/web/logout'
};
export const sendLogin = (data) => async (dispatch) => {
// here i am getting data
dispatch(sendLoginRequest());
const { error, response } = await post(`${API_URL.LOGIN}`, data);
if (response) {
dispatch(sendLoginSuccess(response));
} else if (error) {
dispatch(sendLoginFailed(error));
}
};
错误
Login.Action.js:44 Uncaught (in promise) TypeError: sendLoginRequest is not a function
at Login.Action.js:44:1
at Object.dispatch (redux-thunk.mjs:5:1)
at dispatch (<anonymous>:6:7384)
at boundActionCreators.<computed> (bindActionCreators.ts:12:1)
at handleLogin (Login.js:37:1)
我无法找到这里出了什么问题,请帮我找出这个问题,
我尝试过反应动作创建许多与此相关的解决方案,但无法解决此问题
查看
redux-actions
的文档,createActions
接受一个对象并返回一个对象,而不是函数。您是想打电话给 createAction
吗?
基本问题是您使用
createActions
(复数,带有“s”)而不是 createAction
来创建您的个人操作。看起来 createActions 将此作为边缘情况处理,并返回动作创建器函数的对象。
export default function createActions(actionMap, ...identityActions) { const options = isPlainObject(getLastElement(identityActions)) ? identityActions.pop() : {}; invariant( identityActions.every(isString) && (isString(actionMap) || isPlainObject(actionMap)), 'Expected optional object followed by string action types' ); if (isString(actionMap)) { // <-- return actionCreatorsFromIdentityActions( // <-- [actionMap, ...identityActions], // <-- options // <-- ); // <-- } return { ...actionCreatorsFromActionMap(actionMap, options), ...actionCreatorsFromIdentityActions(identityActions, options) }; }
所以(安全地)假设
SEND_LOGIN_REQUEST
是一个字符串值,即"SEND_LOGIN_REQUEST"
,以下行
const sendLoginRequest = createActions(SEND_LOGIN_REQUEST);
生成一个包含动作创建者函数的对象,而不是直接包含动作创建者函数。
{ sendLoginRequest: (...args) => {....}, }
与
(...args) => {....}
如果您想分派此
sendLoginRequest
操作,那么它可能看起来像 dispatch(sendLoginRequest.sendLoginRequest());
,您可以在其中访问返回的操作映射对象的 sendLoginRequest
(也称为 sendLoginRequest
)。
您可能应该只使用
createAction
实用程序来保持简单(很可能是您从一开始就打算做的事情)。
import { createAction, handleActions, combineActions } from 'redux-actions';
import { post } from '../../utils/api';
import {
SEND_LOGIN_REQUEST,
SEND_LOGIN_SUCCESS,
SEND_LOGIN_FAILED,
SET_TOKEN_ID
} from './Login.Action.constant';
const sendLoginRequest = createAction(SEND_LOGIN_REQUEST);
const sendLoginSuccess = createAction(SEND_LOGIN_SUCCESS);
const sendLoginFailed = createAction(SEND_LOGIN_FAILED);
export const setToken = createAction(SET_TOKEN_ID);
...
dispatch(sendLoginRequest()); // <-- now properly a function
您正在维护/实现一种非常过时的 Redux 形式。您应该真正集成 Redux-Toolkit,它可以删除大部分 Redux 样板代码(例如声明操作类型、创建操作/成功/失败操作等...)。如果您已经熟悉 Redux,这大约需要 5-10 分钟的升级来替换商店创建。
Login.Action.js
可以重写如下:
import { createAsyncThunk } from '@reduxjs/toolkit';
import { post } from '../../utils/api';
const API_URL = {
LOGIN: 'users/login',
LOGOUT: 'user/web/logout'
};
export const sendLogin = createAsyncThunk(
"auth/sendLogin",
async (data, thunkApi) => {
try {
const { error, response } = await post(API_URL.LOGIN, data);
if (response) {
return response;
} else if (error) {
return thunkApi.rejectWithValue(error);
}
} catch(error) {
return thunkApi.rejectWithValue(error);
}
},
);
如果
post
只是抛出错误/拒绝,而不是使用 error
属性来解决,尽管代码变得相当简单:
export const sendLogin = createAsyncThunk(
"auth/sendLogin",
(data, thunkApi) => {
try {
return post(API_URL.LOGIN, data);
} catch(error) {
return thunkApi.rejectWithValue(error);
}
},
);
createAsyncThunk
为您生成三个操作:
新 | 替换 |
---|---|
|
|
|
|
|
|
您可以在任何现有的案例缩减程序中引用这些新操作:
const someReducer = (state, action) => {
switch(action.type) {
...
case sendLogin.pending.type:
// update any pending action state
case sendLogin.fulfilled.type:
// update any success action state
// action.payload is the resolved response value
case sendLogin.rejected.type:
// update any failure action state
// action.payload is the rejected error value
...
default:
return state;
}
};