preface
Before we start, let’s take a look at a basic.js file structure in a React project that the Raect scaffolding built for us:
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = { }
}
render() {
return (
<div>hello jingda</div>); }}export default App;
Copy the code
React class components are important in React. This article will cover the class components in React at length, including but not limited to:
- ES6 Class class definition and inheritance
- How to fix this pointing problem in class components
- The life cycle of components in React
- React Components communicate
Of course, when we talk about class components, we will definitely refer to the function function component that we are also familiar with. And a few other things.
I am also in the process of slowly learning React. Writing articles is to summarize and deepen my impression. It would be nice if you came away from this article with some understanding of React componentization, or just class components.
(Many parts of the article are the author directly code words, if the expression is improper, please correct the comment section, thank you for reading.)
Okay, the article will begin soon.
React component ideas
1.1 Basic Concepts
Take a big, difficult project and divide it up into a lot of small pieces that are done by different people. That’s my idea of componentization.
React components. React components. React components
Components allow you to break up the UI into separate reusable pieces of code and think about each piece individually.
1.2 Classification of Components in React
- According to the definition of components: function components and class components
- Maintenance is performed based on whether a component has state: stateless or stateful
- Different responsibilities of components: presentation components and container components
There is a lot of overlap between these concepts, but their main concern is the separation of data logic and UI presentation:
- Function components, stateless components and presentation components are the main components
Focus on the UI presentation
- Class components, stateful components, and container components are the main
Focus on data logic
;
In simple terms, the data logic changes in the class component, while the function component does not have its own internal state.
React function component
2.1. Functional Component definitions and features
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
Copy the code
This is a javascript function that passes a props object, but it returns JSX code. This JSX code will eventually be compiled by our Babel into a react.createElement () function call.
(If you’re not familiar with this, take a look at what happened in my last post from JSX to render page 😯).
Functional components look relatively simple, much like our traditional JS functions, but this component has some characteristics that may not be suitable for many situations in development:
- There is no life cycle, it will also be updated to load, but there is no life cycle function
(Why not??)
- No this(component instance);
(Why)?
- There is no internal state and only a “props” object (representing properties) with data is received;
In the process of summarizing the features of function functional components, I have these two questions: combined with Google, I get the following answers (if you have better answers, please inform me in the comments section).
1. Why are there no life cycles in function components?
We know that functional components are easy to write, and there is no code for functional components like the class component:
class App extends Component {... }Copy the code
Therefore, it does not inherit from React.component. since the lifecycle functions are implemented by methods of the React.componentclass, there is no way to use the lifecycle functions without inheriting this class
2. Why is this not included in functional components?
When I tried to find this answer online, I didn’t get the expected result, of course I also tried to print this
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="1" />
<Welcome name="2" />
<Welcome name="3" />
</div>
);
}
Copy the code
It’s undefined, but I’m still confused
React components must protect their props from being changed as pure functions.
Let me bring the solution back to pure functions here, and now the answer I can find on the Internet is pure functions:
- The return of a function depends only on its arguments.
- Function execution has no side effects: a function execution has side effects if there are observable changes to the function.
So my understanding here is that this, as an execution context object, now points to undefined, and because of the second property of pure functions, its this cannot be changed. So there’s no need for it to exist.
Of course, this is just my personal opinion. Probably not. (Please let me know in the comments section if there is an answer. Save the kids.)
2.2 use of functional components
- Only one component
function App() {
return (
<div>This is a functional component</div>
);
}
export default App;
Copy the code
Only the code inside the component is rendered
- Combining with the components
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
Copy the code
The parent component is App and the child component is Welcome. The props object stores the name property from the parent component and passes it to the child component Welcome for rendering.
React components
3.1 Definition and Inheritance of classes
3.1.1 Class definition
We all know that there are no “classes” in javascript. There are only syntactic elements of class type (new and instanceof). However, ES6 has added some keywords such as class. But that doesn’t mean there are classes in JS.
Classes are just a design pattern, and you can implement the functionality of a class in some way: for example, generating an instance object
- Use a class: the this keyword stands for instance object
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ') '; }}Copy the code
- Method: p is an instance generated by new
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ') ';
};
var p = new Point(1.2);
Copy the code
3.1.2 Class inheritance
As we have seen above, it is possible to simulate class behavior in Javascript programs through methods, but without inheritance, classes in Javascript are just a skeleton.
Before implementing “class inheritance”, let’s take a look at ES5 archetypal inheritance:
function Person(name,age) {
this.name = name;
this.age = age;
}
Person.prototype.running = function () {
console.log(this.name,this.age,'running')}var p = new Person('why'.18);
console.log(p.name,p.age);
p.running()
Copy the code
The Person constructor has the running() method on its prototype object. When using the new method,p = new Person('why',18)
, an instance of P object is created that has access to the methods on the prototype object Person
When we try to implement this “inheritance” with class:
class Person {
constructor(name,age) {
this.name = name;
this.age = age;
}
running() {
console.log("running")}}class P extends Person {
constructor(name,age,sno) {
super(name,age);
this.sno = sno; }}const p1 = new P("why".10.110)
console.log(stu.name,stu.age,stu.sno)
stu.running()
Copy the code
Here we define two classes, Person and P, where Person is the parent class and P is a subclass of Person. Person has two methods constructor() where this is the instance object.
In the constructor of subclass P, the this keyword can only be used after super is called, otherwise an error will be reported. This is because subclass instances are built on superclass instances, and only super methods can call superclass instances.
3.2 React Class Component
3.2.1 Class Component Definition and Usage
Let’s start by turning the previous functional component into a class component:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="1" />
<Welcome name="2" />
<Welcome name="3" />
</div>
);
}
Copy the code
Convert to a class component: Here I did the following:
- Create an ES6 class with the same name and inherit from react.component.exe.
- Add an empty render() method.
- Move the function body into the Render () method.
- Use this. Props instead of props in the render() method.
- Delete the remaining empty function declarations.
(For a clearer explanation, check out our website.)
export class Welcome extends Component{
constructor(props){
super(props)
}
render(){
return <h1>Hello, {this.props.name}</h1>; }}class App extends Component{
constructor(props){
super(props);
}
render(){
return (
<div>
<Welcome name="1" />
<Welcome name="2" />
<Welcome name="3" />
</div>); }}export default App;
Copy the code
There are also a few things to note in the class component:
The class component definition has the following requirements:
- Component names start in uppercase (whether class or function)
- The class component needs to inherit from react.component
- The class component must implement the Render function
Use class to define a component:
constructor
Optional, we usually initialize some data in constructor;this.state
Maintains the data inside our components.render()
Methods are the only methods that must be implemented in a class component
When render is called, it checks for changes to this.props and this.state and returns one of the following types
- The react elements:
Normally, created with JSX will be rendered as a DOM node by React, and
and
- Arrays or Fragments: Enable the Render method to return multiple elements
render() {
return (
<React.Fragment>
<td>Hello</td>
<td>World</td>
</React.Fragment>
);
}
Copy the code
- String or numeric types: They are rendered as text nodes in the DOM
render() {
return 1;
}
Copy the code
- Boolean type or NULL: Render nothing
render() {
// return null;
return false;
}
Copy the code
3.2.2 Class Component – Binding this problem in event handling
Take a look at this code:
class App extends React.Component{
constructor() {
super(a);this.state = {
}
}
render() {
return (
<div>
<button onClick={this.btnClick}>button</button>
</div>)}btnClick() {
console.log('When the button is clicked this prints:'.this)}}Copy the code
So here’s a very simple example that I want the console to print out when I click a button'When the button is clicked this prints:'
, and the click eventthis
. Let’s try it:Obviously, we get this as undefined here. When we need to click a button to perform some function: for example, click a button to subtract a number by one:
class App extends React.Component{
constructor() {
super(a);this.state = {
couter:100}}render() {
return (
<div>
<div>{this.state.couter}</div>
<button onClick={this.decrement}>- 1</button>
</div>)}decrement() {
console.log(this) //undefined
this.setState({
count:this.state.couter-1}}})Copy the code
The code simply failed because this is undefined in Decrement () and instead of calling this.setState, this.state, the data we should get is this from Constructor, which is our instance object. But I didn’t get it here. Why did this get lost?
If this is inside a class method, it points to an instance of the class by default, but if this method is isolated, it points to the environment in which the method was run. This causes an error when the Decrement () method cannot be found.
So how to solve this problem? There are four ways to do this (four specific ways, two real ways)
- Bind when you bind events
<button onClick={this.decrement.bind(this> -)}1</button>
Copy the code
- Use bind in the constructor
this.decrement = this.decrement.bind(this);
Copy the code
- Use the arrow function when binding events (
This method is easier to use oh, simple, passing parameters is also more convenient
)
<button onClick={() = > {this.decrement()}}>-1</button>
Copy the code
- Write the click event using the arrow function
decrement = () = >{}Copy the code
4. React component lifecycle
4.1 Life Cycle
The entire process from creation to destruction: called the life cycle
The React component also has a life cycle. Note the life cycle of a class component because functional components do not have a life cycle. This is the official lifecycle map. Click here to view it. Of course, this is a simple lifecycle map, including components:
- Load stage: The process by which a component is first rendered on the DOM tree
- Update process: Update the rendering process when the component state changes
- Unload process: The process by which a component is removed from the DOM tree
Here’s how react’s life cycle works: First, there are several life cyclesThe callback function
Need to know:
- The componentDidMount function: the component is already mounted to the DOM tree and is called back
- Update: componentDidUpdate Function: The component is called back when it has been updated
- Unmount: componentWillUnmount function: callback when a component is about to be removed
We can write our own logic code in these callback functions to accomplish our required functions
4.2 In the life cycle method
- constructor
If state is not initialized or binding is not performed, there are two things that are usually done in the React component implementation constructor:
1. We usually assign this. State to initialize this inside
2. Bind instance this to the event
- Render (already said)
- componentDidMount
ComponentDidMount () is called immediately after the component is mounted (inserted into the DOM tree)
ComponentDidMount = componentDidMount
3. Dom-dependent operations can be performed here
4. Send the network request here
5. Add some subscriptions here (unsubscribe at componentWillUnmount);
- componentDidUpdate
1. ComponentDidUpdate is called immediately upon update, not the first rendering
This is where you can manipulate the DOM after the component is updated
3. If the props before and after the update are compared, you can perform the network request here. (If the props are not changed, the network request is not executed.)
- componentWillUnmount
ComponentWillUnmount () is called before the component is unmounted and destroyed
2. Perform the necessary cleanup operations in this method
Cancel network requests or clear subscriptions created in componentDidMount(), etc
4.3 Load, update and unload
- Loading: From the diagram above we can see that all the way through to componentDidMount() execution, experience
Example:
class App extends Component {
constructor(props) {
super(props);
console.log(Constructor ();)
this.state = {
counter:1,}}render() {
console.log("2, render())
return (
<div>
<div>{this.state.counter}</div>
</div>
);
}
componentDidMount() {
console.log(3. Calling componentDidMount())}}Copy the code
As a very simple example, we display the state: counter defined by the constructor on the page and run the code:
- Update, the main lifecycle method undergoes in the process of making an update. The constructor method should not be used in the update process.
Example: Again, when we need to click the button counter+1:
class App extends Component {
constructor(props) {
super(props);
console.log(Constructor ();)
this.state = {
counter:1,}}render() {
console.log("2, render())
return (
<div>
<div>{this.state.counter}</div>
<button onClick={()= >Enclosing btnClick > click ()}</button>
</div>
);
}
componentDidMount() {
console.log(3. Calling componentDidMount())}componentDidUpdate() {
console.log("ComponentDidUpdate ()")}btnClick() {
this.setState({
counter:this.state.counter+1}}})Copy the code
When the button is clicked, the result is:Constructor (), and componentDidMount() will not be executed.
- Offload: Component offload, so let’s define another component that is displayed at first and unrendered when the button is clicked:
class Jing extends Component {
render() {
return <h2>This is Jingda</h2>
}
componentWillUnmount() {
console.log("Called Jing componentWillUnmount() unmount method")}}class App extends Component {
constructor(props) {
super(props);
console.log("Constructor ()")
this.state = {
counter:1.isShow:true}}render() {
console.log("Execute render()")
return (
<div>
<button onClick={()= > this.btnShow()}>999</button>
{this.state.isShow && <Jing/>}
</div>
);
}
componentDidMount() {
console.log("Called componentDidMount()")}btnShow() {
this.setState({
isShow:!this.state.isShow
})
}
}
Copy the code
When you first open the page:When the button is clicked:It executes a Render method and a componentWillUnmount() method.
5. Component communication
5.1 the father the son
The parent component may pass some data to the child component when presenting it:
- The parent component passes
Property = value
To pass child component data in the form of - The child component gets the data passed by the parent through the props parameter
class Child extends Component {
constructor(props) {
super(props);
this.props = props;
}
render() {
const {name,age,height} = this.props
return (
<div>{name+""+age+""+height}</div>)}}class App extends Component {
constructor(props) {
super(props);
this.state = { }
}
render() {
return (
<div>
<Child name="why" age="18" height="1.88" />
</div>); }}Copy the code
5.2 the father
React is a one-way data flow. In React, the parent component can use props to transfer data to the child component. However, how can the child component transfer value to the parent component?
Define a requirement that in the parent component there is counter=0 and in the child component there is a button that I want to click on to add counter to 1.
- 1. Define a function in the parent component.
btnClick()
- 2. Pass parent component to child component.
<Child btnClick={() => this.btnClick()} />
To add a property to a child component - 3, the child component has a reference to the parent component, still passing data through props, but now using the callback function as the parameter props
<button onClick={this.props.btnClick}>+1 </button>
- 4. When a child component fires an event, it is actually the parent component that executes it
See the full code:
export class Child extends Component {
constructor(props) {
super(props);
this.state = { }
}
render() {
return (
<button onClick={this.props.btnClick}>+1 This is the child component button</button>)}}class App extends Component {
constructor(props) {
super(props);
this.state = {
counter:0}}render() {
return (
<div>
<h2>Here is the parent component: {this.state.counter}</h2>
<Child btnClick={()= > this.btnClick()} />
</div>
);
}
btnClick() {
this.setState({
counter:this.state.counter+1}}})Copy the code
Effect:
5.3 Cross-Components (Not considering context)
In the figure above, we can realize the communication between adjacent components such as A->B and B->A. What if we need to transmit data from A to C directly? We need to transmit data from A to B first, and then from B to A.
This approach, if only the implementation of this generational component value problem, can be solved. But when you pass props of A to B, if B doesn’t need props of A, it’s A waste. And in development, there are a lot of complex component passing values.
Context provides a way to share such values between components without explicitly passing props through layer by layer of the component tree in order to share data that is “global” to a component tree, such as the currently authenticated user, topic, or preferred language.
So let me take a little bit more time to understand this Context, and then I’ll come back and summarize it. That’s all for today.
conclusion
That’s the end of this article, let’s review the knowledge points mentioned at the beginning of the article, I don’t know if you understand more.
- ES6 Class class definition and inheritance
- How to fix this pointing problem in class components
- The life cycle of components in React
- React Components communicate
Knowledge is endless, and I know there are a lot of things I don’t fully understand, so take your time. Thank you for reading this article. After I’ve spent some time summarizing, I hope it’s been helpful to you.
There is also the parameter state inside the component, the props object property that passes the parameter, setState()
In addition, I have not learned the hooks of function components that have no state, and class components that have complex this pointing problems and code redundancy problems.
All worth my time.
I’ll stop there