Front-end framework React learning summary

Table of contents

1. The application of React in HTML

2. Common operations of React framework

project packaging

1. Basic grammar rules of JSX

2. Use of state data

3. Life cycle

4. Two-way binding of data and Ref

5. PropTypes validation rules

6. Slots in React

7. Error boundaries

8. Direct manipulation of refs elements

9. Application cases of high-level components

10. Performance optimization

11. The use of Hook life cycle hooks

12. Computed properties in React

3. Passing values ​​between components

1. Pass value between parent and child components

2. Pass value from child to parent

3. Context realizes cross-level communication

context hook case

Fourth, the use of network request framework

Five, the use of React routing

Declarative Navigation

programmatic navigation

programmatic jump

6. The use of Anti Desgin to realize the UI interface

Seven, the use of Redux central warehouse

1. Create a new src/redux/index.js file for storing redux

2. Introduce in src/index.js

3. You can view redux logs through logger

4. Modular management of Redux

5. Precautions

6. Summarize the complete steps of using Redux


1. The application of React in HTML

The core of using React in HTML is to import 3 dependencies:

<!--React核心库-->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<!--React-dom用于支持react操作DOM-->
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!--引入babel用于将jsx转为js-->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

The case code is as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
<div id="root"></div>
</body>
<!--React核心库-->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<!--React-dom用于支持react操作DOM-->
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!--引入babel用于将jsx转为js-->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!--这里一定要用这个type,让babel翻译script标签中的代码-->
<script type="text/babel">
    //1、创建虚拟Dom
    // 方式一  JSX
    const VDOM = (
        <h1 id="title">
            <span>Hello,React</span>
        </h1>
    )
    //方式二 js语法创建DOM
    // const VDOM=React.createElement("h1",{id:"title"},React.createElement("span",{},"Hello,React"))

    //2、将虚拟DOM转成真实DOM,并插入页面
    ReactDOM.render(VDOM, document.getElementById("root"))
</script>
</html>

running result:

The execution process is as follows:

2. Common operations of React framework

Scaffold creation:

Check the official website for usage details, here are just my notes: React Official Chinese Documentation – A JavaScript library for building user interfaces

npx create-react-app projectName

project packaging

 When packaging, you need to add the attribute "homepage": "./" to package.json for path correspondence.

1. Basic grammar rules of JSX

Case code: the object object cannot perform rendering, and arr can be traversed and output through the map function.

import React from 'react';
 function App () {
     const num=16
     const bool=true
     const name="string"
     const arr=[1,2,3,4,"Jack",true]
     const obj={name:"Mary",age:12}
     
     return(
         <div style={
   
   {marginLeft:"20px"}}>
             <div>num:{num}</div>
             <div>bool:{bool}</div>
             <div>name:{name}</div>
             <div>arr:{arr}</div>
             <div>arr遍历: {
                 arr.map((item,index)=>(
                     <p key={index}><span color={"red"}>{item}</span></p>
                 ))
             }</div>
             {/*对象不能直接打印*/}
             {/*<div>obj:{obj}</div>*/}
             <div>obj.name:{obj["name"]}</div>
         </div>
     )
 }

 export default App;

Effect:

2. Use of state data

Reference document: State & Lifecycle – React

3. Life cycle

Sending network requests is generally executed in componentDidMount,

Destroying component overhead is generally performed in componentWillUnmount.

4. Two-way binding of data and Ref

method one: 

class Test extends Component {
    
    constructor (props, context) {
        super(props, context)
        this.state={
            val: "233"
        }
    }
    
    changeVal=(e)=>{
        console.log(e)
        this.setState({
            val: e.target.value
        })
        console.log(e.target.value)
    }
    
    render () {
        return (
            <div>
                <input type="text" onChange={this.changeVal} value={this.state.val} />
            </div>
        )
    }
}

Method 2: Realize through ref

class Test extends Component {
    
