首页 > 解决方案 > 如何在 React js 中使用 redux 进行登录

问题描述

我在 react.js 中使用 redux 创建登录概念我收到一个错误 - 无法读取 {this.props.userlogin.name} 中未定义的属性“名称”

我在代码中创建了动作和减速器。

我的 header.js 文件是 -

import React, { Component } from "react";
import { Link, withRouter } from 'react-router-dom';
import './Header.css'
import logo from '../logo.png';
import LoadingSpinner from '../loadingspinner.component';
import Modal from 'react-bootstrap/Modal';
import { loginUser } from "../../Actions/actions";
import PropTypes from "prop-types";
import { connect } from "react-redux";

const emailRegex = RegExp(/^[a-zA-Z0-9_\-\.]+@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/)

const formValid = formErrors => {
    let valid = true;
    Object.values(formErrors).forEach(val => {
        val.length > 0 && (valid = false)
    });
    return valid;
}

class Header extends Component {
    constructor(props) {
        super(props);

        this.state = {
            show: false,
            email: "",
            name: "",
            password: "",
            loading: false,
            message: '',
            formErrors: {
                email: "",
                password: ""
            }
        };

        this.handleShow = () => {
            this.setState({ show: true });
        };

        this.handleHide = () => {
            this.setState({ show: false });
        };

        this.onChange = this.onChange.bind(this);
        this.onSubmit = this.onSubmit.bind(this);
    }

    componentDidMount() {
        // if (localStorage.usertoken && localStorage.usertoken != 'undefined') {
        //     const token = localStorage.usertoken;

        //     const decoded = jwt_decode(token);
        //     console.log(decoded);
        //     this.setState({
        //         name: decoded.name
        //     })
        // }
    }

    onChange(e) {
        const { name, value } = e.target;
        // console.log("name :", name);
        // console.log("value :", value);
        this.setState({ [e.target.name]: e.target.value });
        let formErrors = this.state.formErrors;

        switch (name) {
            case 'email':
                formErrors.email = emailRegex.test(value) ? '' : "Invalid Email Address";
                break;
            case 'password':
                formErrors.password = value.length < 6 ? 'Minimum 6 character required' : "";
                break;
            default: break;
        }
        this.setState({ formErrors, [name]: value }, () => console.log(this.state));
    }

    logOut(e) {
        e.preventDefault();
        localStorage.removeItem("usertoken");
        this.props.history.push("/");
    }

    onSubmit(e) {

        if (formValid(this.state.formErrors)) {
            this.setState({
                loading: true,
            })
            e.preventDefault();
            const user = {
                email: this.state.email,
                password: this.state.password
            };

            this.props.loginUser(user).then((res, err) => {
                // console.log(res);
                if (res.Success == '0') {
                    this.setState({
                        loading: false,
                        message: res.Message
                    })
                }
                else {
                    // if (localStorage.usertoken && localStorage.usertoken != 'undefined') {
                    //     const token = localStorage.usertoken;

                    //     const decoded = jwt_decode(token);
                    //     console.log(decoded);
                    //     this.setState({
                    //         name: decoded.name
                    //     })
                    // }
                    this.handleHide();
                }
            });
        }
        else {
            e.preventDefault();
            console.error('FORM ERROR - DISPLAY ERROR MESSAGE');
        }
    }

