Used by the React Hooks child component

Get children from the argument and render directly with {children}

Webpack enables the CSS Module

module:{
    rules:{
        {
        test: /\.(sa|sc)ss$/,
        exclude: /node_modules/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              reloadAll: true,
              esModule: true,
              modules: {
                namedExport: true,
              },
            }
          },
          {
            loader: "css-loader",
            options: {
              modules: {
                localIdentName: '[name]__[local]--[hash:base64:5]',
                exportGlobals: true,
                namedExport: true,
              },
            }
          },
          {
            loader: 'postcss-loader'
          },
          {
            loader: 'sass-loader',
          },
        ]
      },
    
    }
}
Copy the code

Using CSS module

import * as style from "./index.module.scss"

<div className={style.container}/>
Copy the code

Commit the canonical

Commitizen use

Commitizen is a tool for writing qualified Commit messages

npm install -g commitizen
Copy the code

Use in the project directory:

commitizen init cz-conventional-changelog --save --save-exact
Copy the code

Use git cz instead of git commit

Generate the changelog:

$ npm install -g conventional-changelog-cli
$ cd my-project
$ conventional-changelog -p angular -i CHANGELOG.md -s
Copy the code

Mobile fit problem

Flexible huawei mobile phone may have various style issues, cooperate with React use postCSS-pxtoREM conversion REM

Width, height, spacing with percentages as far as possible

Add wechat restrictions

export const addWeixinLimit = () = > {
  if (process.env.NODE_ENV === 'production') {
    let ua = navigator.userAgent.toLowerCase();
    let isWeixin = ua.match(/micromessenger/i) = ='micromessenger' && (ua.match(/wxwork/i) != 'wxwork');
    if(! isWeixin) {document.head.innerHTML = '< title > I'm sorry, 
      
       < link rel =" stylesheet "type =" text/CSS "href =" https://res.wx.qq.com/open/libs/weui/0.4.1/weui.css "> ';
      document.body.innerHTML = '
      

Please open the link on wechat client

'
; }}}Copy the code

Configure the react – hot – loader

After installation, add in the.babelrc file

    "plugins": [["react-hot-loader/babel"]]Copy the code

Wrap the App root component in the index.js file


import { hot } from 'react-hot-loader/root';

const HotApp = hot(
  () = > <Provider store={store}>
    <App />
  </Provider>
)

ReactDOM.render(
  <HotApp />.document.getElementById('root'));Copy the code

The react to the router configuration

Configure the asynchronous load routing component and create an AsyncComponent

import React, { Component } from "react";

export default function asyncComponent(importComponent) {
  class AsyncComponent extends Component {
    constructor(props) {
      super(props);

      this.state = {
        component: null
      };
    }

    async componentDidMount() {
      const { default: component } = await importComponent();

      this.setState({
        component: component
      });
    }

    render() {
      const C = this.state.component;

      return C ? <C {. this.props} / > : null; }}return AsyncComponent;
}
Copy the code

Introduced in route.js

import AsyncComponent from '@/components/common/AsyncComponent'
const Home = AsyncComponent(() = > import('@/pages/Home'))
Copy the code

Page routing resets the scroll bar to the top

Create the ScrollToTop.js component

import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'

class ScrollToTop extends Component {
  componentDidUpdate(prevProps) {
    if (this.props.location.pathname ! == prevProps.location.pathname) {window.scrollTo(0.0); }}render() {
    return this.props.children; }}export default withRouter(ScrollToTop);
Copy the code

Wrap a layer of route during route rendering

import ScrollToTop from "@/utils/ScrollToTop.js"
function RenderRouters({ routes }) {
  return routes.map((item) = >
    <ScrollToTop
      key={item.name}
    ><Route
        path={item.path}
        render={()= > (<item.component />)
        } />
    </ScrollToTop>)}Copy the code

Embedded routines by

<Switch>
    <Redirect exact from='/score' to='/score/step' />
    <Route path="/score/step"/>
<Switch/>
Copy the code

Remember not to use exact matching of nested routines, otherwise you will find no sub-routes

Configuration redux

Create types

export default {

  /* * Loading status * COMMON * Loading Begins * Loading ends * */
  LOADING_START: 'LOADING_START'.LOADING_END: 'LOADING_END'.// Get forum data
  FETCH_FORUM: 'FETCH_FORUM'
}
Copy the code

Create the actions

import commonTypes from "@/store/types/common"
import { getForumData } from "@/api/common"
export function startLoading() {
  return {
    type: commonTypes.LOADING_START,
  }
}

export function endLoading() {
  return {
    type: commonTypes.LOADING_END,
  }
}


// Get forum information
export function getForum() {
  return (dispatch) = > {
    return getForumData().then((res) = > {
      dispatch({
        type: commonTypes.FETCH_FORUM,
        payload: res.data
      })
      return res.data
    })
  }
}
Copy the code