    constructor (props, context) {
        super(props, context)
        this.state={
            val: "233"
        }
        //1、在构造函数里创建ref的语法
        this.myRef=React.createRef()
    }
    
    search=()=>{
        //3、获取DOM元素
        console.log(this.myRef.current.value)
    }
    
    render () {
        return (
            <div>
                {/*2、绑定到元素上去*/}
                <input type="text" ref={this.myRef} onChange={this.search}/>
            </div>
        )
    }
}

Operation reference of refs:

Refs and the DOM – React

5. PropTypes validation rules

reference:

Type checking with PropTypes – React

6. Slots in React

reference:

Composition vs Inheritance – React

7. Error boundaries

Avoid rendering nothing at all

Reference: Error Boundaries – React

8. Direct manipulation of refs elements

Use in function components:

Reference: Refs Forwarding – React

9. Application cases of high-level components

Reference: Higher Order Components – React

Realize the reuse of component loading time

import React from "react"

export default function showTime (Comp) {
    return class extends React.Component {
        constructor (props, context) {
            super(props, context)
            this.state = {
                startTime: new Date().getTime(),
                loadingTime: 0
            }
        }
        
        componentDidMount () {
            let endTime = new Date().getTime()
            this.setState({
                loadingTime: endTime - this.state.startTime
            })
        }
        
        render () {
            return (
                <Comp loadingTime={this.state.loadingTime}/>
            )
        }
    }
}

In this way, the reuse of high-level components is realized. When you need to use this function, you only need to call the function object to add the function.

10. Performance optimization

Reference: Performance Optimization – React

1. After the new version, Component uses PureComponent,

PureComponent has its own state and props checks, but rewrites the rendering when there is a change, otherwise it does not re-render to improve performance.

Optimization in function components: equivalent to pureComonent

React.memo() life cycle hook, equivalent to pureCompnent will only update when props and state changes.

Case code:

import React from "react"

const componentTwo = React.memo((props) => {
    return (
        <div>
        
        </div>
    )
})

export default componentTwo

2. Remember to release resources after components are used up

11. The use of Hook life cycle hooks

Reference: Hook API Index – React

The efficiency of using function components is generally higher than that of class components, but there are no properties such as state in function components (stateless components), so Hook was born here to add elements such as state and life cycle to function components.

Introduction to Hooks – React

Case 1: useState to modify the state

import React,{useState} from "react"

function FunComponentOne () {
    //定义一个变量,初始值为0,可通过setCount方法修改值
    //第一个位置变量名,第二个位置方法名:修改变量的方法
    const [count,setCount]=useState(0)
    
    return (
        <div>
            <h2>{count}</h2>
            <button onClick={()=>setCount(count+1)}>+</button>
        </div>
    )
}

export default FunComponentOne

Case 2: useEffect life cycle hook

import React,{useState,useEffect} from "react"

function FunComponentOne () {
    
    //定义一个变量,初始值为0,可通过setCount方法修改值
    //第一个位置变量名,第二个位置方法名
    const [count,setCount]=useState(0)
    
    //第二个参数为空,相当于生命周期钩子:componentDidMount+componentDidUpdate
    //加载完成和数据修改都会走该函数
    useEffect(() => {
        console.log("=======================")
    })
    
    //第二个参数为空数组[],相当于componentDidMount,可以用于网络请求
    useEffect(() => {
        console.log("++++++++++++++++++++++++++++")
    }, [])
    
    //第二个参数可以传入有值的数组,当数组里的变量修改,会调用该函数
    useEffect(() => {
        console.log("!!!!!!!!!!!!!!!!!!!!!!!!!")
    }, [count])
    
    //当第二个参数为空数组[],且有返回函数时相当于componentWillUnMount
    //一般用于销毁主键
    useEffect(() => {
        return function clearUp(){
            console.log("clearUp")
        }
    },[])
    
    
    return (
        <div>
            <h2>{count}</h2>
            <button onClick={()=>setCount(count+1)}>+</button>
        </div>
    )
}

export default FunComponentOne