    render() {
        const { loading, message } = this.state;
        const { formErrors } = this.state;

        const loginRegLink = (
            <div className="" style={{ display: 'inline-flex' }}>
                <li class="nav-item">
                    <a onClick={this.handleShow} class="nav-link" style={{ cursor: 'pointer' }} >Login&nbsp;<i class="fa fa-user" aria-hidden="true"></i></a>
                </li>
                {/* <li class="nav-item">
                    <a class="nav-link" href="/">SignUp&nbsp;<i class="fa fa-lock" aria-hidden="true"></i></a>
                </li> */}
                <li class="nav-item">
                    <a class="nav-link" href="/">AboutUs</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/">ContactUs</a>
                </li>
            </div>
        );

        const userLink = (
            <div className="" style={{ display: 'inline-flex' }}>
                <li class="nav-item">

                    <Link className="nav-link" to="/">{this.props.userlogin.name}</Link>

                </li>
                <li class="nav-item">
                    <a href="" onClick={this.logOut.bind(this)} className="nav-link">
                        Logout
          </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/">AboutUs</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/">ContactUs</a>
                </li>
            </div>

        );

        return (
            <nav class="navbar navbar-expand-md navbar-light bg-basic" >
                <Link to="/">
                    <img src={logo} />
                </Link>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse w-100 flex-md-column" id="navbarTogglerDemo03">
                    <ul class="navbar-nav ml-auto small mb-2 mb-md-0">
                        {/* <li class="nav-item dropdown">
                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                <img className="country-image" src="https://www.countryflags.io/be/shiny/64.png" />&nbsp;English
                        </a>
                            <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                                <a class="dropdown-item" href="#">Action</a>
                                <a class="dropdown-item" href="#">Another action</a>
                                <a class="dropdown-item" href="#">Something else here</a>
                            </div>
                        </li> */}
                        {localStorage.usertoken && localStorage.usertoken != 'undefined' ? userLink : loginRegLink}
                    </ul>

                </div>


                {/* model popup */}
                <Modal
                    show={this.state.show}
                    onHide={this.handleHide}
                    dialogClassName="modal-90w"
                    aria-labelledby="example-custom-modal-styling-title"
                    centered
                    size="md"
                >
                    <Modal.Header closeButton>
                        <Modal.Title id="example-custom-modal-styling-title text-center">
                            IT Referrals Login
            </Modal.Title>
                    </Modal.Header>
                    <Modal.Body>
                        <div class="form-group" id="sampleTableForEmployee">
                            {message !== '' &&
                                <div class="alert alert-danger alert-dismissible" role="alert">
                                    {message}
                                </div>
                            }
                            <form onSubmit={this.onSubmit}>
                                <div className="row">

                                    <div className="col-md-12">
                                        <div className="input-class-field">
                                            <div className="form-group">
                                                <label htmlFor="email"><b>Email</b></label>
                                                <div className="input-group">
                                                    <span className="input-group-addon">
                                                        <span className="glyphicon glyphicon-envelope" />
                                                    </span>
                                                    <input
                                                        type="email"
                                                        className='form-control'
                                                        id="email"
                                                        name="email"
                                                        style={{ width: '100%' }}
                                                        placeholder="anyone@example.com"
                                                        required="required"
                                                        value={this.state.email}
                                                        onChange={this.onChange}
                                                    />
                                                    {formErrors.email && (
                                                        <span className="errorMessage" style={{ color: 'red', fontSize: '14px' }}>{formErrors.email}</span>
                                                    )}
                                                </div>
                                            </div>
                                            <div className="form-group">
                                                <label htmlFor="password"><b>Password</b></label>
                                                <div className="input-group">
                                                    <span className="input-group-addon">
                                                        <span className="glyphicon glyphicon-envelope" />
                                                    </span>
                                                    <input
                                                        type="password"
                                                        className={formErrors.password.length > 0 ? 'error form-control' : 'form-control'}
                                                        style={{ width: '100%' }}
                                                        id="password"
                                                        name="password"
                                                        placeholder="********"
                                                        required="required"
                                                        value={this.state.password}
                                                        onChange={this.onChange}
                                                    />
                                                    {formErrors.password.length > 0 && (
                                                        <span className="errorMessage" style={{ color: 'red', fontSize: '14px' }}>{formErrors.password}</span>
                                                    )}
                                                </div>
                                            </div>

                                            <div className="form-group">
                                                <button
                                                    type="submit"
                                                    className="btn btn-primary btn-block pull-right"
                                                    id="btnContactUs"
                                                >
                                                    {loading ? <LoadingSpinner /> : "Login"}
                                                </button><br /><br />
                                                {/* <p className="forgetpassword"><a href="">Forget my password ?</a></p> */}
                                                {/* <p className="signup">Don't have an account? <Link to="/register"> Create Now</Link> </p> */}
                                            </div>
                                        </div>
                                    </div>


                                </div>
                            </form>
                        </div>
                        <hr />

                    </Modal.Body>
                </Modal>
                {/* end modal popup */}
            </nav >
        )
    }
}

Header.propTypes = {
    loginUser: PropTypes.func.isRequired,
    userlogin: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
    userlogin: state.userlogin
});
export default connect(
    mapStateToProps,
    { loginUser }
)(Header);

我的减速器代码是 -

import { SET_CURRENT_USER } from "../Actions/actions";

export default function userlogin(state = [], action = {}) {
  switch (action.type) {
    case SET_CURRENT_USER:
      return action.userlogin;
    default:
      return state;
  }
}

我的操作代码是 -

// code to login user
export const SET_CURRENT_USER = "SET_CURRENT_USER";

export function loginUser(user) {
  return dispatch => {
    return axios
      .post("http://localhost:4000/login", {
        email: user.email,
        password: user.password
      })
      .then(res => {
        // Set token to localStorage
        localStorage.setItem("usertoken", res.data.token);
        // Decode token to get user data
        const decoded = jwt_decode(res.data.token);
        // Set current user
        dispatch(setCurrentUser(decoded));
      })
      .catch(err => {
        console.log(err.response.data.msg);
      });
  };
}

export function setCurrentUser(userlogin) {
  return {
    type: SET_CURRENT_USER,
    userlogin
  };
}

如何解决 TypeError:无法读取 header.js 文件中未定义错误的属性“名称”。我们如何登录?

标签: reactjsredux

解决方案


根据您的代码,我希望state.userlogin从一个空数组开始。由于您将减速器设置为具有空数组的初始状态:

export default function userlogin(state = [], action = {}) {}

userlogin从你的商店链接到你的组件:

const mapStateToProps = state => ({
    userlogin: state.userlogin
});

然而userlogin似乎是未定义的,这让我相信你没有正确地将你的减速器映射到你的 rootreducer 中。(也许你在那里用过骆驼箱?)

如果您有,那么可能没有为您的应用程序提供正确的商店,或者您可能在初始化后更改了userloginto的状态。undefined


推荐阅读