Practical react technology stack + Express front end and back end blog project (5) — front end and back end login function

Time:2021-6-8

Practical react technology stack + Express front end and back end blog project (5) — front end and back end login function

Project address:https://github.com/Nealyang/R…

I wanted to wait for the project to finish and then serialize a series of blogs. With the development, I did encounter many pitfalls and consulted many people. So I thought, why not record and share the harvest at the same time. Sharing is good, of course,
It would be more beautiful if we could pool our wisdom. Our slogan is:We will never fail

This blog is a serial code blog, which is updated synchronously. With the development of the project in the future, we may encounter the inappropriate places written before, and then we will go back to modify them. If there is something wrong, please don’t be stingy. thank you!

Login section

  • Login screenshot

Practical react technology stack + Express front end and back end blog project (5) -- front end and back end login function

Implementation of front end

Next, we have finished drawing the login interface. The login function involves asynchronous requests. So I need the following actions. Request to initiate action, request to end action, error message reminder action, login action, registration action and the automatic login action we use later.

Because the login function involves global information, we put it into the reducer of index here

const initialState = {
    isFetching: true,
    msg: {
        Type: 1, // 0 failed 1 succeeded
        content: ''
    },
    userInfo: {}
};

export const actionsTypes = {
    FETCH_START: "FETCH_START",
    FETCH_END: "FETCH_END",
    USER_LOGIN: "USER_LOGIN",
    USER_REGISTER: "USER_REGISTER",
    RESPONSE_USER_INFO: "RESPONSE_USER_INFO",
    SET_MESSAGE: "SET_MESSAGE",
    USER_AUTH:"USER_AUTH"
};

export const actions = {
    get_login: function (username, password) {
        return {
            type: actionsTypes.USER_LOGIN,
            username,
            password
        }
    },
    get_register: function (data) {
        return {
            type: actionsTypes.USER_REGISTER,
            data
        }
    },
    clear_msg: function () {
        return {
            type: actionsTypes.SET_MESSAGE,
            msgType: 1,
            msgContent: ''
        }
    },
    user_auth:function () {
        return{
            type:actionsTypes.USER_AUTH
        }
    }
};

export function reducer(state = initialState, action) {
    switch (action.type) {
        case actionsTypes.FETCH_START:
            return {
                ...state, isFetching: true
            };
        case actionsTypes.FETCH_END:
            return {
                ...state, isFetching: false
            };
        case actionsTypes.SET_MESSAGE:
            return {
                ...state,
                isFetching: false,
                msg: {
                    type: action.msgType,
                    content: action.msgContent
                }
            };
        case actionsTypes.RESPONSE_USER_INFO:
            return {
                ...state, userInfo: action.data
            };
        default:
            return state
    }
}

Front end login and registration action initiation

class LoginFormCom extends Component {
    constructor(props) {
        super(props);
    }

    handleLogin = (e) => {
        e.preventDefault();
        this.props.form.validateFields((err, values) => {
            if (!err) {
                this.props.login(values.userName,values.password)
            }
        });
    };

    render() {
        const {getFieldDecorator} = this.props.form;
        return (
            <Form onSubmit={this.handleLogin} className={style.formStyle}>
                <FormItem>
                    {getFieldDecorator('userName', {
                        Rules: [{required: true, message: 'please enter user name!'}],
                    })(
                        <Input prefix={<Icon type="user" style={{fontSize: 13}}/>} placeholder="Username"/>
                    )}
                </FormItem>
                <FormItem>
                    {getFieldDecorator('password', {
                        Rules: [{required: true, message: 'please enter password!'}],
                    })(
                        <Input prefix={<Icon type="lock" style={{fontSize: 13}}/>} type="password"
                               placeholder="Password"/>
                    )}
                </FormItem>
                <FormItem>
                    <Button className={style.loginButton} type="primary" htmlType="submit">
                        Sign in
                    </Button>
                </FormItem>
            </Form>
        )
    }
}

const LoginForm = Form.create()(LoginFormCom);

export default LoginForm

As shown in the above code, in handlelogin, we call the login method passed in by the parent component. Maybe it’s my grandfather. Just its container component.

The code in the container component home.js is as follows:

 Home.defaultProps = {
     userInfo:{}
 };
 
 Home.propsTypes = {
     userInfo:PropTypes.object.isRequired
 };
 
 function mapStateToProps(state) {
     return{
         userInfo:state.globalState.userInfo
     }
 }
 
 function mapDispatchToProps(dispatch) {
     return{
         login:bindActionCreators(actions.get_login,dispatch),
         register:bindActionCreators(actions.get_register,dispatch)
     }
 }
 
 export default connect(
     mapStateToProps,
     mapDispatchToProps
 )(Home);
 

As mentioned above, we have defined login and register. They are login and registration methods. In the login section, we write as above. Of course, the registration function is the same as above.

###How to log in and register Saga

Because login and registration are asynchronous, we need saga to monitor the initiation of this action. And then deal with it accordingly.