Create the reducer

import commonTypes from "@/store/types/common"
const initialState = {
  isLoading: false.forumData: {}};function commonReducer(state = initialState, action) {
  switch (action.type) {
  case commonTypes.LOADING_START:
    return {
      ...state,
      isLoading: true};case commonTypes.LOADING_END:
    return {
      ...state,
      isLoading: false};case commonTypes.FETCH_FORUM:
    return {
      ...state,
      forumData: action.payload
    };

  default:
    return state
  }
}

export default commonReducer;
Copy the code

Integration of the reducer

import { combineReducers } from 'redux'

import common from './common'
import user from './user'
export default combineReducers({
  common,
  user
})
Copy the code

Create the store

import { createStore, compose, applyMiddleware } from 'redux'
import reducer from './reducers'
import thunk from 'redux-thunk'
const configureStore = (preloadedState) = > createStore(
  reducer,
  preloadedState,
  compose(
    applyMiddleware(thunk),
  )
)
export default configureStore()
Copy the code

The root node passes in store

import { Provider } from 'react-redux'
import store from '@/store'

<Provider store={store}>
    <App />
</Provider>
Copy the code

Introduce use through CONNECT

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as CommonAction from '@/store/actions/common';

class App extends Component {
  componentDidMount() {
    console.log(this.props)
    let token = LocalStorageUtil.get('token')}render() {

    const { isLoading } = this.props;
    const renderContent = (<BrowserRouter>
      <Fragment>
        <Route exact path="/" render={()= > (
          <Redirect to="/home" />)} / ><RenderRouters routes={routes}></RenderRouters>
      </Fragment>
    </BrowserRouter>)
    return (
      <div className="App">
        {
          isLoading
            ? (<ActivityIndicator
              toast
              text="Loading..."
              animating={isLoading}
            />)
            : renderContent
        }
      </div>)}}const mapStateToProps = (state, props) = > ({
  isLoading: state.common.isLoading,
})

const mapDispatchToProps = (dispatch) = > ({
  ...bindActionCreators(CommonAction, dispatch)
})

export default (connect(mapStateToProps, mapDispatchToProps)(App));
Copy the code

Introduced via React hooks

import { useDispatch, useSelector } from "react-redux";
import { getForum } from "@/store/actions/common"

const { formData } = useSelector(state= > state.user)
const dispatch = useDispatch()

dispatch(getForum())
Copy the code

Configure webPack packaging optimization

Configuration HtmlWebpackPlugin

new HtmlWebpackPlugin({
    filename: utils.resolve('.. /dist/index.html'),
    template: 'public/index.html'.inject: true.hash: true.minify: {
        removeComments: true.collapseWhitespace: true.removeAttributeQuotes: true}}),Copy the code

Configure splitChunks, JS compression, and CSS compression

    optimization: {
        minimize: true.minimizer: [
            new TerserPlugin({ Js / / compression
                parallel: true
            }),
            / / compress CSS
            new OptimizeCSSAssetsPlugin({
                cssProcessorOptions: {
                    discardComments: { removeAll: true } // Remove comments}}),].splitChunks: {
            chunks: "async".minSize: 30000.minChunks: 1.maxAsyncRequests: 5.maxInitialRequests: 3.automaticNameDelimiter: '~'.name: true.cacheGroups: {
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    priority: -10
                },
                default: {
                    minChunks: 2.priority: -20.reuseExistingChunk: true}}}}Copy the code

Use antD-Mobile + RC-form

Using InputItem

import { InputItem, Toast, Modal } from 'antd-mobile';
import { createForm } from 'rc-form';
const { getFieldProps, getFieldValue, validateFields, getFieldError } = props.form;


<InputItem
        {. getFieldProps('phone'{initialValue: formData.phone.rules: [{ required: true.message:'Please enter mobile phone number'}, {validator: (rule.value) = >IsPhoneNumber (value.replace(/\s+/g, "")), message: 'please input the appropriate phone number'}]})} type="phone" placeholder=" please input the appropriate phone number "><span className={style.formText}>Mobile phone number<span className={style.required}>*</span></span></InputItem>
Copy the code

Use validateFields for validation

validateFields(async (error, value) => {
      for (const key of Object.keys(value)) {
        if (error && error[key] && error[key].errors.length > 0) {
          for (const err of error[key].errors) {
            Toast.fail(err['message'])
            return; }}}})Copy the code

If you use CSS Modules, change the default style with :global global injection

:global {
  .am-list-item{
    background-color:transparent! important; }}Copy the code

conclusion

This project was to build react from scratch. During the building process, I reviewed webpack again and learned some skills of React configuration, so as to get better acquainted with React