Github effect demo: react-demo

Project creation

Create a project folder

mkdir react-demo
cd react-demo
npm init -y
Copy the code

Depend on the installation

yarn add react react-dom

yarn add webpack webpack-cli webpack-dev-server webpack-merge
babel-core babel-loader babel-polyfill babel-preset-env babel-preset-react
babel-preset-stage-0 cross-env
file-loader jsx-loader
css-loader style-loader url-loader less less-loader --dev 
Copy the code

Webpack configuration

Distinguish between development environment and production environment. Create corresponding configuration files respectively. Antd-mobile loads them on demand

  • Installing a plug-in
yarn add babel-plugin-import -D
Copy the code
  • Modify the babel.config.js configuration
module.exports = {
  presets: ["@babel/preset-env"."@babel/preset-react"].plugins: [
    "@babel/plugin-transform-runtime"."@babel/plugin-proposal-class-properties"["import", { libraryName: "antd-mobile".style: true}}]].Copy the code

Externals configuration

Externals in webpack prevents certain imported packages from being packaged into bundles

modules.export = {
  plugins: [
    new HtmlWebpackPlugin({
      title: 'React Board'.files: { // Configure CDN import
        js: [
          '//unpkg.com/swiper/js/swiper.min.js'].css: [
          '//unpkg.com/swiper/css/swiper.min.css']}})],externals: {
  	swiper: 'Swiper'}}Copy the code

Index.html Settings:


      
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title><% = htmlWebpackPlugin.options.title% ></title>
  <! -- require cdn assets css -->
  <% for (var i in htmlWebpackPlugin.options.files.css) { %>
  <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.files.css[i] %>" />
  <%} % >
</head>

<body>
  <div id="root"></div>
  <! -- require cdn assets js -->
  <% for (var i in htmlWebpackPlugin.options.files.js) { %>
  <script type="text/javascript" src="<%= htmlWebpackPlugin.options.files.js[i] %>"></script>
  <%} % >
</body>

</html>
Copy the code

Use:

import Swiper from 'swiper';
Copy the code

Mobile adaptation

Use ** postCSs-loader ** to implement CSS conversion

// The project uses less
yarn add postcss-less-loader -D
Copy the code

Webpack. Base. Js configuration

{
  test: /\.(css|less)$/.use: [
      'style-loader'.'css-loader'.'less-loader'.'postcss-less-loader']}Copy the code

postcss-px-to-viewport

Use this plugin to convert all PX to VW window size

yarn add postcss-px-to-viewport -D
Copy the code

Create postcss.config.js in the project root directory