export function* register (data) {
    yield put({type:IndexActionTypes.FETCH_START});
    try {
        return yield call(post, '/user/register', data)
    } catch (error) {
        yield put({ type:IndexActionTypes.SET_ Message, msgcontent: 'registration failed', msgt ype:0 });
    } finally {
        yield put({type: IndexActionTypes.FETCH_END});
    }
}


export function* registerFlow () {
    while(true){
        let request = yield take(IndexActionTypes.USER_REGISTER);
        let response = yield call(register, request.data);
        if(response&&response.code === 0){
            yield put({ type:IndexActionTypes.SET_ Message, msgcontent: 'registration successful! ", msgT ype:1 });
            yield put({type:IndexActionTypes.RESPONSE_USER_INFO,data:response.data})
        }

    }
}

Here, let’s give an example of registerflow, which is actually monitoring user_ Action of register. Then call the register method, send the request to start action (interface appears Loading), then request to end action. After receiving the request, take out the data and send the action after getting the data

The basic idea as above, the code as above, we study ha, do not understand the place, direct issue.

Posterior segment

router.post('/register', (req, res) => {
    let {userName, password, passwordRe} = req.body;
    if (!userName) {
        Responseclient (RES, 400, 2, 'user name cannot be empty');
        return;
    }
    if (!password) {
        Responseclient (RES, 400, 2, 'password cannot be empty');
        return;
    }
    if (password !== passwordRe) {
        Responseclient (RES, 400, 2, 'two passwords are inconsistent');
        return;
    }
    //Verify that the user is already in the database
    User.findOne({username: userName})
        .then(data => {
            if (data) {
                Responseclient (RES, 200, 1, 'user name already exists');
                return;
            }
            //Save to database
            let user = new User({
                username: userName,
                password: md5(password + MD5_SUFFIX),
                type: 'user'
            });
            user.save()
                .then(function () {
                    User.findOne({username: userName})
                        .then(userInfo=>{
                            let data = {};
                            data.username = userInfo.username;
                            data.userType = userInfo.type;
                            data.userId = userInfo._id;
                            Responseclient (RES, 200, 0, 'registration successful', data);
                            return;
                        });
                })
        }).catch(err => {
        responseClient(res);
        return;
    });
});

In fact, the back end is almost the same. Let’s take registration as an example. Explain the above code briefly

Responseclient is an encapsulated method. The code is as follows:

module.exports = {
     MD5_ Suffix: "eiowafnajkdlfjsdkfj, elder sister Fu and elder sister Wen are in trouble. I see you @ # ¥%... &) (* &) ',
     md5: function (pwd) {
         let md5 = crypto.createHash('md5');
         return md5.update(pwd).digest('hex')
     },
     Responseclient (RES, httpcode = 500, code = 3, message ='server exception ', data = {}){
         let responseData = {};
         responseData.code = code;
         responseData.message = message;
         responseData.data = data;
         res.status(httpCode).json(responseData)
     }
 }

It allows you to abbreviate a lot of code. Then judge whether the user name and password are empty and whether the two passwords are consistent( Although these parts should also be judged at the front end, the back end should also be protected as far as possible).

Verify that the user is already in the database. If it doesn’t exist, store it and return the user information. If it exists, the corresponding information will be returned to the client.

Note that we use saga here, so as long as the HTTP request for three handshakes is successful, we will return 200. For repeated user name and other errors, we will give a status code in the returned data.

When storing, we use MD5 encryption, in order to prevent MD5 decryption, we add a random string at the end. When logging in, get the user’s login password, add a random string, encrypt with MD5, and then compare with the database data memory.

These are the basic ideas of back-end implementation. We will not repeat the basic operation of mongoose here. You can view the documents by yourself.

router.post('/login', (req, res) => {
     let {username, password} = req.body;
     if (!username) {
         Responseclient (RES, 400, 2, 'user name cannot be empty');
         return;
     }
     if (!password) {
         Responseclient (RES, 400, 2, 'password cannot be empty');
         return;
     }
     User.findOne({
         username,
         password: md5(password + MD5_SUFFIX)
     }).then(userInfo => {
         if (userInfo) {
             //Login successful
             let data = {};
             data.username = userInfo.username;
             data.userType = userInfo.type;
             data.userId = userInfo._id;
             //Login successful后设置session
             req.session.userInfo = data;
 
             Responseclient (RES, 200, 0, 'login successful', data);
             return;
         }
         Responseclient (RES, 400, 1, 'wrong user name and password');
 
     }).catch(err => {
         responseClient(res);
     })
 });

##Summary

Basically, this is a process of checking and adding. It also realizes the basic interaction between the front end and the back end. Let’s feel it~

Then you must also find that after logging in, it seems that we have to log in again every time we refresh. This is not what we want. Of course, this part of the function, we will introduce in the next blog.

##Project implementation steps series blog

##Communication

If you have something you don’t understand or need to communicate with me, you are welcome to mention issue. Or add a group to contact me~

Scan code concerns my personal WeChat official account, and reply directly, there must be a response. Share more original articles. Click exchange learning plus wechat and QQ group. Study together and make progress together

Practical react technology stack + Express front end and back end blog project (5) -- front end and back end login function

Welcome to join us

Node.js technology exchange group: 209530601

React technology stack: 398240621

Front end technology: 604953717 (New)