First, learning and harvest
React Stateless components and stateful components
React Communicates with internal components
3. React component lifecycle
4. React Principle
5. React Routes
The React component
Stateless components and stateful components
- Function components are called stateless components, and class components are called stateful components
- State is data
- Function components have no state of their own and are only responsible for data presentation (static)
- The class component has its own state and is responsible for updating the UI so that the page can interact with the user (dynamic)
For example: the value in the counter starts from 0, click the button, add 1 to the value operation, the value in the counter is the state.
2. Features of props in the component
-
You can pass any type of data to a component
-
Props is a read-only object that can only read the value of the property and cannot modify the object
-
Note: When using a class component, if you write a constructor, you should pass props to super(); otherwise, you cannot get props in the constructor.
class Hello extends React.Component { constructor() { super(a);console.log(this.props); // To get the props parameter, you need to say props in the constructor and super } // this. Props can get this render() { return ( <div> <span>Name: {this. Props. The name}</span> <span>Age: {this. Props. Age}</span> </div> ); } } ReactDOM.render( <Hello name="zhangsan" age={19} />.document.getElementById("root"));Copy the code
3. Three ways of communication between components
The parent component passes data to the child component
- The parent component provides the passed state data
- In the parent component, add attributes to the child component tag with values of data in state
- The child component receives data passed in the parent component through props
/ / the parent component
class Parent extends React.Component {
state = {
ParentName: "Zhang"
};
render() {
return (
<div>Parent component name: {this.state.ParentName}<Children1 name={this.state.ParentName} />
</div>); }}/ / child component
class Children1 extends React.Component {
render() {
console.log(this.props);
return <div>Child component receives data from parent component: {this.props. Name}</div>;
}
}
ReactDOM.render(<Parent />.document.getElementById("root"));
Copy the code
3.2. Child components pass data to parent components
The parent component provides the callback function, and the child component calls the callback function and passes the data as an argument to the callback function.
- The parent component provides a callback function (to receive data)
- In the parent component, add a property to the child component tag that is the parent component’s callback function (this). Callback function name)
- Declare a function in the child component, and then, in the function of the child component, call the callback function of the parent component through that function
- Passes the child’s data as an argument to the parent’s callback function
- Trigger a click event (or other event) in a child component to execute a function declared in the child component
class Parent2 extends React.Component {
state = {
childName: ""
};
// The parent component provides a callback function (to receive data)
ParentHandle = data= > {
console.log(data);
this.setState({
childName: data
});
};
render() {
return (
<div>{this.state.childname}<Children2 fn={this.ParentHandle} />
</div>); }}class Children2 extends React.Component {
state = {
childName: "Zhang Sanfeng"
};
childHandle = () = > {
// The child component calls the callback function through this props
// Pass the child's data as an argument to the callback function
this.props.fn(this.state.childName);
};
render() {
return (
<div>{/* Trigger a click event (or other event) in a child component to execute a function declared in the child component */}<button onClick={this.childHandle}>Click on me to pass the name to the parent component</button>
</div>
);
}
}
ReactDOM.render(<Parent2 />.document.getElementById("root"));
Copy the code
3.3 Communication between sibling components
Idea: Promote the state to the sibling’s nearest parent, making the state shared. (State improvement)
- Promote the shared state to the nearest public parent, which manages the state
- The common parent component provides shared state
- The common parent provides methods to manipulate shared state
- Sibling components simply receive state through props or call methods on operation state
class Parent3 extends React.Component {
// The public parent provides shared state
state = {
count: 0
};
// The public parent provides methods to manipulate shared state
parentHandle = () = > {
this.setState({
count: this.state.count + 1
});
};
render() {
return (
<div>
<Child1 childCount={this.state.count} />
<Child2 childFn={this.parentHandle} />
</div>); }}class Child1 extends React.Component {
render() {
// The sibling component only needs to receive the state through props
return <h1>The current counter value: {this.props. ChildCount}</h1>; }}class Child2 extends React.Component {
render() {
return (
// Sibling components simply call the methods of operation state via props
<button
onClick={()= >{ this.props.childFn(); }} > 1</button>
);
}
}
ReactDOM.render(<Parent3 />.document.getElementById("root"));
Copy the code
4, the Context
Context provides a way to share such values between components without having to explicitly pass props through layer by layer of the component tree.
// Context (pass data across components, solve nested deeper component pass value)
// Use React. CreateContext to create Provider objects and Consumer objects
// Provider object: used to provide data
// Consumer object: used to consume data
const { Provider, Consumer } = React.createContext();
class App extends React.Component {
render() {
return (
<Provider value="color">
<div>
<Node />
</div>
</Provider>); }}class Node extends React.Component {
render() {
return (
<div>
<SubNode />
</div>); }}class SubNode extends React.Component {
render() {
return (
<div>
<Child />
</div>); }}class Child extends React.Component {
render() {
return <Consumer>{data => <div>{data}</div>}</Consumer>;
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
5.1 children attribute
- Children property: Represents the children of the component label. Props has this property when the component tag has child nodes
- The children attribute, like ordinary props, can have any value (text, React elements, components, functions)
Children as a text node
class App extends React.Component {
render() {
return (
<div>
<Node>I'm a child node</Node>
</div>); }}class Node extends React.Component {
render() {
console.log(this.props);
return (
<div>The text in the component is {this.props. Children}</div>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
Children as a component
// children as a component
class App extends React.Component {
render() {
console.log(this.props);
return <div>{this.props.children}</div>; }}class Node extends React.Component {
render() {
return <div>I'm a Node component</div>;
}
}
ReactDOM.render(
<App>
<Node />
</App>.document.getElementById("root"));Copy the code
Children as a function
// children as a function
class App extends React.Component {
render() {
console.log(this.props);
return <div>{this.props.children()}</div>; }}const handle = () = > {
console.log("hello");
};
ReactDOM.render(<App>{handle}</App>.document.getElementById("root"));
Copy the code
5.2 props check
Premise:
- The props are external to the component, and there is no guarantee of what format the component consumer will pass in
- If the data is passed in the wrong format, an error may occur within the component
- Key problem: The user of the component does not know the exact cause of the error
Solutions:
Props validation: Allows the props type, format, and so on to be specified when creating a component
Function: Captures errors caused by props when using components, and provides specific error messages to improve component robustness.
Steps:
- Install the prop-types package,
yarn add prop-types
或npm i prop-types
- Import prop – types package
import PropTypes from "prop-types";
- PropTypes = {} to add validation rules to the props of the component
- Validation rules are specified through the PropTypes object
Functional form
// function form
const App = props= > {
const arr = props.colors;
const lis = arr.map((item, index) = > <li key={index}>{item}</li>);
return (
<div>
<ul>{lis}</ul>;
</div>
);
};
// Note that the propTypes here start with a lowercase P.
App.propTypes = {
// meaning: here PropTypes are capitalized with P, which is introduced above.
colors: PropTypes.array
};
ReactDOM.render(
<App colors={["red","pink]} "/ >.document.getElementById("root"));Copy the code
Component form
/ / Props
// Install and import the prop-types package
// 2. Use the component name. PropTypes = {} to add validation rules to props of the component
// 3. Validation rules are specified by the PropTypes object
import PropTypes from "prop-types";
class App extends React.Component {
// state = {
// arr: this.props.colors
/ /};
render() {
const arr = this.props.colors;
return (
<div>
<ul>
{/* {this.state.arr.map((item, index) => (
<li key={index}>{item}</li>
))} */}
{arr.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>); }}// Note that the PropTypes here are different from the function forms.
App.defaultProps = {
colors: PropTypes.array
};
ReactDOM.render(
<App colors={["red","pink]} "/ >.document.getElementById("root"));Copy the code
Default value of 5.3 props
Usage scenarios: For example, the paging function is used to display the number of items
// The default value for props
const App = (props) = > {
return (
<div>
<h1>The default value for props is :{props.PageSize}</h1>
</div>
);
};
App.defaultProps = {
PageSize: 30}; ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
The React component life cycle
Component lifecycle: The entire process of creating a component, mounting it to a page to run, and uninstalling it when it is not in use.
Each phase of the lifecycle is always accompanied by calls to methods that are the hook functions of the lifecycle.
Hook functions provide opportunities for developers to manipulate components at different stages.
Only class components have a life cycle; function components have no life cycle.
1. Hook functions for the mount phase
Hook function | trigger | role |
---|---|---|
constructor | When a component is created, it is executed first | 1. Initialize state 2. Bind this to the event handler |
render | Fires every time a component is rendered | 1. Render UI< SetState () cannot be called in the render hook function. SetSate () can update state and UI. If setSate() is called, render will be called to update UI. If setSate() is called in render, recursive update will occur. |
componentDidMount | Execute after the component is mounted (DOM rendering is complete) | 1. Send network requests 2. DOM manipulation |
Update phase hook function
Execution time |
---|
When the component receives the new props, it triggers render to update the UI |
2. Calling setSate() triggers render to update the UI |
3. Calling forceUpdate() forces render to trigger to update the UI |
With any of these changes, the component is rerendered
Hook function | trigger | role |
---|---|---|
render | Fires every time a component is rendered | 1. Render the UI |
componentDidUpdate | Execute after component update (complete DOM rendering) | 1. Send network requests 2. DOM manipulation 3. Note that setState() must be called in an if condition, because calling setState() from this hook also updates recursively |
componentDidUpdate(prevProps){
console.log(prevProps)
console.log(this.props)
}
if(prevProps.name ! = = =this.props.name){
this.setState({})
}
Copy the code
3. Hook functions for the uninstall phase
Hook function | trigger | role |
---|---|---|
componentWillUnmount | Component unmount (disappear from page) | Perform cleanup, such as cleanup timers |
4. Reuse React components
React component reuse: Reuse states or logic that have similar or identical functions in multiple components. Reuse: state and methods for manipulating state.
Reuse mode:
- Render props model
- High order Component (HOC)
1, Render props mode
// Component reuse
// render props mode
class Mouse extends React.Component {
state = {
x: 0.y: 0}; handleMouseMove =(event) = > {
this.setState({
x: event.clientX,
y: event.clientY,
});
};
// Listen for mouse movement events
componentDidMount() {
window.addEventListener("mouseover".this.handleMouseMove);
}
render() {
// return null;
return this.props.render(this.state); }}class App extends React.Component {
render() {
return (
<div>
<h1>Render props model</h1>
<Mouse
render={(mouse)= > {
return (
<div>{mouse.x} {mouse.y}</div>); }} / ><Mouse
render={(mouse)= > {
return (
<div>
<img
src={logo}
alt=""
style={{
position: "absolute",
left: mouse.x - 96.top: mouse.y - 96,
}}
/>
</div>); }} / ></div>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
Use children instead of render
import logo from "./assets/logo192.png";
// The lifecycle of the component
// class App extends React.Component {
// constructor() {
// super();
/ /}
// }
/ / Props
// Install and import the prop-types package
// 2. Use the component name. PropTypes = {} to add validation rules to props of the component
// 3. Validation rules are specified by the PropTypes object
import PropTypes from "prop-types";
// Component reuse
// render props mode
class Mouse extends React.Component {
state = {
x: 0.y: 0}; handleMouseMove =(event) = > {
this.setState({
x: event.clientX,
y: event.clientY,
});
};
// Listen for mouse movement events
componentDidMount() {
window.addEventListener("mouseover".this.handleMouseMove);
}
componentWillUnmount() {
window.removeEventListener("mouseover".this.handleMouseMove);
}
render() {
// return null;
// return this.props.render(this.state);
return this.props.children(this.state);
}
}
Mouse.propTypes = {
children: PropTypes.func.isRequired,
};
class App extends React.Component {
render() {
return (
<div>
<h1>Render props model</h1>{/ *<Mouse
render={(mouse)= > {
return (
<div>{mouse.x} {mouse.y}</div>); / > * /}}} {/ *<Mouse
render={(mouse)= > {
return (
<div>
<img
src={logo}
alt=""
style={{
position: "absolute",
left: mouse.x - 96.top: mouse.y - 96,
}}
/>
</div>); / > * /}}}<Mouse>
{(mouse) => {
return (
<div>{mouse.x} {mouse.y}</div>
);
}}
</Mouse>
<Mouse>
{(mouse) => {
return (
<div>
<img
src={logo}
alt=""
style={{
position: "absolute",
left: mouse.x - 96.top: mouse.y - 96,
}}
/>
</div>
);
}}
</Mouse>
</div>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
2. High-level Component (HOC)
Objective: To realize state logic reuse
HOC (higher-order Components) is a function that receives a component to wrap and returns an enhanced component
The high-level component creates a class component inside which the reused state logic code is provided to pass the reused state to the WrappedComponent via props
const EnhancedComponent = higherOrderComponent(WrappedComponent);
Copy the code
Steps to use higher-order components
Create a function with a name starting with hoc
2. Specify function parameters that start with a capital letter (as the component to be rendered).
Create a class component inside the function, provide reusable state logic code, and return the class component.
In this component, the parameter component is rendered and the state is passed to the parameter component via props
5. Call the higher-order component, pass in the component to be enhanced, get the enhanced component with the return value, and render it to the page
// Higher-order components
Create a function with a name starting with hoc
// 2. Specify function parameters that start with a capital letter (as the component to be rendered).
const hocMouse = (WrappedComponent) = > {
// create a class component inside the function, provide the reusable state logic code, and return the class component.
class Mouse extends React.Component {
// Mouse status
state = {
x: 0.y: 0}; handleMouseMove =(e) = > {
this.setState({
x: e.clientX,
y: e.clientY,
});
};
// Control the state of the mouse logic
componentDidMount() {
window.addEventListener("mousemove".this.handleMouseMove);
}
// Unbind events
componentWillUnmount() {
window.removeEventListener("mousemove".this.handleMouseMove);
}
render() {
return (
<div>{/* render the props component and pass the state to the props component */}<WrappedComponent {. this.state} ></WrappedComponent>
</div>); }}// Return the class component
return Mouse;
};
// Test higher-order components
const PagePosition = (props) = > {
return (
<div>X :{props. X},y:{props. Y}</div>
);
};
// Image location
const PageCatPosition = (props) = > (
<img
src={logo}
alt=""
style={{
position: "absolute",
left: props.x - 96.top: props.y - 96,
}}
/>
);
// 5. Call the higher-order component, pass in the component to be enhanced, get the enhanced component with the return value, and render it to the page
const MousePage = hocMouse(PagePosition);
const PageCat = hocMouse(PageCatPosition);
class App extends React.Component {
render() {
return (
<div>
<h1>Use of higher-order components</h1>{/* Render enhanced components */}<MousePage></MousePage>
<PageCat></PageCat>
</div>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
High-level component transfer props
Add {… this.props}
const hocMouse = (WrappedComponent) = > {
// Create class components internally to provide reuse state logic in class components
class Mouse extends React.Component {
// Mouse status
state = {
x: 0.y: 0}; handleMouseMove =(e) = > {
this.setState({
x: e.clientX,
y: e.clientY,
});
};
// Control the state of the mouse logic
componentDidMount() {
window.addEventListener("mousemove".this.handleMouseMove);
}
// Unbind events
componentWillUnmount() {
window.removeEventListener("mousemove".this.handleMouseMove);
}
render() {
console.log(this.props);
return (
<div>
<WrappedComponent {. this.state} {. this.props} ></WrappedComponent>
</div>
);
}
}
Mouse.displayName = `hocMouse${getDisplayName(WrappedComponent)}`;
// Return the class component
return Mouse;
};
const getDisplayName = (WrappedComponent) = > {
return WrappedComponent.displayName || WrappedComponent.name || "Component";
};
// Test higher-order components
const PagePosition = (props) = > {
console.log(props);
return (
<div>X :{props. X},y:{props. Y}</div>
);
};
// Image location
const PageCatPosition = (props) = > (
<img
src={logo}
alt=""
style={{
position: "absolute",
left: props.x - 96.top: props.y - 96,
}}
/>
);
const MousePage = hocMouse(PagePosition);
const PageCat = hocMouse(PageCatPosition);
class App extends React.Component {
render() {
return (
<div>
<h1>Use of higher-order components</h1>{/* Render enhanced components */}<MousePage a="1"></MousePage>
<PageCat></PageCat>
</div>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
The React Principle
1. React works
1),UI = f(data){}
The UI is the interface, the interface is the result of the execution of the function, it’s based on the idea of functional programming, and what we do is we implement the function, we change the UI, by changing the parameter data in the function, changing the data, so that the data drives the function, the function affects the UI. So in React, whenever you implement a component or do something else, you implement a function, change the data in the function, let the data drive the function, and let the function affect the UI. In other words, you change the UI by changing data. That’s the idea of React responsiveness.
Data is props and state
Developers just need to maintain variable data state (what) and let the React framework handle DOM operations (what) for us.
React uses the Diffing algorithm to calculate how to update views. However, the Diffing algorithm assumes that the developer will provide an ID for each subitem of the long list to help the algorithm compare, as shown in the figure below:
React believes that if the keys are the same, there is no need to recalculate and render. As long as the keys are different (for example, a new x node is inserted), the x node needs to be rendered separately.
Two elements of key in the same set of components
1. Key is unique among sibling nodes.
2, The key value is stable, the key value must be fixed, do not always change the key value, in actual development, the key value should not set the array index value, because this is unstable value, for example, as shown in the figure above, the index value of B was 1 before, but after changing, the index value becomes 2.
3. A ternary expression does not need to be marked with a key, because there will be a corresponding value in the corresponding position regardless of whether the ternary expression condition is true or not.
2) The completed rendering process
The initial rendering process is divided into 3 steps.
First, developers write React using JSX syntax. Babel compiles JSX into a browser-aware React JS syntax. This step is usually done locally in conjunction with webPack.
The second step is to render the virtual DOM by executing the reactdom. render function.
Step 3: React renders the virtual DOM into the real DOM.
Page update process is also 3 steps.
First, when the page needs to be updated, call setState declaratively to tell React what data has changed.
In the second step, React automatically calls the render method of the component to render the virtual DOM.
Third, react uses the Diffing algorithm to compare the current virtual DOM to the one that needs to be updated. Then re-render the actual DOM of the different parts.
- What is modularization: from the point of view of the code, to analyze the problem, the business logic of our programming time, divided into different modules for development, so as to facilitate the reuse of the code;
- What is componentization: From the perspective of the UI, to analyze problems, put a page, broken down into several unrelated groups, with the development of our project, we hand components will be more and more, in the end, if we want to implement a page, may directly get existing components for stitching, can quickly get a complete page, so convenient the reuse of the UI elements; A component is a collection of elements;
3) What is Virtual DOM (Virtual DOM)
The virtual DOM (VDOM) is a programming concept in which a virtual view is kept in memory and kept synchronized with the “real” DOM through a library such as ReactDOM. This process is called reconciliation.
This programming approach uses React’s declarative API: You need to tell React what state you want the view to be in, and React is responsible for ensuring that the DOM matches that state. So you don’t have to do all the property manipulation, event handling, and DOM updates yourself when building your app. React does it for you.
Since the “virtual DOM” is more of a pattern than a specific technology, we sometimes use it to mean something else. In the React world, the “virtual DOM” and the React tuple are often linked because they are both objects used to represent views. React, however, also uses objects called “fibers” to store additional information about the component tree. In React, they are also considered part of the “virtual DOM” implementation.
4) Are Shadow DOM and Virtual DOM the same concept?
No, they’re not the same concept. Shadow DOM is a browser technology designed to encapsulate variables and CSS in Web components. The virtual DOM is a concept implemented by JavaScript libraries on top of browser apis.
5) Diff algorithm
- Tree Diff: The new and old DOM trees are compared layer by layer, which is called tree Diff. Whenever we compare nodes of all layers from front to back, we will inevitably find those elements that need to be updated.
- Component diff: The comparison between components when comparing each layer is called component diff; When comparing components, if the two components have the same type, it is temporarily considered that the component does not need to be updated. If the components have different types, remove the old component immediately, create a new component, and replace it with the removed position.
- Element diff: In a component, comparisons are made between each element, so element-level comparisons are called Element diff.
- Key: The key attribute can make a layer of association between the DOM node on the page and the object in the virtual DOM.
Fiber is the new engine in React 16. Its main purpose is to enable incremental rendering of the virtual DOM.
React Fiber is a re-implementation of the React core algorithm.
React Fiber aims to improve its applicability to areas such as animation, layout, and gestures. Incremental rendering is its most important feature: it can break up the rendering work into multiple pieces and divide those pieces into multiple frames for execution.
Other core features include the ability to pause, suspend, or resume work when new updates arrive; The ability to set priorities for different types of updates; And new concurrency primitives.
6) what is reconciliation?
-
reconciliation
React is an algorithm that compares two trees and determines which parts of the tree need to be updated.
-
update
Changes to the data used to render the React application. Usually the result of setState. The end result will be a re-render
The core idea of the React API is to think of updates as rerenders of the entire application. This allows developers to derive declaratively without worrying about how the application will efficiently transition from one state to another (A to B, B to C, C to A, and so on).
In fact, rerendering the entire application for each change is only appropriate for the simplest applications. In a real-world application, there is a significant performance overhead.
Reconciliation is the algorithm behind what is widely known as the “virtual DOM”.
- Different component types are expected to generate substantially different trees. React will not attempt to make a difference comparison, but will simply replace the old tree entirely.
- Use keys for list differences comparison to optimize performance. Keys should be stable, predictable, and unique.
-
-
Scheduling
Scheduling
-
scheduling
The process of determining when work should be performed.
-
work
Any calculation must be performed. Work is usually the result of an update (e.g. setState).
In the current implementation of React, React recursively traverses the tree and calls the Render method to update the entire tree in one iteration of the Event loop. In the future, however, it will delay some updates to prevent dropping frames.
This is a common theme in React design. Some popular libraries implement a “push” approach, where calculations are performed as new data arrives. But React sticks to the “pull” approach, where calculations can be deferred until needed.
React is not a general-purpose data processing library. It is simply a library designed to build user interfaces. We think of knowing which calculations are relevant now and which are not something that has a unique place in the application.
If something is off-screen, we can defer any logic associated with it. If the data comes faster than the frame rate block, then we can merge and batch update. We can prevent frames from being dropped by prioritizing work from user interaction with the interface (such as the animation of a button click) and less important back-work (such as remotely loading data to render new content).
The core points are summarized as follows:
- In the UI, not all updates need to take effect immediately. In fact, doing so is wasteful and can cause frame drops that affect the user experience.
- Different types of updates have different priorities. An animated update usually needs to be executed faster than an update from data.
- A push-based scheme requires the application (you, the engineer) to decide how to schedule the work. A pull-centric solution allows frameworks such as React to be smarter and make those decisions for you.
The main goal of iBER is to enable React to enjoy the benefits of scheduling. Specifically, we need to be able to do the following things:
- Pause a task and be able to resume it later.
- Set different priorities for different tasks.
- Reuse previously completed tasks.
- You can terminate a task if it is no longer needed.
To do this, we first need a way to break down the tasks into task units. In a sense, these task units are fibers. A fiber represents a task unit.
view = fn(data) Copy the code
Thus rendering the React application is similar to calling a function that contains other function calls.
-
2. Everything is a component
2.1 components
Any data obtained between components via props is read-only and cannot be reassigned
Tags in JSX syntax are not rendered directly to the page. Instead, they are converted to javascript code like react. createElement and then rendered to the page by render
Static methods in the ES6 class are mounted in the Constructor constructor and instance methods are mounted in the prototype object
class Person {
constructor(name,age){
this.name = name
this.age = age
}
Say is the instance method
say(){
console.log('hello')}// info is static
static info = 123
}
class Chinese extends Person {
Using the extends keyword to implement inheritance, a subclass's constructor constructor must display a call to the super() method, which represents a reference to constructor from the parent class
constructor(name,age,color,lang) {
super(name,age)
}
}
var p1 = new Person('zs'.12)
console.log(p1)
var c1 = new Person('ls'.12.'yellow'.'Chinese')
console.log(c1)
c1.say()
console.log(Chinese.info)
Copy the code
React Stateless Component vs. stateful Component Stateless Component: Stateless Component is the most basic form of Component. It is purely static because it has no state effect. In general, UI libraries are also the category of components that will be developed initially. Such as buttons, labels, input boxes, etc. Its basic structure is the props plus a render function. This component is also the most reusable because it does not involve state updates.
Stateful Component: A Component that contains state and that state was changed by events or external messages is a Stateful Component. Stateful components usually have a lifecycle that triggers state updates at different times. This type of component is also commonly used in writing business logic, depending on the number of states and lifecycle mechanisms of components in different business scenarios.
2.1 When to use stateless components? When to use stateful components?
1. If a component only needs props to render a fixed page, it is suitable to use a stateless component created by function.
Stateful components are suitable if a component needs to store its own private data and execute different business logic in different phases of the component.
In React, we typically handle two types of data using props and state. Props is read-only and can only be set by the parent component. State is defined within a component and can be changed during its life cycle. Basically, stateless components use props to store data, while stateful components (also known as smart components) use state to store data.
In general, stateless function writing is better than react. createClass and react.componentis better than react. createClass. Components that can be created using react.componentshould not be created in the react.createclass form.
There are three ways to create components in React:
- ES5 writing:
React.createClass
- ES6 writing:
React.Component
- Stateless function writing, also known as pure components
Declarative programming
Difference between declarative and imperative
- Imperative programming: Instructing the “machine” how to do things so that whatever you want it to do will happen.
- Declarative programming: Tell the machine what you want and let the machine figure out how to do it.
JQuery is imperative programming, jQuery tells you to use its API, to do something, and if the API changes, the code we write changes, because the API changes, we have to change the API, so it’s not very friendly.
The code we write in React is not likely to call system-level apis. Instead, we implement functions that respond to it. The code we write just declares what we need to do and how we need to do it.
4. SetState () description
-
SetState () updates data asynchronously
-
SetState () can be called multiple times, but only render is triggered once
class App extends React.Component {
state = {
num: 0}; handleAdd =() = > {
// call this.setState several times. Num cannot be accumulated
this.setState({
num: this.state.num + 1});this.setState({
num: this.state.num + 1});console.log(this.state.num);
};
render() {
return (
<div>
<h2>The current value is {this.state.num}.</h2>
<button onClick={this.handleAdd}>+ 1</button>
</div>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
- Recommend the grammar
class App extends React.Component {
state = {
num: 0}; handleAdd =() = > {
// This syntax is recommended: this syntax is also asynchronous, but this. SetState is called multiple times, where num is cumulative.
// state: indicates the latest state
// props: indicates the latest props
this.setState((state, props) = > {
return {
num: state.num + 1}; });this.setState((state, props) = > {
return {
num: state.num + 1}; });console.log(this.state.num);
};
render() {
return (
<div>
<h2>The current value is {this.state.num}.</h2>
<button onClick={this.handleAdd}>+ 1</button>
</div>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
- The second argument to setState()
setState({},callback)
class App extends React.Component {
state = {
num: 0}; handleAdd =() = > {
// This syntax is recommended: this syntax is also asynchronous, but this. SetState is called multiple times, where num is cumulative.
// state: indicates the latest state
// props: indicates the latest props
this.setState(
(state, props) = > {
return {
num: state.num + 1}; },() = > {
console.log(this.state.num); // the num value is synchronized with the num value in the page.});console.log(this.state.num); / / 0
};
// componentDidUpdate hook function executes before this.setState
componentDidUpdate() {
console.log("componentDidUpdate".this.state.num); // the num value is synchronized with the num value in the page.
}
render() {
return (
<div>
<h2>The current value is {this.state.num}.</h2>
<button onClick={this.handleAdd}>+ 1</button>
</div>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
Conclusion:
- The componentDidUpdate hook function executes before this.setState, and the second argument to this.setState is the same as the componentDidUpdate hook function.
5. Component update mechanism
5.1 setState() has two functions
- Change the state
- Update the UI (component)
5.2 Component Update Process
When the parent component is updated, all child components in the current parent component are also updated, without affecting the parent component’s update, nor does it affect the parent component’s sibling update.
5.3 Avoid unnecessary updates to render
Component update mechanism: Updates of parent components cause updates of child components.
Problem above: Updates are made when there are no changes to child components.
ShouldComponentUpdate (nextProps, nextState)
ShouldComponentUpdate () shouldComponentUpdate() lets React know if the current state or property changes don’t affect the output of the component. It returns a value to determine whether the component should be rerendered. This method is not called during initial rendering or when forceUpdate() is used.
Use nextState in shouldComponentUpdate(nextProps, nextState) to avoid unnecessarily updating the render
class App extends React.Component {
state = {
num: 0}; handleAdd =() = > {
this.setState(() = > {
return {
num: Math.floor(Math.random() * 3),}; }); };shouldComponentUpdate(nextProps, nextState) {
// nextState: Indicates the latest status
// this.state: current state
console.log("nextState", nextState, "this.state".this.state);
/* if (nextState.num == this.state.num) { return false; } return true; * /
//
returnnextState.num ! = =this.state.num;
}
render() {
console.log("Re-render");
return (
<div>
<h2>The current value is {this.state.num}</h2>
<button onClick={this.handleAdd}>Add 1</button>
</div>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
Trigger time: hook function in update phase, executed before component re-render (shouldComponentUpdate –> render)
Use nextProps in shouldComponentUpdate(nextState) to avoid unnecessarily updating the render
class App extends React.Component {
state = {
num: 0}; handleAdd =() = > {
this.setState(() = > {
return {
num: Math.floor(Math.random() * 3),}; }); };render() {
return (
<div>
<NumData num={this.state.num}></NumData>
<button onClick={this.handleAdd}>Add 1</button>
</div>); }}class NumData extends React.Component {
shouldComponentUpdate(nextProps) {
console.log("nextProps", nextProps, "this.props".this.props);
returnnextProps.num ! = =this.props.num;
}
render() {
console.log("Re-render");
return <h2>The current value is {this.props. Num}</h2>;
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
5.4 PureComponent
The shouldComponentUpdate hook function is automatically implemented in PureComponent for convenience
Principle of PureComponent: a PureComponent internally compares the props and state to determine whether to rerender the component
class App extends React.PureComponent {
state = {
num: 0}; handleAdd =() = > {
this.setState(() = > {
return {
num: Math.floor(Math.random() * 3),}; }); };render() {
console.log("Re-render");
return (
<div>
<h2>The current value is {this.state.num}</h2>
<button onClick={this.handleAdd}>Add 1</button>
</div>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
class App extends React.Component {
state = {
num: 0}; handleAdd =() = > {
this.setState(() = > {
return {
num: Math.floor(Math.random() * 3),}; }); };render() {
console.log("Re-render");
return (
<div>
<NumData num={this.state.num}></NumData>
<button onClick={this.handleAdd}>Add 1</button>
</div>); }}class NumData extends React.PureComponent {
render() {
return <h2>The current value is {this.props. Num}</h2>;
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
Pure component internal comparisons are shallow compare, which is fine for numeric types, but problematic for reference types
Note: When the props or state property value is a reference type, you should create new data rather than modify the original data directly
class App extends React.PureComponent {
state = {
obj: {
num: 0,}}; handleAdd =() = > {
// Create a new object
constnewObj = { ... this.state.obj,num: Math.floor(Math.random() * 3)};this.setState(() = > {
return {
obj: newObj,
};
});
};
render() {
console.log("Re-render");
return (
<div>
<h2>The current value is {this.state.obj.num}</h2>
<button onClick={this.handleAdd}>Add 1</button>
</div>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
Also note: do not use push/unshift methods to modify the array directly. These methods modify the array and do not create new arrays. Instead, use concat or slice methods that return new arrays.
this.setState({
list:[...this.state.list,{newData}]
})
Copy the code
React Routing
Routing is a set of mapping rules. In React, routing is the mapping between URL paths and components. In fact, you configure the mapping between paths and components to enable users to navigate from one view to another
1. Basic Usage
// Import the React route
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
const About = () = > {
return <div>On the page</div>;
};
class App extends React.Component {
render() {
return (
// Wrap the entire application with the Router component, which is used only once
<Router>
<div>
<h2>The React routing</h2>{/* Specify route entry */}<Link to="/about">Jump to the About page</Link>{/* Specify route exit */}<Route path="/about" component={About}></Route>
</div>
</Router>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
2. Programmatic navigation
class Login extends React.Component {
handleLogin = () = > {
// Programmatic navigation push jumps to a page
this.props.history.push("/home");
};
render() {
return (
<div>
<div>Welcome to the login page</div>
<br />
<button onClick={this.handleLogin}>The login</button>
</div>); }}const HomePage = (props) = > {
const handleBack = () = > {
// Programmatic navigation go(-1) returns
props.history.go(-1);
};
return (
<div>
<h2>Home page</h2>
<button onClick={handleBack}>exit</button>
</div>
);
};
const App = () = > {
return (
<Router>
<div>
<h2>The sign-up page</h2>
<Link to="/login">To log in</Link>
<br />
<br />
<Route path="/login" component={Login} />
<Route path="/home" component={HomePage} />
</div>
</Router>
);
};
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
3. Default route
const About = () = > {
return <div>On the page</div>;
};
class App extends React.Component {
render() {
return (
<Router>
<div>
<h2>The React routing</h2>{/* Default route */}<Route path="/" component={About}></Route>
</div>
</Router>
);
}
}
ReactDOM.render(<App />.document.getElementById("root"));
Copy the code
4. Fuzzy matching and precise matching
In React, the React route defaults to fuzzy matching mode.
Add exact attributes to the default route
<Route exact path="/" component={About}></Route>
Copy the code