Contents of this document:
- 1. React entrance
- 2. JSX syntax
- 3. Components
- 4. Use setstate correctly
- 5. Life cycle
- 6. Component composition
- 7.redux
- 8.react-redux
- 9.react-router
- 10.PureComponent
- 11. Know hook
- 12. Customize hook and hook usage rules
- 13. Usememo and usecallback of hook API
Reference website:https://zh-hans.reactjs.org/docs/getting-started.html
1. React entrance
start
- Create project: NPX create react app my app
- Open project: CD my app
- Start project: NPM start
- Configuration item: NPM run eject
Note: exposing configuration items is irreversible
CRA file structure
├── README. MD document
Public - public static resources
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└ - SRC source code
├── App.css
├── App. JS root component
├── App.test.js
├── index. CSS global style
├── index. JS entry file
├── logo.svg
└── serviceWorker. JS PWA support
├── package. JSON NPM dependency
Entry file definition, webpack config. js
entry: [
//Webpackdevserver client, which realizes the hot update function during development
isEnvDevelopment &&
require.resolve('react-dev-utils/webpackHotDevClient'),
//Application entry: Src / index
paths.appIndexJs,
].filter(Boolean),
webpack. config. JS is a webpack configuration ⽂ file. The constant statement at the beginning shows that CRA can support ts, sass and CSS modularization.
// Check if TypeScript is setup
const useTypeScript = fs.existsSync(paths.appTsConfig);
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
React and reactdom
Delete all the codes under SRC and create a new index js。
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(<h1>Hello React</h1>, document.querySelector('#root'));
React is responsible for logic control, data – > vdom
Reactdom renders the actual DOM, vdom – > dom
React uses JSX to describe the UI
Babel loader compiles JSX into corresponding JS objects, react CreateElement then constructs the JS object into the virtual DOM required by react.
2. JSX syntax
JSX is a syntax extension of JavaScript. Its format is more like a template language, but in fact it is completely implemented inside JavaScript.
JSX can well describe the UI and effectively improve the development efficiency,
2.1. Basic use
Use of expression {}, index js
const name = "react study";
const jsx = <div>hello, {name}</div>;
2.2. function
Function is also a legal expression, index js
const obj = {
fistName: "Harry",
lastName: "Potter"
};
function formatName(name) {
return name.fistName + " " + name.lastName;
}
const jsx = <div>{formatName(user)}</div>;
2.3. object
JSX is a JS object and a legal expression, index js
const greet = <div>good</div>;
const jsx = <div>{greet}</div>;
2.4. Conditional statement
Conditional sentences can be realized based on the above conclusion, index js
const show = true;//false;
const greet = <div>good</div>;
const jsx = (
<div>
{/ * conditional sentence * /}
{show? Greet: "login"}
{show && greet}
</div>
);
2.5. array
The array is treated as a set of child elements, and a set of JSX is stored in the array, which can be used to display the list data
const a = [0, 1, 2];
const jsx = (
<div>
{/ * array * /}
<ul>
{/ * diff, ⾸ first ⽐ compare the type, and then the key. Therefore, for elements of the same type at the same level, the key value must be unique * /}
{a.map(item => (
<li key={item}>{item}</li>
))}
</ul>
</div>
);
2.6. Use of attributes
import logo from "./logo.svg";
const jsx = (
<div>
{/ * attribute: use double quotation marks for static values and curly braces for dynamic values; class, for, etc. should be handled specially. * /}
<img src={logo} style={{ width: 100 }} className="img" />
</div>
);
2.7. modularization
CSS modularization, create index module. css,index. js
import style from "./index.module.css";
<img className={style.logo} />
Or NPM install sass – D
import style from "./index.module.scss";
<img className={style.logo} />
More CSS modules rule references
http://www.ruanyifeng.com/blog/2016/06/css_modules.html
3. Components
Component, conceptually similar to JavaScript functions. It accepts any input parameter (i.e. “props”) and returns the react element used to describe the content of the page presentation.
There are two types of components: class component and function component.
3.1. Class component
Class components usually have state and life cycle, inherit from component and implement render method. Create ⼀ clocks with the class component
import React, {
Component
} from "react";
export default class ClassComponent extends React.Component {
constructor(props) {
super(props);
//Use the state attribute to maintain the state and initialize the state in the constructor
this.state = {
date: new Date()
};
}
componentDidMount() {
//The status is updated every second after the component is mounted
this.timerID = setInterval(() => {
//Use the setstate ⽅ method to update the state
this.setState({
date: new Date()
});
}, 1000);
}
componentWillUnmount() {
//Stop timing before component unloading
clearInterval(this.timerID);
}
componentDidUpdate() {
console.log("componentDidUpdate");
}
render() {
return <div > {
this.state.date.toLocaleTimeString()
} < /div>;
}
}
3.2. Function component
Function components are usually stateless. They only focus on content display and return rendering results
From react16 8 began to introduce hooks, and functional components can also have state.
Create a clock with the function component:
import React, { useState, useEffect } from "react";
export function FunctionComponent(props) {
const [date, setDate] = useState(new Date());
Useeffect (() = > {// side effects
const timer = setInterval(() => {
setDate(new Date());
}, 1000);
return () => clearInterval(timer);// Execute when the component is unloaded
}, []);
return (
<div>
<h3>FunctionComponent</h3>
<p>{date.toLocaleTimeString()}</p>
</div>
);
}
Tip: if you are familiar with the life cycle function of react class, you can regard useeffect hook as a combination of componentdidmount, componentdidupdate and componentwillunmount.
4. Use setstate correctly
setState(partialState, callback)
- partialState : object|function
Used to generate a subset merged with the current state. - callback : function
Called after state update.
4.1. You should know three things about setstate():
Do not modify the state directly
For example, this code does not re render components:
//Error demonstration
this.state.comment = 'Hello';
⽽ yes, you should use setstate():
//Correct use
this.setState({comment: 'Hello'});
4.2. State updates may be asynchronous
For performance reasons, react may combine multiple setstate () calls into one call.
Observe the value of log and the counter displayed by button in the following example.
import React, {
Component
} from "react";
export default class SetStatePage extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0
};
}
changeValue = v => {
this.setState({
counter: this.state.counter + v
});
console.log("counter", this.state.counter);
};
setCounter = () => {
this.changeValue(1);
//this.changeValue(2);
//console.log("counter", this.state.counter);
};
render() {
const {
counter
} = this.state;
return (
< div >
<h3 > SetStatePage < /h3>
<button onClick = {this.setCounter} >
{counter}
< /button>
</div>
);
}
}
If you want to obtain the latest status value, there is the following formula:
1. Get the status value in the callback
changeValue = v => {
this.setState({
counter: this.state.counter + v
},
() => {
console.log("counter", this.state.counter);
}
);
};
- Use timing:
setTimeout(() => {
this.setCounter();
}, 0);
- Modify state in native event
componentDidMount(){
document.body.addEventListener('click', this.changeValue, false)
}
Summary: setstate is asynchronous only in synthetic events and lifecycle functions, but synchronous in both native events and settimeouts. This asynchrony is actually a batch update.
4.3. State updates are merged
changeValue = v => {
this.setState({
counter: this.state.counter + v
});
};
setCounter = () => {
this.changeValue(1);
this.changeValue(2);
};
This changeValue(1); Will not take effect
If you want to update the state chain:
changeValue = v => {
this.setState(state => ({
counter: state.counter + v
}));
};
setCounter = () => {
this.changeValue(1);
this.changeValue(2);
};
5. Life cycle
Reference documents:https://zh-hans.reactjs.org/docs/react-component.html#constructor
When a component instance is created and inserted into the DOM, its life cycle call sequence is as follows:
- constructor()
- static getDerivedStateFromProps()
- render()
- componentDidMount()
The update is triggered when the props or state of the component changes. The life cycle calling sequence of component update is as follows:
- static getDerivedStateFromProps()
- shouldComponentUpdate()
- render()
- getSnapsBeforeUpdate()
- componentDidUpdate()
The following three life cycle functions will be discarded and replaced with getderivedstatefromprops. If currently used, add unsafe_:
- componentWillMount
- componentWillReceiveProps
- componentWillUpdate
Two new life cycle functions are introduced
- static getDerivedStateFromProps
- getSnapshotBeforeUpdate
getDerivedStateFromProps
static getDerivedStateFromProps(props, state)
GetDerivedStateFromProps will be called before calling the render method, and will be called at the initial mount and subsequent updates. It should return an object to update the state. If it returns null, nothing will be updated.
Note that this method is triggered before each rendering regardless of the reason. This is different from unsafe_ In contrast, componentwillreceiveprops is triggered only when the parent component is re rendered, not when setstate is called internally.
getSnapshotBeforeUpdate
getSnapshotBeforeUpdate(prevProps, prevState)
After render, before componentdidupdate.
GetSnapshotBeforeUpdate () is called before the last render output (submitted to the DOM node). It enables the component to capture some information (for example, scroll position) from the DOM before changes occur. Any return value of this lifecycle will be passed as a parameter to componentdidupdate (prevprops, prevstate, snapshot).
6. Component composition
Composite components give you enough agility to define the appearance and behavior of components, which is more clear and safe. If there is public non UI logic between components, extract them for JS module import instead of inheriting it.
Anonymity
Create a new layout JS file
import React, {
Component
} from "react";
import TopBar from "../components/TopBar";
import BottomBar from "../components/BottomBar";
export default class Layout extends Component {
componentDidMount() {
const {
Title = "mall"
} = this.props;
document.title = title;
}
render() {
const {
children,
showTopBar,
showBottomBar
} = this.props;
console.log("children", children);
return (
< div >
{showTopBar && <TopBar />}
{children}
{showBottomBar && <BottomBar />}
</div>
);
}
}
UserPage.js:
import React, { Component } from "react";
import Layout from "./Layout";
export default class UserPage extends Component {
render() {
return (
<Layout showTopBar={true} showBottomBar={true}>
<div>
<h3>UserPage</h3>
</div>
</Layout>
);
}
}
Named
Similar to the named slot in vu, we pass an object in
import React, {
Component
} from "react";
import Layout from "./Layout";
export default class HomePage extends Component {
render() {
return ( < Layout showTopBar = {
false
}
showBottomBar = {
true
}
Title = "mall homepage" >{
/* <div>
<h3>HomePage</h3>
</div> */
} {
{
content: (
<div >
<h3 > HomePage < /h3>
</div>
),
Txt: "this is a ⽂ text",
btnClick: () => {
console.log("btnClick");
}
}
} <
/Layout>
);
}
}
7.redux
In the following scenario, it is wise to introduce redux
- You have a considerable amount of data that changes over time;
- Your state needs a single reliable data source;
- You think putting all States in the top-level components can meet your needs.
- The state of a component needs to be shared.
Redux is the state content of JavaScript applications and provides predictable state management. It ensures that the program is consistent and easy to test.
Install Redux
npm install redux –save
Redux get started
Take an example of accumulation
- You need a store to store data
- The reducer of the store initializes the state and defines the state modification rules
- Submit the modification of data through an action of dispatch
- Submit the action to the reducer function and return a new state according to the type of the incoming action
Create a store, Src / store / reduxstore js
import {
createStore
} from 'redux'
const counterReducer = (state = 0, action) => {
switch (action.type) {
case 'ADD':
return state + 1
case 'MINUS':
return state - 1
default:
return state
}
}
const store = createStore(counterReducer)
export default store
Create reduxpage
import React, {
Component
} from "react";
import store from "../store/ReduxStore";
export default class ReduxPage extends Component {
componentDidMount() {
store.subscribe(() => {
console.log("subscribe");
this.forceUpdate();
//this.setState({});
});
}
add = () => {
store.dispatch({
type: "ADD"
});
};
minus = () => {
store.dispatch({
type: "MINUS"
});
};
render() {
console.log("store", store);
return (
<div>
<h3>ReduxPage</h3>
<p>{store.getState()}</p>
<button onClick={this.add}>add</button>
<button onClick={this.minus}>minus</button>
</div>
);
}
}
If you click the button, you can’t update it because there is no subscription status change
You can also use Src / index JS render subscription status changes
import store from './store/ReduxStore'
const render = () => {
ReactDom.render( <
App / > ,
document.querySelector('#root')
)
}
render()
store.subscribe(render)
Checkpoint
- Createstore create store
- Reducer initializes and modifies status functions
- Getstate get state value
- Dispatch submission update
- Subscribe change subscription
8.react-redux
install
npm install react-redux –save
React Redux provides two APIs
- Provider provides a store for descendant components
- Connect provides data and change methods for components
Global store, index js
import React from 'react'
import ReactDom from 'react-dom'
import App from './App'
import store from './store/'
import { Provider } from 'react-redux'
ReactDom.render(
<Provider store={store}>
<App/>
</Provider>,
document.querySelector('#root')
)
Get status data, reactreduxpage js
import React, {
Component
} from "react";
import {
connect
} from "react-redux";
class ReactReduxPage extends Component {
render() {
const {
num,
add,
minus
} = this.props;
return ( <
div >
<
h1 > ReactReduxPage < /h1> <
p > {
num
} < /p> <
button onClick = {
add
} > add < /button> <
button onClick = {
minus
} > minus < /button> < /
div >
);
}
}
const mapStateToProps = state => {
return {
num: state,
};
};
const mapDispatchToProps = {
add: () => {
return {
type: "add"
};
},
minus: () => {
return {
type: "minus"
};
}
};
export default connect(
Mapstatetoprops, // state mapping mapstatetoprops
Mapdispatchtoprops, // dispatch event mapping
)(ReactReduxPage);
Parameters in connect: state mapping and event mapping
9.react-router
The react router contains three libraries: react router, react router Dom and react router native. The react router provides the most basic routing function. In actual use, we will not directly install the react router, but choose to install the react router DOM (used in browsing) or react router native (used in RN) according to the application running environment. Both react router Dom and react router native rely on react router, so during installation, react router will be automatically installed to create web applications,
use:
install
npm install –save react-router-dom
Basic use
The idea of “everything is a component” is adopted in the react router. The route consists of “route”, “link”, “route”, “exclusive switch” and “redirect” all exist in the form of components
Create routerpage js
import React, {
Component
} from "react";
import {
BrowserRouter as Router,
Route,
Link
} from "react-router-dom";
export default class RouterPage extends Component {
render() {
return (
<div >
<h3 > RouterPage < /h3>
<Router >
< link to = "/" > Home Page < / link >
< link to = "/ user" > User < / link >
{/ * the root path is determined by adding exact to achieve exact matching * /}
<Route
exact
path = "/"
component = {HomePage}
//children={() => <div>children</div>}
//render={() => <div>render</div>}
/>
<Route
path = "/user"
component = {UserPage}
/>
</Router>
</div>
);
}
}
class HomePage extends Component {
render() {
return ( <
div >
<
h3 > HomePage < /h3> <
/div>
);
}
}
class UserPage extends Component {
render() {
return ( <
div >
<
h3 > UserPage < /h3> <
/div>
);
}
}
Three ways route renders content
Route rendering priority: children > component > render.
These three methods are mutually exclusive. You can only use one.
children:func
Sometimes, no matter whether the location matches or not, you need to render some content. At this time, you can use children.
Other rendering methods are exactly the same as render except that they will be rendered regardless of whether the location matches or not
render:func
But when you use render, all you call is a function.
Render only when the location matches.
component: component
Render only when the location matches.
404 page
Set a route without path to the end of the route list, indicating that it must match
{/ * adding a switch means that only one * /}
<Switch >
{/ * the root path is determined by adding exact to achieve exact matching * /}
<Route
exact
path = "/"
component = {HomePage}
/>
<Route
path = "/user"
component = {UserPage}
/>
<Route
component = {EmptyPage}
/>
</Switch>
class EmptyPage extends Component {
render() {
return (
<div >
<h3 > EmptyPage - 404 < /h3>
</div>
);
}
}
10.PureComponent
React. Purecomponent and react Component is very similar. The difference between the two is react Component does not implement shouldcomponentupdate(), but react Purecomponent implements this function by shallow comparison between prop and state.
If you assign the same props and state to the react component, and the render () function will render the same content, then in some cases, use react Purecomponent improves performance.
Achieve performance optimization
Customized shouldcomponentupdate component
import React, {Component,PureComponent} from "react";
export default class PureComponentPage extends PureComponent {
constructor(props) {
super(props);
this.state = {
counter: 0,
// obj: {
// num: 2,
// },
};
}
setCounter = () => {
this.setState({
counter: 100,
// obj: {
// num: 200,
// },
});
};
render() {
const {
counter,
obj
} = this.state;
console.log("render");
return (
<div >
<h1 > PuerComponentPage < /h1>
<div onClick = {this.setCounter} > counter: {counter} < /div>
</div>
);
}
}
11. Know hook
Hook, right? Hook is a special function that allows you to “hook in” the feature of react. For example, usestate is a hook that allows you to add state in the react function component.
When do you use hook? If you are writing functional components and realize that you need to add some states to them, the previous practice was to convert others into classes. Now you can use hook in existing function components.
import React, { useState } from "react";
export default function HookPage(props) {
//Declare a state variable called "count" and initialize it to 0
const [count, setCount] = useState(0);
return (
<div>
<h3>HookPage</h3>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>add</button>
</div>
);
}
Using effect hook
Effect hook allows you to perform side effects in function components.
Data acquisition, setting subscriptions, and manually changing the DOM in the react component are side effects. Whether you know these operations or the name “side effects”, they should have been used in the component.
import React, { useState, useEffect } from "react";
export default function HookPage(props) {
//Declare a state variable called "count" and initialize it to 0
const [count, setCount] = useState(0);
//Similar to componentdidmount and componentdidupdate
useEffect(() => {
//New title
document.title = `You clicked ${count} times`;
});
return (
<div>
<h3>HookPage</h3>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>add</button>
</div>
);
}
It is not allowed to change DOM, add subscriptions, set timing, record records and perform other operations including side effects in the function component body (this means in the react rendering stage), because it may cause inexplicable bugs and destroy the consistency of the UI.
Use useeffect to complete the side effect operation. The function assigned to useeffect is executed after the component is rendered to the screen. You can think of effect as an escape route from the pure functional world of react to the command world.
By default, effect will be executed after each round of rendering, but you can choose to let it execute only when some values change.
Conditional execution of effect
By default, effect is executed after each round of component rendering. In this way, once the dependency of effect changes, it will be recreated.
However, in some scenarios, doing so may be overkill. For example, in the subscription example in the previous part, we do not need to create a new subscription every time the component is updated, but only need to re create it when the source props changes.
To do this, you can pass a second parameter to useeffect, which is the array of values that effect depends on. The updated example is as follows:
import React, { useState, useEffect } from "react";
export default function HookPage(props) {
//Declare a state variable called "count" and initialize it to 0
const [count, setCount] = useState(0);
const [date, setDate] = useState(new Date());
//Similar to componentdidmount and componentdidupdate
useEffect(() => {
//Update title
document.title = `You clicked ${count} times`;
}, [count]);
useEffect(() => {
const timer = setInterval(() => {
setDate(new Date());
}, 1000);
}, []);
return (
<div>
<h3>HookPage</h3>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>add</button>
<p>{date.toLocaleTimeString()}</p>
</div>
);
}
At this time, the subscription will be re created only after the value of the second parameter group of useeffect changes.
Clear effect
Generally, resources such as subscription or timing ID created by effect need to be cleared during component unloading. To achieve this, the useeffect function needs to return a clear function to prevent memory leakage. The clear function will be executed before the component is unloaded.
useEffect(() => {
const timer = setInterval(() => {
setDate(new Date());
}, 1000);
return () => clearInterval(timer);
}, []);
12. Customize hook and hook usage rules
Sometimes we want to reuse some state logic between components. So far, there are two mainstream solutions to solve this problem: high-order components and render props. Custom hook allows you to achieve the same goal without adding components.
Custom hook is a function whose name starts with “use”. Other hooks can be called inside the function.
import React, { useState, useEffect, useMemo } from "react";
export default function CustomHookPage(props) {
//Define a state variable called count and initialize it to 0
const [count, setCount] = useState(0);
//Similar to didmount and didupdate
useEffect(() => {
console.log("count effect");
//Just execute when the count changes
document. Title = ` clicked ${count} times;
}, [count]);
return (
<div>
<h3>Customize hook</h3>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>add</button>
<p>{useClock().toLocaleTimeString()}</p>
</div>
);
}
//For custom hook, the name must start with use
function useClock() {
const [date, setDate] = useState(new Date());
useEffect(() => {
console.log("date effect");
//Just execute it at didmount time
const timer = setInterval(() => {
setDate(new Date());
}, 1000);
//Clear the timer, similar to willunmount
return () => clearInterval(timer);
}, []);
return date;
}
Hook usage rules
Hooks are JavaScript functions, but there are two additional rules for using them:
Hook can only be called on the outermost layer of a function. Do not call in loops, conditional judgement, or subfunctions.
Hook can only be invoked in the function component of React. It is not necessary to invoke in other JavaScript functions. (there are other places where you can call hook — in the custom hook.)
13. Usememo and usecallback of hook API
useMemo
Pass the “create” function and dependency array as parameters into usememo, which recalculates the memoized value only when a dependency changes. This optimization helps to avoid high overhead calculations at each rendering.
···
import React, { useState, useMemo } from “react”;
export default function UseMemoPage(props) {
const [count, setCount] = useState(0);
const expensive = useMemo(() => {
console.log(“compute”);
let sum = 0;
for (let i = 0; i < count; i++) {
sum += i;
}
return sum;
//This ⾥ is re executed only when the count changes
}, [count]);
const [value, setValue] = useState(“”);
return (
<div>
<h3>UseMemoPage</h3>
<p>expensive:{expensive}</p>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>add</button>
<input value={value} onChange={event => setValue(event.target.value)} />
</div>
);
}
···
useCallback
Pass the inline callback function and dependency array as parameters into usecallback, which will return the memoized version of the callback function. The callback function will be updated only when a dependency changes. It is often useful when you pass a callback function to an optimized sub component that uses reference equality to avoid unnecessary rendering, such as shouldcomponentupdate.
···
import React, { useState, useCallback, PureComponent } from “react”;
export default function UseCallbackPage(props) {
const [count, setCount] = useState(0);
const addClick = useCallback(() => {
let sum = 0;
for (let i = 0; i < count; i++) {
sum += i;
}
return sum;
}, [count]);
const [value, setValue] = useState(“”);
return (
<div>
<h3>UseCallbackPage</h3>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>add</button>
<input value={value} onChange={event => setValue(event.target.value)} />
<Child addClick={addClick} />
</div>
);
}
class Child extends PureComponent {
render() {
console.log(“child render”);
const { addClick } = this.props;
return (
<div>
<h3>Child</h3>
<button onClick={() => console.log(addClick())}>add</button>
</div>
);
}
}
···
Usecallback (FN, DEPs) is equivalent to usememo (() = > FN, DEPs).