我正在使用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;
因此,如果有人对我可以在哪里缩短代码有任何指示,我将不胜感激。谢谢。
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的新软件包可以解决样板问题。