1. React-redux:

This section will be implemented via react-redux before juejin.cn/post/694011… Login refactoring to make the project clearer. Let’s take a look at the SRC directory structure:

The SRC ├ ─ App. Js ├ ─ index. The js ├ ─ store | ├ ─ redux | | ├ ─ index. The js | | ├ ─ rootReducer. Js | | ├ ─ user / / 🚀 this part is the key ~! | | | ├ ─ actionCreator. Js | | | ├ ─ actionType. Js | | | └ reducer. Js ├ ─ pages | ├ ─ the About the js | ├ ─ Home. Js | ├ ─ the Login. The js | ├ ─ NotFound. Js | └ User. JsCopy the code

1. Store creation:

SRC Create a store folder. If the project is large, it is best to break it down by functionality. For example, the user logs in as a folder, and the store folder has index.js and rootreducer.js to integrate all functions.

Here’s the code in store/index.js:

// store/index.js
import {createStore} from "redux";
import {applyMiddleware} from "redux";
import logger from "redux-logger";
import thunk from "redux-thunk";
import {rootReducer} from "./rootReducer";
/ / create a store
// 🚀 Use applyMiddleware after installing middleware
// 🚀 Combine multiple reducer through combineReducers
const store = createStore(rootReducer,applyMiddleware(logger,thunk));
export default store;
Copy the code

This is where rootReducer is introduced to create a store, and through applyMiddleware.

2. Part of the login function of user module

There are three files in the user folder:

  • actionType.js: Used to declareAciton typeThe constant
  • actionCreator.js: encapsulates some returnsThe action of the function
  • reducer.js: handlingactionthePure functions

🚀 then take a look at the respective parts of the code:

//actionType.js
export const LOGIN = "login";
Copy the code
//actionCreator.js
import {LOGIN} from "./actionType";
export const loginUser = () = > {
    return {
        type:LOGIN
    }
}
//🚀 redux-thunk can have Dispatch dispatch a function that takes Dispatch as an argument
export const login =  (dispatch) = >{
    setTimeout(() = >{
        const action = loginUser();
        dispatch(action);
    },1000)};Copy the code
//reducer.js
import {LOGIN} from "./actionType";
import {login} from "./actionCreator";
// Initial state
const initState = {
    isLogin:false.userInfo:{}
}
Reducer is a pure function
function user(state = initState,action){
        switch (action.type){
            case LOGIN:
                return {isLogin:true}
            default:
                return initState
        }
}
export default user;
// 🚀 literally matches state in redux to this.props of the component
export const mapStateToProps = state= > {
    return {
        // 🚀 plus the current state key for modular identification
        user:state.user
    }
}
// 🚀 mapDispatch matches the dispatch to this. Props of the component
export const mapDispatchToProps = dispatch= >{
    return {
        login(){
            dispatch(login)
        }
    }
}
Copy the code
  • mapStateToPropsWill: Literally means willreduxIn thestateThat matches the componentthis.propsIn the
  • mapDispatchToPropsFrom:mapDispatchTo take the literal meaning of “is to takedispatchMatched to the componentthis.propsin

Rootreducer.js merges each reducer of the module:

// store/rootReducer.js
import {combineReducers} from "redux";
import userReducer from "./user/reducer";

export const rootReducer  = combineReducers({
    user:userReducer
})
Copy the code

3. In the project root directoryindex.js

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import store from "./store/redux"
import {Provider} from "react-redux";
import App from "./App";
function render(){
    ReactDOM.render(
        <Provider store = {store}>
            <App/>
        </Provider>
        ,
        document.getElementById('root')); } render();// 🚀 sign up to subscribe to render again every time state is updated
stores.subscribe(render)
Copy the code
  • willstoreBring in, and then passreact-reduxIn thePrivider,storeAs apropsPass it on and onApp componentWrap up.
  • throughstore.subscribeSubscribe to the page

4. App. Js components:

import React, {Component} from 'react';
import {BrowserRouter as Router,Route,Link,Switch,Redirect} from "react-router-dom";
import Home from "./pages/Home.js";
import NotFound from "./pages/NotFound";
import About from "./pages/About";
import Login from "./pages/Login";
import {connect} from "react-redux";
import {mapStateToProps} from "./store/redux/user/reducer";

@connect(mapStateToProps)
class PrivateRoute extends Component{
    render(){
        const Comp = this.props.sendComponent;
        console.log("I'm component COMp",Comp);
        return(
            <Route
                {. this.props} // 🚀 is best used herecomponentRather thanrender
                component={
                    (props) = >
                        this.props.user.isLogin ?
                            (<Comp {. props} / >) :
                            (<Redirect to={{ pathname: '/login',
                                state: { from: props.location } }} />)
                }>
            </Route>)}}class App extends Component {
    render() {
    return (
          <Router>
            <ul>
              <li>
                <Link to="/">Home page</Link>
              </li>
                <li>
                    <Link to="/about">About me</Link>
                </li>
            </ul>{/* Routing configuration */}<Switch>{/ * 🚀 (1) * /}<Route exact path="/home" component={Home} />
                <Route  path="/user" component={User}/>{/* 🚀PrivateRoute is a higher-order component */}<PrivateRoute  path="/about" sendComponent={About}/>
                <Route path="/login" component={Login}/>{/* 🚀 is placed in front of NotFound, because the Switch has found the component that matches the condition, it does not proceed further */}<Redirect to="/home"/>
                <Route component={NotFound}/>
              </Switch>
          </Router>); }}export default App;
Copy the code
  • PrivateRouteIs the routingRouteThe encapsulation
  • <PrivateRoute path="/about" sendComponent={About}/>Hang onsendComponentOn theAboutComponents in thePrivateRouteIs throughthis.props.sendComponentGet.
  • throughmapStateToPropsTo get thethis.props.user.isLoginTo determine which one to render

5. FinallyLogin.jsComponents:

//page/Login.js
import React, {Component} from 'react';
import {Redirect} from "react-router-dom";
import {connect} from "react-redux";
import {mapStateToProps,mapDispatchToProps} from ".. /store/redux/user/reducer";

@connect(mapStateToProps,mapDispatchToProps)
class Login extends Component {
    toOrigin = () = >{
        // 🚀 is used to specify the key (user), but to specify the function (this.props. Login)
        this.props.login();
    }
    render() {
        console.log("Value passed by PrivateRoute".this.props.location.state);
        let path = this.props.location.state.from.pathname;
        let {isLogin} = this.props.user;
        if(isLogin){
            return <Redirect to={path}/>
        }
        else{
            return (
                <div>
                    <p>Please login first</p>
                    <button onClick={this.toOrigin}>Log in</button>
                </div>); }}}export default Login;
Copy the code
  • through@connect(mapStateToProps,mapDispatchToProps)After the decorator is decorated,toOriginIn the functionthis.props.login()In fact, the call is inreducer.jsDefined in themapDispatchToPropsIn theThe login function