2022 is coming, the front end development is very rapid, now the front end is no longer writing simple pages, with the Web big front end, engineering is becoming more and more hot, there are also many frameworks. Many companies are not only using a single framework, as the front end development of the two most popular frameworks in the country, are necessary to master. Therefore, I decided to learn React at the end of this year when the epidemic was raging, so as to gain more competitiveness in my future job search.
Learning stage, if there is something wrong, welcome to leave a message in the comment area, I timely correction
This article has been serialized, other chapters portal β¬οΈ
Chapter 1 – Understanding JSX syntax
Chapter 2 – Function components and Class components
Chapter 4 – Event Handling
Chapter 5 -Ref and Refs
Chapter 6 – Life Cycle
Chapter 7 – Communicating Context across Components
Chapter 8 -React Hooks
Props and State
React uses props to receive data, and state maintains its own data. The props property is read-only and cannot be modified. If the data is modified, we can only modify the state of the parent component.
Props
π‘ props can accept multiple types of data, even one component, which is very flexible, we can pass any data through props
Passing ordinary data
import {Component} from 'react'
import ReactDOM from 'react-dom'
class Demo extends Component {
constructor(props) {
super(props)
this.state = {
date: '2022-01-14'}}render() {
return(
<Date date={this.state.date} />)}}function Date(props) {
console.log(props)
return (
<h1>{props.date}</h1>
)
}
ReactDOM.render(<Demo />.document.querySelector('#root'))
Copy the code
Let’s print props so we can see what it looks like, okay
Pass a piece of structure
import {Component} from 'react'
import ReactDOM from 'react-dom'
class Demo extends Component {
constructor(props) {
super(props)
this.state = {
date: '2022-01-14'}}render() {
const element = <h1>{this.state.date}</h1>
return(
<Date date={element} />)}}function Date(props) {
console.log(props)
return (
<div>
{props.date}
</div>
)
}
ReactDOM.render(<Demo />.document.querySelector('#root'))
Copy the code
We’ve changed the code here so that passing a structure through props seems to work
The date attribute (props) is a REACT DOM element. The date attribute (props) also has a children attribute (props), which contains the date of the parent component. This means that anything written in the middle automatically adds an attribute to props.
The children property of props
Next, try passing a structure or text between components
import {Component} from 'react'
import ReactDOM from 'react-dom'
class Demo extends Component {
constructor(props) {
super(props)
this.state = {
date: '2022-01-14'.name: 'Ming'}}render() {
return(
<Date date={this.state.date}>
{this.state.name}
</Date>)}}function Date(props) {
console.log(props)
return (
<div>
<h1>{props.date}</h1>
</div>
)
}
ReactDOM.render(<Demo />.document.querySelector('#root'))
Copy the code
If we pass a structure or a component, then it’s an object. If we pass multiple structures or components, So its value is an array
The code is omitted, and the result of the console is directly captured:
If children were an array, we could iterate over all the children
State
π‘ state provides the data used to maintain components, similar to the data function in VUE
Only class components have state. It provides the data that the component initializes. We can use this.state. Get the property name. So let’s see how we can modify the state data. Ok
React provides the only way to change state: setState()
For example, a small requirement, implement a counter function, click a button can add or subtract data
class Demo extends React.Component {
constructor() {
super(a)this.state = {
counter: 0
}
}
handelClick = (num) = > {
this.setState({
counter: this.state.counter + num
})
}
render() {
return(
<div>
<h2>Current count: {this.state.counter}</h2>
<button onClick={()= > {this.handelClick(1)}}>+ 1</button>
<button onClick={()= > {this.handelClick(-1)}}>- 1</button>
</div>
)
}
}
ReactDOM.render(<Demo/>.document.querySelector('#app'))
Copy the code
So let me write it this way for the moment, because we’re dealing with this problem, and we’ll talk about it, and you can see that we’ve successfully modified the data using the setState method
SetState use
In React, the setState method is the only way to modify data. It is a callback function that takes an object as an argument or a callback function as an argument. π about setState
The object parameters
π‘ Problem: When we call setState and print the data immediately, it will not display the updated data, but the last one, and multiple setStates will be merged into one, and the later one will overwrite the previous one, as shown in the figure below
add = () = > {
const { count } = this.state
this.setState({
count: count + 1
})
this.setState({
count: count + 2
})
this.setState({
count: count + 1
})
console.log(count)
}
Copy the code
React will put the object parameters received by setState into an update queue, extract and merge all the objects together, and then trigger component updates. Therefore, multiple calls to setState will only trigger one re-render, since DOM updates are expensive
The callback parameter
π‘ think: If we need to call multiple times and the data depends on the last result, is there a way to solve this problem? – In addition to object arguments, setState can also receive a callback argument, which takes a single argument that is the result of the last execution
add = () = > {
const { count } = this.state
this.setState((pre) = > {
return {
count: pre.count + 1}})this.setState((pre) = > {
return {
count: pre.count + 1}})this.setState((pre) = > {
return {
count: pre.count + 1}})console.log(count)
}
Copy the code
Note that both object and function callbacks retrieve the data immediately after the setState call, so we need to retrieve the data after the component is updated, not immediately
SetState can take two functions as arguments, and the second function argument will wait for setState to execute before executing, so we can also fetch data in the second callback argument
SetState Synchronous or asynchronous
Conclusion π‘ : SetState is synchronous and behaves asynchronously due to React optimizations. SetState only behaves asynchronously in React raised events (such as onClick) and hook functions. This is synchronized in both native events (select DOM listener addEventListener) and setTimeout
π about setState synchronization asynchronous official website
React Event Handling
class Demo extends Component {
constructor(props) {
super(props)
this.state = {
date: '2022-01-14'.name: 'Ming'.count: 0
}
}
handleClick = () = > {
this.setState({
count: this.state.count + 1
})
console.log(this.state.count, 'First log')
this.setState({
count: this.state.count + 1
})
console.log(this.state.count, Log the second time.)
setTimeout(() = > {
console.log(this.state.count, Log the third time)
this.setState({
count: this.state.count + 1
})
console.log(this.state.count, 'Fourth log')
this.setState({
count: this.state.count + 1
})
console.log(this.state.count, 'Fifth log')})}render() {
return(
<div>
<h1>Display current count: {this.state.count}</h1>
<button onClick={this.handleClick}>button</button>
</div>)}}Copy the code
We can see that the second log is printed immediately after the setState adjustment, but the initial value is still obtained. This also shows that multiple calls to React will be merged into a queue. Instead of updating the state immediately, it will update the state once, which behaves like async. And then after the third log, it’s already updating state immediately, which means it’s synchronized in setTimeout.
React hook function
componentDidMount = () = > {
this.setState({
count: this.state.count + 1
})
console.log(this.state.count, 'First log')
this.setState({
count: this.state.count + 1
})
console.log(this.state.count, Log the second time.)
setTimeout(() = > {
console.log(this.state.count, Log the third time)
this.setState({
count: this.state.count + 1
})
console.log(this.state.count, 'Fourth log')
this.setState({
count: this.state.count + 1
})
console.log(this.state.count, 'Fifth log')})}Copy the code
We changed the handleClick function to React lifecycle hook function componentDidMount. The printable result is the same as in the event handler.
Why doesn’t React update this.state synchronously?
React queues setState to be executed at once, thus avoiding the problem of components being rendered multiple times. If not, the performance overhead and experience would be bad. An update only needs to be re-rendered once. There is no need to re-render multiple times to cause a redraw
SetState Immutable power
We know that in JS, the simple type of data is directly occupied by the memory, and the complex type of data is only a reference, when we modify the simple type of data, is directly can be modified out. When we modify a complex type of data, such as obj.name = ‘xiaoming’, its reference address is not changed, it still points to the same memory space
export default class Index extends Component {
constructor(props) {
super(props)
this.state = {
list: [{name: 'Ming'.id: 1
},
{
name: 'little red'.id: 2}}}]shouldComponentUpdate(nextProps, nextState) {
console.log(nextState)
if(this.state.list ! == nextState.list) {return true
}
return false
}
addName = () = > {
const obj = {name: 'xiao gang'.id: 3}
this.state.list.push(obj)
this.setState({
list: this.state.list
})
}
render() {
console.log('Render function executed');
return (
<div>
<ul>
{
this.state.list.map((item) => {
return <li key={item.id}>{item.name}</li>})}</ul>
<button onClick={this.addName}>button</button>
</div>)}}Copy the code
For example, if we have a small requirement, click on the button to add a new piece of data to the array, and in the shouldComponentUpdate hook function, we should update the component by checking whether the list changes. If we are pushing an object directly into the list, we know that the array is a reference type. The referenced address does not change and does not change before and after state, resulting in return false and the component does not update. But when you print nextState, it’s already added, and the component doesn’t update no matter how many times you click it, because the reference address never changes
Let’s modify the code:
addName = () = > {
const arr = [...this.state.list]
arr.push({
name: 'xiao gang'.id: 3
})
this.setState({
list: arr
})
}
Copy the code
Using the es6 extension operator, we extend the array to a new array, not the original reference address, but a new array of reference addresses. After we add the data and reset the list value, we can see that the page is updated and re-rendered.