Case 3: Hook reducer is similar to the upgraded version of useState

Reference: Hook API Index – React

Case 4: Custom Hook reduces coupling

Reference: Custom Hook - React

You can define frequently called hooks into your own hooks, pay attention to start with use

12. Computed properties in React

Equivalent to Computed in Vue

3. Passing values ​​between components

1. Pass value between parent and child components

The way to pass parameters through components:

<ChildOne num={12}/>
<ChildTwo num={24}/>

Subcomponents receive parameters:

class ChildTwo extends Component {
    render () {
        return (
            <div>
                <h2>我是子组件ChildTwo: {this.props.name}</h2>
            </div>
        )
    }
}

function ChildOne (prop) {
     return(
         <div>
             <h2>ChildOne子组件:{prop.num}</h2>
         </div>
     )
}

2. Pass value from child to parent

Pass the method object to the child component through the parent component, and the child component calls the method and passes in the corresponding parameters and processing to the parent component.

parent component:

function ParentOne () {
    function getSonData (data) {
        console.log(data)
    }
    
    return (
        <div>
            <ChildThree getSonData={getSonData} />
        </div>
    )
}

Subassembly:

 function ChildThree (prop) {
     function sendData(){
         prop.getSonData("我是子组件的数据")
     }
     return(
         <div>
             <button onClick={sendData}>点击向父组件传值</button>
         </div>
     )
 }

Here, the parent component passes the getSonData method object to the child component first. After the child component gets the method object, it can call it through prop and pass in the parameters of the child component to the method. At this time, the method in the parent component will be called to get the child component. The data.

3. Context realizes cross-level communication

Reference: Context - React

 (1) First, create a MyContext.js to manage context environment variables

import React from "react"
//创建中间仓库
const MyContext=React.createContext(undefined)

export default MyContext

(2) Case

The first layer of parent components, providing data

class LayerOne extends Component {
    
    constructor (props, context) {
        super(props, context)
        this.state={
            name: "cute Tom"
        }
    }
    
    render () {
        return (
            <div>
                <h1>我是one</h1>
                <MyContext.Provider value={this.state}>
                    <LayerTwo/>
                </MyContext.Provider>
            </div>
        )
    }
}

The second layer: contains the third layer

class LayerTwo extends Component {
    render () {
        return (
            <div>
                <h2>我是two</h2>
                <LayerThree/>
            </div>
        )
    }
}

The third layer can directly consume data. Note that you need to declare which MyContext it is

class LayerThree extends Component {
    render () {
        return (
            <div>
                <h3>我是three</h3>
                <MyContext.Consumer>
                    {value => <div><h2>{value.name}</h2></div>}
                </MyContext.Consumer>
            </div>
        )
    }
}

LayerThree.contextType=MyContext

Effect:

context hook case

Use in function components: Context Hook

Link: useContext - Short Book 

Fourth, the use of network request framework

See my blog:

Front-end framework network requests Fetch Axios_Dragon Wu's Blog-CSDN Blog

Five, the use of React routing

Official documentation: React Router: Declarative Routing for React.js

reference:

React Router 6 (React Routing) The most detailed tutorial - Alibaba Cloud Developer Community

6.v new features:

Summary of new features of react-router 6

First install dependencies:

yarn add react-router-dom@6

Declarative Navigation

(It is recommended to use programmatic navigation for higher efficiency)

Case code: generally use BrowseRouter with history records

import React, { Component } from "react"
import { BrowserRouter, Routes, Route, Navigate, NavLink, useParams,Link,Outlet } from "react-router-dom"

class Home extends Component {
    render () {
        return (
            <div>
                <h1>Home</h1>
            </div>
        )
    }
}

class About extends Component {
    render () {
        return (
            <div>
                <h1>About</h1>
            </div>
        )
    }
}

function Detail () {
    
    console.log(useParams())
    return (
        <div>
            <h2>详情</h2>
            <p>id: {useParams().id}</p>
        </div>
    )
}

