关于保持React / redux登录代码清洁的最佳实践的指南

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

我正在使用Nodejs服务器和Mongo数据库开发react / redux应用程序。我的react / redux端具有正常运行的登录代码,该登录代码已成功传递到服务器并登录了用户。它似乎太冗长,需要重构以压缩它。我意识到有上百万种重构样板的方法,但是如果有人能指出我要使我的loginAction代码和loginReducer代码更加优雅的地方,我将不胜感激。

以下是使用Redux表单组件,loginActions.js,actionTypes.js和loginReducer.js文件的Login.js页面。登录正确运行,并使用电子邮件/密码组合触摸数据库,以返回authUser数据。

Login.js

import React, { Component } from "react";
import { connect } from "react-redux";
import "./Register.scss";
import LoginForm from "../../components/Forms/AuthForms/LoginForm";
import * as actions from "../../store/actions/authActions/loginActions";
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";

    class Login extends Component {
      state = {
        email: "",
        password: "",
      };

      handleChange = (event) => {
        this.setState({
          email: event.email,
          password: event.password,
        });
      };

      handleSubmit = (event) => {
        event.preventDefault();
        let user = {
          email: this.state.email,
          password: this.state.password,
        };
        console.log("submit", user);

        this.props.onLogin(user);
        console.log("click");
      };
      render() {
        console.log();

        return (
          <Container className="form">
            <Row className="form-row">
              <h3>Login</h3>
              <LoginForm
                onChange={this.handleChange}
                onSubmit={this.handleSubmit}
                user={this.user}
              />
            </Row>
          </Container>
        );
      }
    }

const mapStateToProps = (state) => {
  console.log(state);
  return {
    loading: state.login.loading,
    authUser: state.login.authUser,
    token: state.login.token,
    isAuth: state.login.isAuth,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    onLogin: (user) => dispatch(actions.loginUser(user)),
  };
};

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

loginActions.js

import * as actionTypes from "../types";
import axios from "axios";

export const loginStart = () => {
  return {
    type: actionTypes.LOGIN_START,
  };
};

export const loginSuccess = (token, authUser) => {
  return {
    type: actionTypes.LOGIN_SUCCESS,
    token,
    authUser,
  };
};

export const loginFail = (error) => {
  return {
    type: actionTypes.LOGIN_FAIL,
    error: error,
  };
};

export const logout = () => {
  localStorage.removeItem("token");
  localStorage.removeItem("authUser");
  return {
    type: actionTypes.LOGOUT,
  };
};

export const loginUser = (user) => {
  return (dispatch) => {
    dispatch(loginStart());
    axios
      .post("http://localhost:3100/auth/login", user)
      .then((response) => {
        /* This is an artifact of the way the authController returns the MongoDB doc.
        Needs fixing in authController. Also, need to remove password from return MongoDB doc
        for authUser.
        */
        let authUser = response.data.user._doc;
        localStorage.setItem("token", response.data.token);
        localStorage.setItem("authUser", JSON.stringify(authUser));
        dispatch(loginSuccess(response.data.token, authUser));
      })
      .catch((error) => {
        dispatch(loginFail(error));
      });
  };
};

export const setLoginRedirect = (path) => {
  return {
    type: actionTypes.SET_LOGIN_REDIRECT,
    path,
  };
};

loginReducer.js

import * as actionTypes from "../../actions/types";
import { updateObject } from "../../../shared/utility";
/* upDateObject export code
      export const updateObject = (oldObject, newValues) => {
          return {
              ...oldObject,
              ...newValues
          };
      };
*/
const initialState = {
  token: localStorage.getItem("token") || null,
  authUser: JSON.parse(localStorage.getItem("authUser")) || {},
  isAuth: false,
  error: null,
  loading: false,
  loginRedirectPath: "/dashboard",
};

const loginStart = (state, action) => {
  return updateObject(state, {
    error: null,
    loading: true,
  });
};

const loginSuccess = (state, action) => {
  return updateObject(state, {
    token: action.token,
    authUser: action.authUser,
    error: null,
    loading: false,
    isAuth: true,
  });
};

const loginFail = (state, action) => {
  return updateObject(state, {
    error: action.error,
    loading: false,
  });
};

const logout = (state, action) => {
  return updateObject(state, {
    token: null,
    authData: null,
    isAuth: false,
  });
};

const setLoginRedirect = (state, action) => {
  return updateObject(state, { loginRedirectPath: action.path });
};

const reducer = (state = initialState, action) => {
    switch (action.type) {
        case actionTypes.LOGIN_START:
            return loginStart(state, action)
        case actionTypes.LOGIN_SUCCESS:
            return loginSuccess(state, action)
        case actionTypes.LOGIN_FAIL:
            return loginFail(state, action)
        case actionTypes.LOGOUT:
            return logout(state, action)
        case actionTypes.SET_LOGIN_REDIRECT:
            return setLoginRedirect(state, action)
        default: return state
    };
};

export default reducer;

因此,如果有人对我可以在哪里缩短代码有任何指示,我将不胜感激。谢谢。

reactjs redux action reducers
1个回答
0
投票

Login.js

  handleSubmit = (e) => {
    //rest of the code
    e.preventDefault()
    const user = {
      email: this.state.email,
      password: this.state.password,
    }
    this.props.dispatch(loginUser(user, () => this.props.history.push("/dashboard")))
  }

不是使用多个用于成功登录,失败登录的操作,而是使用单个loginUser函数,该函数返回一个分派操作的函数,也就是thunk

loginActions.js

export const loginUser = (user, redirect) => {
  return async dispatch => {
    dispatch({ type: actionTypes.loginStart })
    try {
      const res = await axios.post(`${url}/auth/login`, user)
      dispatch({
        type: actionTypes.loginSuccess,
        data: { authUser: res.data.user._doc }
      })
      localStorage.setItem("token", res.data.token)
      localStorage.setItem("authUser", JSON.stringify(res.data.authUser));
      redirect()
    } catch (error) {
      dispatch({
        type: actionTypes.loginFail,
        data: { error },
      })
    }
  }
}

成功登录后将用户重定向到仪表板。

对于注销,您可以像在上面的代码中一样添加注销操作。


loginReducer.js


const initialState = {
  token: localStorage.getItem("token") || null,
  authUser: JSON.parse(localStorage.getItem("authUser")) || {},
  isAuth: false,
  error: null,
  loading: false,
}

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.loginStart:
      return {
            ...state,
            loading: true,
            isAuth: false
            error: null
        }
    case actionTypes.loginSuccess:
        return {
            ...state,
            loading: false,
            isAuth: true
            authUser: action.authUser
            token: action.token
            error: null
        }
    case actionTypes.loginFail:
        return {
            ...state,
            loading: false,
            error: action.error
        }
        default: return state
    };
};


const reducer
export default reducer

IMO,这仍然是很多代码。如果您还想“清理”它,那么有一个名为redux-toolkit的新软件包可以解决样板问题。

© www.soinside.com 2019 - 2024. All rights reserved.