preface

Last time I learned react to write a background management, this time I am thinking of writing a mobile terminal project. This project was born.

A vUE version of this project was written before. If you are interested, you can click on it


Easy Mock is used to simulate the data

Using the same data I used to write Vue-Toutiao

Account: vue – toutiao

Password: 123456

Technology stack

react + react-redux + react-router + webpack

Structure:

  • Build: webpack configuration
  • Config: indicates project configuration parameters
  • src
    1. actions: Stores the action method
    2. assets: static resource file, store images and so on
    3. components: Common components
    4. reducersDeposit: reducer
    5. router: Route management
    6. store: State management redux
    7. styles: style file
    8. utils: Common packaging
    9. views: View page
  • Static: static files: store favicon.ico, etc

Results demonstrate

knowledge

According to the need to load

The component is loaded through the import() method, and the Promise result returned by the import is processed through the higher-order component.

// asyncComponent.js
import React from 'react'

export default loadComponent => (
    class AsyncComponent extends React.Component {
        state = {
            Component: null,
        }
        async componentDidMount() {
            if(this.state.Component ! == null)return
            try {
                const {default: Component} = await loadComponent()
                this.setState({ Component })
            }catch (err) {
                console.error(`Cannot load component in <AsyncComponent />`);
                throw err
            }
        }

        render() {
            const { Component } = this.state
            return(Component) ? <Component {... this.props} /> : null } } )Copy the code

Use the following

import asyncComponent from './asyncComponent'
const Demo = asyncComponent(() => import(`views/demo.js`))
<Route path="/demo" component={Demo}/>
Copy the code

Routing setting

Configure routes and route status in a unified manner

import asyncComponent from './asyncComponent'
const _import_views = file => asyncComponent(() => import(`views/${file}`))
export const loyoutRouterMap = [
    { 
        path: '/', 
        name: 'home', 
        exact: true,
        component: _import_views('Home')
    },
    { 
        path: '/video', 
        name: 'video',
        component: _import_views('Video')
    },
    { 
        path: '/headline', 
        name: 'Micro Headlines',
        component: _import_views('Headline')
    },
    { 
        path: '/system', 
        name: 'System Settings',
        auth: true, 
        component: _import_views('System')}]Copy the code

Login to intercept

Use the auth attribute in the route configuration to determine whether to log in

{ 
    path: '/system', 
    name: 'System Settings',
    auth: true, 
    component: _import_views('System')}Copy the code

Login configuration and judgment

// authRoute.js
import React from 'react'
import store from '.. /store'
import { Route, Redirect } from 'react-router-dom'

export default class extends React.Component {
    render () {
        let{component: Component, ... Rest} = this.props // Whether to log inif(! store.getState().user.user.name) {return <Redirect to='/login' />
        }
        return<Route {... Rest} Component ={component}/>}}/ / generate route const renderRouteComponent => routes => routes.map((route, index) => {if(route.auth) {// Need permission to log inreturn<AuthRoute key={index} {... route}/> }return<Route key={index} {... route}/> })Copy the code

Routing animation

React-router-transition switch animation

And then history.slideStatus to determine how to animate

The react – the router – the transition specific apis

Redux-thunk handles asynchronous action

Use redux-actions to write the actions and reducer

// action.js
import { createAction } from 'redux-actions'
import axios from 'utils/axios'
export const getHeadlineList = (params) => dispatch => {
    return new Promise( (resolve, reject) => {
        axios.get('headline/list', params)
            .then( res => {
                const list = res.data.list
                dispatch(createAction('GET_HEADLINE_LIST')(list))
                resolve(list)
            }).catch( err => {
                reject(err)
            })
    })
}

// reducer.js
import { handleActions } from 'redux-actions'
import { combineReducers } from 'redux'
const state = {
    headlineList: []
}
const headline = handleActions({
    GET_HEADLINE_LIST: (state, action) => {
        let list = action.payload
        state.headlineList = state.headlineList.concat(list)
        return{... state} } }, state)exportDefault combineReducers({headline}) // store.js // redux-thunk configuration import {createStore, compose, applyMiddleware} from'redux'
import reducer from '.. /reducers'
import thunk from 'redux-thunk'
const configureStore => createStore(
    reducer,
    compose(
        applyMiddleware(thunk)
    ) 
)
export default configureStore()

Copy the code

There are some scattered knowledge points, I will not introduce, specific can be viewed on Github.

github

Personal blog

Online viewing address