function Main(){
    return (
        <div>
            <h1>文档</h1>
            <Link to={"/doc/one"}>文档1</Link>
            <Link to={"/doc/two"}>文档2</Link>
            <Link to={"/doc/three"}>文档3</Link>
            {/*嵌套路由时注意书写这个标签*/}
            <Outlet/>  {/* 指定路由组件呈现的位置 */}
        </div>
    )
}

function App () {
    
    return (
        <div>
            <BrowserRouter>
                <div>
                    <NavLink to={"/home"}>首页</NavLink>|
                    <NavLink to={"/about"}>关于</NavLink>|
                    <NavLink to={"/detail/123"}>详情</NavLink>|
                    <NavLink to={"/doc"}>文档</NavLink>
                </div>
                <Routes>
                    <Route path={"/home"} element={<Home />} />
                    <Route path={"/about"} element={<About />} />
                    {/*嵌套路由*/}
                    <Route path={"doc"} element={<Main/>}>
                        <Route path={"one"} element={<h3>one</h3>} />
                        <Route path={"two"} element={<h3>two</h3>} />
                        <Route path={"three"} element={<h3>three</h3>} />
                    </Route>
                    {/*动态路由*/}
                    <Route path={"/detail/:id"} element={<Detail />} />
                    {/*路由重定向,也可用于404处理*/}
                    <Route path="/*" element={<Navigate to="/home" replace />} />
                    {/*404处理*/}
                    <Route path="*" element={<NotFound />} />
                </Routes>
            </BrowserRouter>
        </div>
    )
}

export default App

// 用来作为 404 页面的组件
const NotFound = () => {
    return <div>你来到了没有知识的荒原</div>
}

programmatic navigation

(1) Create a new src/router/index.js file

import { Navigate } from "react-router-dom"
import Home from "../page/home/Home"
import HomeLeft from "../page/home/HomeLeft"
import HomeRight from "../page/home/HomeRight"
import About from "../page/About"
import Detail from "../page/Detail"
const routes=[
    {
        path: "/",
        element: <Navigate to="/home" />
    },
    {
        path: "home",
        element: <Home />,
        children: [
            {
                index: true,
                element: <HomeLeft />
            },
            {
                path: "right",
                element: <HomeRight />
            }]
    },
    {
        path: "/about",
        element: <About />
    },
    {
        path: "/detail",
        element: <Detail />
    },
    { path: "*", element: <p>404页面不存在</p> }
]
export default routes

(2) Add BrowserRouter container for src/index.js

Note: BrowserRouter must be in the outer layer of the App tag

 (3) App.js is as follows:

import React from 'react'
import routes from "./router/index.js"
import {useRoutes,NavLink } from "react-router-dom"

 function App () {
     // useRoutes可以用路由表生成<Routes>...</Routes>结构
     // 根据路由表生成对应的路由规则
     const element = useRoutes(routes)
     
     return(
         <div id="App">
             <div>
                 <NavLink to={"/home"} >首页</NavLink>|
                 <NavLink to={"/about"}>关于</NavLink>|
                 <NavLink to={"/detail"}>详情</NavLink>
             </div>
             <div>
                 {element}
             </div>
         </div>
     )
 }

 export default App
(4) If there are nested routes, use the <Outlet/> tag to indicate where the subcomponent is inserted
class Home extends Component {
    render () {
        return (
            <div>
                <h1>Home</h1>
                <Link to={"/home/right"}>homeRight</Link>
                <Link to={"/home"}>homeLeft</Link>
                {/*嵌套路由时注意书写这个标签*/}
                <Outlet/>  {/* 指定路由组件呈现的位置 */}
            </div>
        )
    }
}

programmatic jump

default is push mode

export default function HomeNews() {
  const navigate = useNavigate();
  const jump = ()=>{
    navigate('/home')
  }
  return (
      <News>
        <button onClick={jump}>点击跳转</button>
      </News>
  )
}

Use {replace:true} will become replacethe mode

