Table of contents
1. The application of React in HTML
2. Common operations of React framework
4. Two-way binding of data and Ref
8. Direct manipulation of refs elements
9. Application cases of high-level components
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
Fourth, the use of network request framework
Five, the use of React routing
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
3. You can view redux logs through logger
4. Modular management of Redux
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:
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.
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 replace
the 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.