module.exports = {
  plugins: {
    "postcss-px-to-viewport": {
      viewportWidth: 375.// The width of the window corresponds to the width of our design. Iphone6 is usually 375 (xx/375*100vw).
      viewportHeight: 667.// the window height on the Iphone6 is 667
      unitPrecision: 3.// Specify the decimal number to convert 'px' to the window unit value (often not divisible)
      viewportUnit: "vw".// Specify the window unit to convert to. Vw is recommended
      selectorBlackList: ['.ignore'.'.hairlines'].// Specify a class that is not converted to Windows units. It can be customized and added indefinitely. It is recommended to define one or two common class names
      minPixelValue: 1.// less than or equal to '1px' does not convert to window units, you can also set to whatever value you want
      mediaQuery: false.// Allow conversion of 'px' in media queries
      exclude: /(node_module)/i // Ignore the UI component library}}}Copy the code

postcss-plugin-px2rem

This plugin is to convert all PX into REM size units

yarn add postcss-plugin-px2rem -D
Copy the code

Postcss. Config. Js configuration:

module.exports = {
  plugins: {
    "postcss-plugin-px2rem": {
      rootValue: 16.// Use the 750 design draft with rem.js
      unitPrecision: 5.mediaQuery: true.exclude: /(node_module)/i.selectorBlackList: ['html'.'mp-'.'calendar'.'iconfont'].// In the rem.js global effect, exclude the influence of the specified file
      propBlackList: ['border'] // Filter attributes}}}Copy the code

You need to create rem.js or download lib-Flexible directly

const viewportWidth = 750
// Base size
const baseSize = 32
// Set the rem function
function setRem() {
  // The zoom ratio of the current page width to 750 width can be modified according to your needs.
  const scale = document.documentElement.clientWidth / viewportWidth
  // Set the font size at the root of the page
  document.documentElement.style.fontSize = (baseSize * Math.min(scale, 2)) + 'px'
}
/ / initialization
setRem()
// Resets rem when changing the window size
window.onresize = function () { setRem() }
Copy the code

In the entry file introduce:

// App.js

import './utils/rem'
// import "./utils/flexible.js"
Copy the code

EsLint configuration

Install the ESLint plugin

yarn add eslint eslint-plugin-import babel-eslint eslint-plugin-react-hooks -D
Copy the code

Create the.eslintrc.js configuration file in the root directory

module.exports = {
  parser: "babel-eslint".plugins: [
    "react-hooks"].rules: {
    "react-hooks/rules-of-hooks": "error".// Check the Hook rules
    "react-hooks/exhaustive-deps": "error" // Check for effect dependencies}}Copy the code

The React routing

yarn add react-router-dom react-router-config
Copy the code

Use react-router-config to simplify route configuration. Create the routes.js file

import Home from "@/pages/Home"
import Me from "@/pages/Me"
import Test from "@/pages/Test"

console.log(typeof process.env.API)

const routes = [
  {
    path: "/home".exact: true.component: Home
  },
  {
    path: "/me".exact: true.component: Me
  },
  {
    path: "/test".exact: true.component: Test
  }
];

export default routes;
Copy the code

Import route from root file app.js:

import { renderRoutes } from 'react-router-config'
import routes from './routes'
import { HashRouter as Router } from 'react-router-dom'

import Layouts from "./components/Layouts";

function App() {
  return (
    <Router>
      <Layouts>
        {renderRoutes(routes)}
      </Layouts>
    </Router>
  )
}

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

Development of Hooks

What is a Hook? Hook is a special function that lets you “Hook” into the React feature. Hooks can only be declared in Function Component.

useState

Returns a state and a function setter that can modify the state

import React, { useState } from 'react';
import { Button } from "antd-mobile";

function User() {
  const [user, setUser] = useState('Mondo')
  return (
    <div>
      <div>{user}</div>
      <Button type="primary" onClick={e= >SetUser (' imondo. Cn)} > change the State</Button>
    </div>)}Copy the code

useEffect

Replace componentDidMount, componentDidUpdate, componentWillUnmount, etc

import React, { useState, useEffect } from 'react';

function User() {
  const [user, setUser] = useState('Mondo')
  useEffect((a)= > {
    setTimeout((a)= > {
      setUser("js.imondo.cn")},2000)
  }, [user]) // Update only when user changes
  return (
    <div>
      <div>{user}</div>
      <Button type="primary" onClick={e= >SetUser (' imondo. Cn)} > change the State</Button>
    </div>)}Copy the code

useContext

Receives a context object and returns the current value of that context. The current context value is determined by the < MyContext.provider > value prop of the upper-layer component closest to the current component. This Hook triggers rerendering when the most recent < myContext. Provider> update is made to the upper layer of the component. Can be used for value passing between components

import React, { useContext } from 'react';
const theme = {
  color: "red"
}
const UserContext = React.createContext(theme);
function User() {... return (<UserContext.Provider value={theme}>
      <Child/>
    </UserContext.Provider>
  )
}
function Child() {
  const theme = useContext(UserContext);
  return (
    <div style={{color: theme.color}} >context</div>)}Copy the code

useMemo

UseMemo (() => fn, deps) passes the “create” function and an array of dependencies as arguments to useMemo, which recalcates memoized values only when a dependency changes. This optimization helps avoid costly calculations every time you render. Can be used as a calculated property in vUE

import React, { useState, useMemo } from 'react';
import { Button  } from "antd-mobile";

function User() {
  const [user, setUser] = useState(1)
  /* Cache calculated attributes */
  const data = useMemo((a)= > ({
    users: (user + 1)
  }), [user]);
	 const onChangeUser = (e) = > {
    setUser(+e.target.value);
  }
  return( <UserContext.Provider> <input value={user} onChange={onChangeUser}/> <div>{data.users}</div> <Button type="primary" OnClick ={e => setUser(user + 1)}> Change State</Button> </ usercontext.provider >)}Copy the code

useReducer

Const [state, dispatch] = useReducer(Reducer, initialArg, init) It is an alternative to useState and is used in some scenarios:

  • The state logic is complex and contains multiple child values
  • The next state depends on the previous state

The most important thing is that it’s written like **redux **

import React, { useReducer } from "react";
import { Button  } from "antd-mobile";
let initCount = 0;
function reducer(state = initCount, action) {
  switch (action) {
    case "increment":
      state++
      return state
    case "decrement":
      state--
      return state      
    default:
      throw new Error();
  }
}
function User() {
  const [count, disaptch] = useReducer(reducer, initCount)
  return (
    <UserContext.Provider value={theme}>
      <div>useReducer</div>
      <div>Counter {count}</div>
      <Button type="primary" onClick={e= >Disaptch (" decrement ")} ></Button>
      <Button type="primary" onClick={e= >> add disaptch (" increment ")}</Button>
    </UserContext.Provider>)}Copy the code

useRef

Return a mutable ref object whose.current property is initialized as the parameter passed in. If you want to access a REF object within a child component, the child component needs to declare the component with class.

import React, { useState, useMemo, useRef } from 'react';

function Parent() {
  let [count, setCount] = useState(0)
  const childRef = useRef(null)
  const childClick = (val) = > {
    childRef.current.setState({
      num: 2
    });
  }
  return (
    <div>
      <h4>Components by value</h4>
      <button onClick={childClick}>Pass values to child components</button>
      <Child1 ref={childRef} />
    </div>); } class Child1 extends React.Component { constructor() { super(... arguments); this.state = { num: 1 } } render() { const { num } = this.state; return (<div>
        <div>Ref components</div>
        <div>{num}</div>
      </div>)}}Copy the code

Remember to read before writing React Hooks


Welcome to pay attention to the public number, we communicate and progress together.