navigate('/home', { replace: true });

You can also use  navigate(-1) a number to jump

navigate(1)//传入数字

6. The use of Anti Desgin to realize the UI interface

Official documentation: Ant Design - A UI Design Language

1. Add to project:

yarn add antd

2. Style introduction

Globally reflect styles: import styles in src/index.js, not recommended, will import a lot of useless styles

import 'antd/dist/antd.css';  // or 'antd/dist/antd.less'

on demand, recommended

The following two methods can only load the components used.

  • Use  babel-plugin-import (recommended).

  • yarn add babel-plugin-import
    // .babelrc or babel-loader option
    {
      "plugins": [
        ["import", { "libraryName": "antd", "style": "css" }] // `style: true` 会加载 less 文件
      ]
    }

  • Then just import the module from antd, no need to import styles separately. It is equivalent to the way of manual introduction below.

    // babel-plugin-import 会帮助你加载 JS 和 CSS
    import { DatePicker } from 'antd';
  • Manual import

    import DatePicker from 'antd/lib/date-picker';  // 加载 JS
    import 'antd/lib/date-picker/style/css';        // 加载 CSS
    // import 'antd/lib/date-picker/style';         // 加载 LESS

3. It can be called directly in the component

Seven, the use of Redux central warehouse

When our project is a little more complicated, the native state may not be able to efficiently manage and operate the data cache, and Redux can manage the data in a unified manner and reduce code coupling.

Reference: Getting started with Redux | Redux Chinese official website

 It works similar to hook reducer

yarn add @reduxjs/toolkit

Installation reference: Installation | Redux Chinese official website

1. Create a new src/redux/index.js file for storing redux

//1、引入redux
import { configureStore } from "@reduxjs/toolkit"

//2、创建仓库
const store = configureStore({reducer})

//3、reducer为store服务的执行者, action={type:"",data:5}
function reducer (preState = 10, action) {
    switch (action.type) {
        case "add":
            return preState + action.data
        case "sub":
            return preState - action.data
        default:
            return preState
    }
}

//4、使用store
console.log(store)
//获取仓库的数据
console.log(store.getState())
//触发action
store.dispatch({
    type: "add",
    data: 5
})
console.log(store.getState())

2. Introduce in src/index.js

Running result: You can see that the data has been manipulated

3. You can view redux logs through logger

yarn add redux-logger

After adding logger:

//1、引入redux
import { configureStore } from "@reduxjs/toolkit"
//引入日志
import { logger } from "redux-logger/src"

//2、创建仓库
// const store = configureStore({reducer})
const store = configureStore({
    reducer,
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger)
})

//3、reducer为store服务的执行者, action={type:"",data:5}
function reducer (preState = 10, action) {
    switch (action.type) {
        case "add":
            return preState + action.data
        case "sub":
            return preState - action.data
        default:
            return preState
    }
}

//4、使用store
console.log(store)
//获取仓库的数据
console.log(store.getState())
//触发action
store.dispatch({
    type: "add",
    data: 5
})
console.log(store.getState())

You can see the print of the log:

Combine multiple reducers 

//1、引入redux
import { configureStore} from "@reduxjs/toolkit"
//引入日志
import { logger } from "redux-logger/src"

//2、创建仓库
// const store = configureStore({reducer})
const store = configureStore({
    //合并多个reducer
    reducer:{
        reducer,
        reducer2
    },
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger)
})

//3、reducer为store服务的执行者, action={type:"",data:5}
function reducer (preState = 10, action) {
    switch (action.type) {
        case "add":
            return preState + action.data
        case "sub":
            return preState - action.data
        default:
            return preState
    }
}

function reducer2 (preState = { user: "", num: 5 }, action) {
    const { type, data } = action
    let newState = { ...preState }
    switch (type) {
        case "addUser":
            newState.user = data.user
            return newState
        case "delUser":
            newState.user = ""
            return newState
        default:
            return newState
    }
}

