React is not as easy to learn as Vue, from a learning standpoint. All things are difficult at the beginning, and then in the middle, the result is difficult…… Here is how I integrated the plug-in step by step and built the basic framework.

1 using the create – react – app

Create a project catalog using the official scaffolding tool

npx create-react-app react-app
Copy the code

The NPX in the first line is not a typo, it is the package runtime tool that comes with NPM 5.2+.

After the installation is complete, start the project using NPM or YARN

npm start(yarn start)
Copy the code

After the project is started, the default port number is 3000, which can be accessed through localhost:3000

Change the original catalog deconstruction, adjust to personal more accustomed or comfortable

2 Basic Configuration

2.1 Css preprocessors

Create-react-app does not expose configuration files by default. Running NPM run eject to expose configuration files is irreversible. Personally prefer to use react-app-rewired custom configuration (similar to vue-cli3 custom configuration file)

X react-app-rewired create-react-app 1.x react-app-rewired create-react-app 2.x react-app-rewired create-react-app 2.x react-app-rewired@^2.0.0+ The version needs to be used with customize-cra

2.1.1 support Scss

Create-react-app comes with sass-Loader and sass-related configurations. You only need to install Node-sass to use it

npm i node-sass -D
Copy the code

Note that the installation of Node-sass will always fail, NPM I node-sass is my preferred method to install all packages directly using CNPM –sass_binary_site=https://npm.taobao.org/mirrors/node-sass/

2.1.2 support Less

Since antD will be integrated in the future, I recommend using less for the unified preprocessor, and execute:

npm i react-app-rewired customize-cra -D
Copy the code

Modify the package. The json

"scripts": {
    "start": "react-app-rewired start"."build": "react-app-rewired build"."test": "react-app-rewired test"."eject": "react-scripts eject"
}
Copy the code

Then create config-overrides. Js in the root directory and add the configuration:

const { override, addLessLoader } = require('customize-cra')
const path = require('path')

module.exports = override(
  addLessLoader()
)
Copy the code

2.2 Introduction of global common styles

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import './common/style/reset.less'
import './common/style/base.less'
import './common/fonts/iconfont.css'

ReactDOM.render(<App />, document.getElementById('root'))
Copy the code

3 routing

Execute the installation command:

npm i react-router-dom
Copy the code

Modify app.jsx file:

import React, { Component } from 'react'
import { Router } from 'react-router-dom'
import history from './history'
import RouteConfig from './routes'

export default class App extends Component {
  render() {
    return (
      <Router history= {history}>
        <RouteConfig />
      </Router>
    )
  }
}
Copy the code

BrowserRouter or HashRouter would normally be introduced. I use this scheme for non-component JS jump hacks (used when encapsulating HTTP request interceptors).

// history.js
import { createBrowserHistory } from 'history';
const history = createBrowserHistory()

export default history
Copy the code

BaseLayout is a basic layout component that uses Suspense and lazy import() to load routes on demand (react version 16.6.0+ only supports this form)

//RouteConfig routes index.js import React, {Suspense} from'react'
import { Route, Switch } from 'react-router-dom'
import { Spin } from 'antd';
import BaseLayout from '.. /page/layout'
import Home from '.. /page/home'
import Login from '.. /page/login'
import NotFound from '.. /page/other/404'
import accounts from './accounts'
import loan from './loan'

const allRoutes = [
  ...accounts,
  ...loan
]

const Loading = () => {
  return (
    <div
      className="loading"
      style={{
        paddingTop: '50px',
        textAlign: 'center'
      }}
    >
      <Spin size="large" />
    </div>
  )
}

export default () => {
  return (
    <Switch>
      <Route path="/login" component={Login}></Route>
      <Route path="/"render={(props) => ( <BaseLayout {... props}> <Suspense fallback={<Loading />}> <Switch> <Route exact path="/" component={Home} />
              {
                allRoutes.map((route, index) => <Route path={route.path} key={index} component={route.comp} />)
              }
              <Route path="*" component={NotFound} />
            </Switch>
          </Suspense>
        </BaseLayout>
      )}></Route>
    </Switch>
  )
}
Copy the code

4 Layout Basic Layout components

To import ANTD and reference it as needed, execute the command:

npm i antd
npm i babel-plugin-import -D
Copy the code

Modify config-overrides. Js file:

const { override, fixBabelImports, addLessLoader } = require('customize-cra')
const path = require('path')

module.exports = override(
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: 'css',
  }),
  addLessLoader()
)
Copy the code

Layout master file

import React, { Component } from 'react'
import { Layout } from 'antd'
import SiderBar from './siderbar'
import MainView from './mainView'

const { Sider } = Layout

