需要有关保持react/redux登录代码干净的最佳实践的指导



我正在开发一个带有Nodejs服务器和Mongo数据库的react/redux应用程序。我有我的react/redux端的正常登录代码,它成功地传递到服务器并登录到用户。它似乎太长了,需要重构来浓缩它。我知道有一百万种方法可以重构样板,但如果有人能给我指出一些地方,让我的loginAction代码和loginReducer代码更优雅,我将不胜感激。

以下是使用redux表单组件的Login.js页面、loginAction.js、actionTypes.js和loginReducer.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);

loginAction.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;

所以,如果有人能告诉我在哪里可以缩短代码,我将不胜感激。谢谢。

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的新包,它基本上解决了样板问题。

最新更新