未捕获(承诺中)类型错误:调度不是连接中的函数

问题描述 投票:0回答:2

我正在使用 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)

issue img

我无法找到这里出了什么问题,请帮我找出这个问题,

我尝试过反应动作创建许多与此相关的解决方案,但无法解决此问题

javascript reactjs redux react-redux
2个回答
0
投票

查看

redux-actions
的文档,
createActions
接受一个对象并返回一个对象,而不是函数。您是想打电话给
createAction
吗?


0
投票

基本问题是您使用

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-Toolkit

您正在维护/实现一种非常过时的 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
为您生成三个操作:

替换
sendLogin.pending
sendLoginRequest
sendLogin.fulfilled
sendLoginSuccess
sendLogin.rejected
sendLoginFailed 

您可以在任何现有的案例缩减程序中引用这些新操作:

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;
  }
};
© www.soinside.com 2019 - 2024. All rights reserved.