export default class BaseLayout extends Component {
  constructor() {
    super()
    this.state = {
      collapsed: false,
    }
  }
  onCollapse = (collapsed) => {
    this.setState({
      collapsed,
    })
  }
  render() {
    return (
      <Layout className="layout">
        <Sider
          width="230px"
          collapsible
          className="layout-sider"
          style={{
            position: 'fixed',
            left: '0',
            top: '0',
            bottom: '0',
            paddingTop: '10px',
          }}
          onCollapse={this.onCollapse}
        >
          <div
            className="iconfont icon-logo"
            style={{
              lineHeight: 1,
              fontSize: this.state.collapsed ? '50px' : '100px',
              color: '#fff',
              textAlign: 'center',
            }}
          ></div>
          <p
            className="layout-sider__desc"
            style={{
              paddingTop: '10px',
              whiteSpace: 'nowrap',
              color: '#fff',
              textAlign: 'center',
            }}
          >
            {this.state.collapsed ? 'jack ma' : 'Welcome, Jack Ma'}
          </p>
          <SiderBar pathname={this.props.location.pathname}></SiderBar>
        </Sider>
        <MainView collapsed={this.state.collapsed}>{this.props.children}</MainView>
      </Layout>
    )
  }
}

Copy the code

5 Encapsulate the HTTP request

In Vue, I usually mount the encapsulated HTTP request on this. In React, I just reference whatever I need

5.1 axios instance

import axios from 'axios'
import defaultConfig from './config'
import { notification } from 'antd'
import history from '.. /history'

const axiosInstance = axios.create(defaultConfig)

axiosInstance.interceptors.request.use(
  config => {
    return config
  },
  error => {
    console.log(error)
    return Promise.reject(error)
  }
)

axiosInstance.interceptors.response.use(
  response => {
    letdata = response.data ........................... . Interceptors in logic... notification.error({ message:'wrong',
        description: data.message
      })
    }
    return data
  },
  error => {
    if (error.response) {
      switch (error.response.status) {
        case 500:
          notification.error({
            message: 'wrong',
            description: 'Interface service error'
          })
          break
        case 404:
          notification.error({
            message: 'wrong',
            description: 'Interface does not exist'
          })
          break
        case 403:
          notification.error({
            message: 'wrong',
            description: 'User information expired'
          })
          history.push('/login')
          break
        case 401:
          notification.error({
            message: 'wrong',
            description: 'Login expired'
          })
          break
        default:
          notification.error({
            message: 'wrong',
            description: 'Interface cannot connect'
          })
          break}}return Promise.reject(error)
  }
)

export default axiosInstance

Copy the code

5.2 Encapsulated request functions

import axiosInstance from './axios'

export const GET = (url, params) => {
  return axiosInstance({
    method: 'get',
    url,
    params
  }).then(res => {
    return Promise.resolve(res)
  }).catch(err => {
    return Promise.reject(err)
  })
}

export const POST = (url, data) => {
  return axiosInstance({
    method: 'post',
    url,
    data
  }).then(res => {
    return Promise.resolve(res)
  }).catch(err => {
    return Promise.reject(err)
  })
}
Copy the code

5.3 API management

import { GET, POST } from '@/http'

export const doLogin = (data = {}) => {
  return POST('Backend URL', data)
}

export const getMenuData = (params = {}) => {
  return GET('Backend URL', params)
}
Copy the code

5.4 Page

. Omit the code import {getMenuData} from'@/api'

export default class Siderbar extends Component {
  constructor() {
    super()
    this.state = {
      menuTree: []
    }
  }
  componentDidMount() {this.getmenu ()} getMenu = async () => {const menus = await getMenuData() // recursive loop out of the menu const menuTree = this.renderMenu(menus) this.setState({ menuTree, }) } }Copy the code

The last

1 Configure cross-domain

When create-react-app is lower than 2.0, it can be found in package.json:

"proxy": {"/manage": {"target":"http://test.xxx.com"."changeOrigin": true}}Copy the code

For create-react-app versions later than 2.0, only string can be configured in package.json, so run the following command to install:

npm i http-proxy-middleware -D
Copy the code

Create setupproxy.js in the SRC directory

const { createProxyMiddleware } = require('http-proxy-middleware')

module.exports = function (app) {
  app.use('/api', createProxyMiddleware({
    target: 'https://test.xxx.com',
    changeOrigin: true,
    secure: false,
    pathRewrite: {
      '/api': ' '}})); };Copy the code

2 Other Configurations

To configure the alias, modify config-overrides

const { override, fixBabelImports, addWebpackAlias, addLessLoader } = require('customize-cra')
const path = require('path')

module.exports = override(
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: 'css',
  }),
  addWebpackAlias({
    [The '@']: path.resolve(__dirname, './src')
  }),
  addLessLoader()
);
Copy the code

Vue can use scoped to avoid global style contamination, while React uses objects directly in components or distinguishes between class names. To implement the CSS Module, modify the addLessLoader configuration in config-overrides

const { override, fixBabelImports, addWebpackAlias, addLessLoader } = require('customize-cra')
const path = require('path')

module.exports = override(
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: 'css',
  }),
  addWebpackAlias({
    [The '@']: path.resolve(__dirname, './src')
  }),
  addLessLoader({
    localIdentName: '[local]--[hash:base64:5]'}));Copy the code

Less and an error will be reported if the less loader version you installed is larger than 6.0