//4、使用store
console.log(store)
//获取仓库的数据
console.log(store.getState())
// //触发action
store.dispatch({
    type: "add",
    data: 5
})
console.log(store.getState())

store.dispatch({
    type: "addUser",
    data: {
        user: "大猫"
    }
})

store.dispatch({
    type: "delUser"
})

operation result:

4. Modular management of Redux

When writing a project, we need to add a namespace to avoid duplication:

In addition, we also need to extract the constants into a file for management:

Category management reducers:

 reducer/index.js: import all reducers for easy calling

import { count } from "./countReducer"
import {user} from "./userReducer"

export const reducers={
    count,
    user
}

redux/index.js imports the index file of the reducer:

//1、引入redux
import { configureStore} from "@reduxjs/toolkit"
//引入日志
import { logger } from "redux-logger/src"

//引入reducers
import { reducers } from "./reducers"

//2、创建仓库
// const store = configureStore({reducer})
const store = configureStore({
    //合并多个reducer
    reducer: reducers,
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger)
})

5. Precautions

Return value note:

It is best to follow the logic of this format when writing:

Redux does not support asynchronous operations by default. The general implementation idea is to perform redux operations when synchronously callback after the asynchronous task is completed:

6. Summarize the complete steps of using Redux

Installation dependencies:

yarn add @reduxjs/toolkit

yarn add react-redux

Log dependencies:

yarn add redux-logger

(1) Create a store warehouse, and reducers are managed separately

reducers: In data development, the type string should be put into a constant management

export function count(preState={num:0},action){
    const {type,data}=action
    let newState={...preState}
    switch (type) {
        case "num/add":
            newState.num+=data.num
            return newState
        case "num/sub":
            newState.num-=data.num
            return newState
        default:
            return newState
    }
}
export function user(preState={user:{name:"",age:1}},action){
    const {type,data}=action
    let newState={...preState}
    switch (type) {
        case "user/update":
            newState.user=data.user
            return newState
        case "user/delete":
            newState.user={name:"",age:1}
            return newState
        default:
            return newState
    }
}

Index all reducers:

import { count } from "./countReducer"
import { user } from "./userReducer"

export const reducers = {
    count,
    user
}

Create a store warehouse and enable logging:

//1、引入redux
import { configureStore } from "@reduxjs/toolkit"
//引入日志
import { logger } from "redux-logger/src"

//导入reducers
import { reducers } from "./reducers"

//2、创建仓库
// const store = configureStore({reducer})
const store = configureStore({
    //合并多个reducer
    reducer: reducers,
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger)
})


export default store

(2) Import to src/index.js file, global configuration

(3) Use in components

import React from "react"
import { connect } from "react-redux"

function ReduxTestComp (props) {
    return (
        <div>
            <h1>count: {props.count.num}</h1>
            <h1>user:{props.user.user.age},{props.user.user.name}</h1>
            <button onClick={()=>props.updateUser({user:{ name: "Jack", age: 12 }})}>修改用户</button>
            <button onClick={()=> props.deleteUser()}>删除用户</button>
            <button onClick={()=>props.addNum()}>+</button>
        </div>
    )
}

export default connect((state) => {//读取仓库中所有state
    console.log(state)
    return {
        count: state.count,
        user: state.user
    }
}, (dispatch) => {//action操作
    console.log(dispatch)
    return {
        updateUser: (data) => {
            return dispatch({ type: "user/update", data: data })
        },
        deleteUser: ()=>{
            return dispatch({type:"user/delete"})
        },
        addNum:()=>{
            return dispatch({type:"num/add",data:{num:12}})
        }
    }
})(ReduxTestComp)
import React from "react"
import ReduxTestComp from "./component/reduxTest/ReduxTestComp"

function App () {
    
    return (
        <div id="App">
            <ReduxTestComp />
        </div>
    )
}

export default App

So far, the full application of redux has been realized.

Guess you like

Origin blog.csdn.net/qq_50909707/article/details/127847618