Home > other >  React-Redux: Unhandled Rejection (TypeError): dispatch is not a function
React-Redux: Unhandled Rejection (TypeError): dispatch is not a function

Time:03-16

I am struggling with Login page. This is the actions/login.js:

export const login = (username, password) => (dispatch) => {
  return AuthService.login(username, password).then(
    (data) => {
        debugger;
      dispatch({
        type: LOGIN_SUCCESS,
        payload: { user: data },
      });
      return Promise.resolve();
    },
    (error) => {
      const message =
        (error.response &&
          error.response.data &&
          error.response.data.message) ||
        error.message ||
        error.toString();
      dispatch({
        type: LOGIN_FAIL,
      });
      dispatch({
        type: SET_MESSAGE,
        payload: message,
      });
      return Promise.reject();
    }
  );
};

This is my AuthService.js :

import {BASE_URL} from "../constants/globalConstants";
import axios from "axios";
export const USER_INFO = 'USER_INFO';

    const loginEndpoint = BASE_URL   "authenticate";
    
    class AuthService {
        
      login(username, password) {
          debugger;
        return axios
          .post(BASE_URL   "authenticate", { username, password })
          .then((response) => {
            if (response.data.jwtToken) {
              localStorage.setItem(USER_INFO, JSON.stringify(response.data));
            }
            return response.data;
          });
      }
      logout() {
        localStorage.removeItem(USER_INFO);
      }
      register(username, email, password) {
        return axios.post(BASE_URL   "register", {
          username,
          email,
          password,
        });
      }
    }
    export default new AuthService();

And finally the Login.js:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Link } from "react-router-dom";
import { Container, Row, Col, Card, CardBody, FormGroup, Label, Input, Button } from "reactstrap";
import { AvForm, AvField } from "availity-reactstrap-validation";
import axios from 'axios'
import { bindActionCreators } from "redux";
import { selectedSidebarStyle } from "../../actions/sidebarStyleAction";
import { connect } from "react-redux";
import tokenIsValid from './authrorization/JwtAuthorization'
import './../../static/css/Auth.css'
import { BASE_URL } from "../../constants/globalConstants";
import AuthService from "../../services/AuthService";
import { login } from "../../actions/auth";

export const USER_NAME_SESSION_ATTRIBUTE_NAME = 'authenticatedUser';
export const JWT_AUTH_TOKEN = 'AUTH_TOKEN';
export const USER_INFO = 'USER_INFO';

const style = { border: '1px solid #FB3E3E' }

class Login extends Component {

  constructor(props) {
    super(props);
    this.state = {
      email: "",
      password: "",
      userAuth: false,
      loading: false,
    }
  }

  handleFieldChange = (event) => {
    this.setState({
      [event.target.name]: event.target.value
    })
  }

  //   this.props.history.push(`/welcome/${this.state.username}`)
  requestLogin = () => {
    const loginEndpoint = BASE_URL   "authenticate";

    axios({
      method: 'post',
      url: loginEndpoint,
      data: {
        username: this.state.username,
        password: this.state.password
      }
    }).then((response) => {
      if (response.data !== null) {
        sessionStorage.setItem(USER_INFO, JSON.stringify(response.data));
      }
    }, (error) => {
      console.log("Unsuccessful login request")

    })
  }

  authHeader() {
    const user = JSON.parse(localStorage.getItem(USER_INFO));
    if (user && user.jwtToken) {
      return { Authorization: 'Bearer '   user.jwtToken };
    } else {
      return {};
    }
  }

  isUserLoggedIn() {
    let user = window.sessionStorage.getItem(USER_INFO)
    if (user === null) {
      return false
    }
    return true;
  }

  getLoggedInUserName() {
    let user = window.sessionStorage.getItem(USER_INFO)
    if (user === null) {
      return ''
    }
    return user
  }

  /*
  * TODO: See where to use the logout and how to redirect the user to the login page in case JWT token is expired
  * */
  logout() {
    sessionStorage.removeItem(USER_INFO);
  }

  handleSubmit = (e) => {
    e.preventDefault();
    const {dispatch} = this.props;
    dispatch(login(this.state.username, this.state.password))
      .then(() => {
        window.location.reload();
      })
      .catch(() => {
        this.setState({
          loading: false
        });
      });

  }
  render() {
    return (
      <React.Fragment>
        <div className="account-home-btn d-none d-sm-block">
          <Link to="/" className="text-white"><i className="mdi mdi-home h1"></i></Link>
        </div>

        <section className="bg-account-pages height-100vh">
          <img className={"hive-logo1"} src={require('./hive-logo.png')} alt="Logo" width="70px" height="60px" />
          <div className="display-table">
            <div className="display-table-cell">
              <Container>
                <Row className="justify-content-center">
                  <Col lg={5}>
                    <Card className="account-card">
                      <CardBody>
                        <div className="text-center mt-3">
                          <h3 className="font-weight-bold"><a href=""
                            className="text-dark text-uppercase account-pages-logo">Sign In</a>
                          </h3>
                          <u><p className="text-muted">Enter your credentials to continue to the platform.</p></u>
                        </div>
                        <div className="p-3">
                          <AvForm onSubmit={this.handleSubmit}>
                            <FormGroup>
                              <Label htmlFor="username">Email</Label>
                              <AvField type="text" name="username" value={this.state.email}
                                onChange={this.handleFieldChange} required className="form-control"
                                id="username"
                                placeholder="Enter email" />
                            </FormGroup>

                            <FormGroup>
                              <Label htmlFor="userpassword">Password</Label>
                              <AvField type="password" name="password" value={this.state.password}
                                onChange={this.handleFieldChange} required className="form-control"
                                id="userpassword" placeholder="Enter password" />
                            </FormGroup>

                            <div className="custom-control custom-checkbox">
                              <Input type="checkbox" className="custom-control-input" id="customControlInline" />
                              <Label className="custom-control-label" htmlFor="customControlInline">Remember
                                me</Label>
                            </div>

                            <div className="mt-3">
                              <Button color="none" type="submit" className="sign-in-button" >Sign In</Button>
                            </div>

                            <div className="mt-4 mb-0 text-center">
                              <Link to="password_forget" className="text-dark"><i className="mdi mdi-lock"></i> Forgot
                                your password?</Link>
                            </div>
                          </AvForm>
                        </div>
                      </CardBody>
                    </Card>
                  </Col>
                </Row>
              </Container>
            </div>
          </div>
        </section>

      </React.Fragment>
    );
  }
}

Login.PropTypes = {
  dispatch: PropTypes.func,
  login: PropTypes.func
};

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators({
      login
    }, dispatch)
  };
}

const mapStateToProps = (state) => {
  const { isLoggedIn } = state.auth;
  const { message } = state.message;
  return {
    isLoggedIn,
    message
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(Login);

And I made so many changes and I can't fix this: enter image description here

I am trying to push the login details, fetched from the bckend to the Session Storage and push it to the Redux so I can fetch the data later after loging and keep the token, id, password and email for the user

CodePudding user response:

Somewhere in the documentation I have read that if we use mapDispatchToProps function in the connect method then the component will not get dispatch function as props .I tried finding the document link but could not get it.

try debugging component props to see dispatch function is there or not

CodePudding user response:

You are already binding login with the dispatch.

So to call that, you need to do this;

this.props.login(...)

instead of this;

dispatch(login(...))

Functions in mapDispatchToProps are added to dispatch and if you call them like this this.props.function_name(), they are dispatched too.

  • Related