Create a class component

import React from 'react'; class B extends React.Component { constructor(props) { super(props); } render() { return ( <div>hi</div> ) } } export default B; //extends, constructor, superCopy the code

When you don’t need extra code,

constructor(props) {
       super(props);
    }
Copy the code

You can delete

What to do if the browser does not support this version of ES6: use Webpack + Babel to translate ES6 into ES5.

Props- External data/properties

define

  • propsIs the external data interface of a component

role

  • Accept external data

    • Can only read but not modify write
    • External data is passed by the parent component
  • Accept external functions

    • Calls external functions in child components
    • This function is typically a function of the parent component

The code examples

  1. Initialize theprops
// Construtor and super can be omitted without writing, or a full class B extends React.Com {constructor(props) {super(props); } render(){} }Copy the code

Through the initialization props, enclosing props is the address of the external data object Note: constructor initialization function inside, if you still need to write other things, such as this. The state, etc., that it is necessary to write all these three lines, must write props parameters on it.

  1. The incomingpropsTo B components
class Parent extends React.Component { constructor(props){ super(props) this.state = State} onClick = ()=>{} render(){return <B name={this.state.name} OnClick ={this.onClick}>hi</B> // The parent component passes' props' to the 'B' component, and the external data is wrapped as an objectCopy the code

The props passed in will be wrapped as an object, {name:’frank’,onClick:… ,children:’hi’}

  1. readProps (this. Props. XXX)
class B extends React.Component { constructor(props) { super(props); } render(){ return <div onClick={this.props.onClick}> {this.props.name} <div> {this.props.children} </div> </div> } } // The 'B' component reads' props' from 'this.props. XXX'Copy the code

Note: The child component disallows modification to props

Reason:

  • Modify thepropsThat is, the address of the modified external data. For example,This.props = {/* Another object */}. Since it is external data, it should be updated externally
  • Modify thepropsProperty, for examplethis.props.xxx ='hi. Since this is external data, you should not modify values from internal components
  • The external data is modified by the parent component, the owner of the external data
  1. The hookcomponentWillReceiveProps
  • When the component accepts newprops, triggers special functions called hookshooks
  • It’s now renamedUNSAFE_componentWillReceivePropsBut it has been abandoned. This hook is not recommended

State&setState- internal data

State is the internal data interface of the component

  1. Initialize thestate
class B extends React.Component { constructor(props) { super(props); this.state = { user: {name:'frank', age:18} } } render() { /* ... * /}}Copy the code
  1. readstate
this.state.user
Copy the code
  1. Modify/writestatethis.setState(newState, fn)
this.setState({x: This.state. x+1}) // or this.setState((state)=>({x:state.x+1}))) // This is recommended. // Show merge merges the old state with the new stateCopy the code
This.setstate ((state, props)=> newState,fn) // This is also recommended because, better understood, the callback fn will execute after the write is successfulCopy the code

Note: React only checks the difference between the first layer of the new state and the old state, and copies data missing in the new state from the old state

4. Life cycle

1. constructor

USES:

  • Initialize theprops
  • Initialize thestateBut you can’t call setState at this point
  • Used to writebind this
Constructor (){// this.onclick = this.onclick.bind (this)} // Use the new syntax instead of onClick = ()=> {} constructor(){/* */}Copy the code
  • ifYou just need to initialize propsI don’t have to write itconstructor

This function is called when the React component is created

2. shouldComponentUpdate

USES:

  • Return false to block UI updates
  • Returns true, indicating that UI updates are not blocked

The sample

import React from 'react'; class App extends React.Component { constructor(props) { super(props) this.state = { n: 1 }; } onClick = () => { this.setState(state => ({ n: state.n + 1 })); this.setState(state => ({ n: state.n - 1 })); } render() {console.log(' console.log ') return (<div> App <div> {this.state.n} <button onClick={this.onclick}>+1</button>  </div> </div> ) } } export default App;Copy the code

Suppose you have a situation where you click a button, you do a bunch of things to n, and you find that the value of n is still 1. (Using +1, then -1 simulation)

Click the button and notice that n on the page is still 1. This is no problem. Because the value of n hasn’t changed.

But, log prints twice. Why didn’t n change and render was called?

{n:1} and {n:1} are two different objects with different addresses. React thinks the data has changed and calls the render function. A new virtual DOM is then generated. After comparing the two virtual DOM, it is found that the value of n is 1, there is no difference, so the UI is not updated. But render is called

So it’s unnecessary to call Render, generate a new DOM, compare, find no difference, and stop updating. React mistakenly thinks the address of the data has changed. However, it turns out that the data has not changed. Therefore, the steps in the middle are unnecessary.

Can’t render be called without n being changed? ShouldComponentUpdate hook does this

import React from 'react'; class App extends React.Component { ... . } shouldComponentUpdate(newProps, NewState) {if (newstate.n === this.state.n) {return false} else {return true}} render() {console.log('render once ') . . } export default App;Copy the code

If the new n is the same as the current n, return false, no need to update. When you click the React button, there will be no log and render will not be called.

ShouldComponentUpdate? A: It allows us to manually determine whether component updates are needed. We have the flexibility to set the return value according to the application scenario to avoid unnecessary updates.

React.PureComponentInstead ofReact.Component

React has a shouldComponentUpdate hook that needs to be checked manually, so React has a built-in function called React.PureComponent. Inheriting class extends is equivalent to the functionality of should.

The PureComponent compares each key of the new state to the old state and each key of the new props to the old props before render. If all keys have the same value, no render is performed; Render if any key value is different. (Compare the outermost layer only)

If all keys have the same value, no render is performed; Render if any key value is different.

class App extends React.PureComponent {}
Copy the code

3. render

USES:

  • Create a virtual DOM to display the viewreturn (<div>... </div>)
  • The element of return can have only one root element.
  • If you have two root elements, either use one<div>Wrap it up or use it<React.Fragment></React.Fragment>Wrap it up. You can abbreviate it<></>
  • The difference is:<div>Will be rendered to the page, and<React.Fragment></React.Fragment>It won’t be rendered.

Render can write any JS code,

  • if... else...
class App extends React.PureComponent { constructor(props){ super(props) this.state={ n:1, Array :[1,2,3]} render() {if (this.state.n % 2 === 0) {return <div> even </div>} else {return <span> odd </span>}}Copy the code
  • ? :
class App extends React.PureComponent { ... . } render() { return ( <> {this.state.n % 2 === 0 ? Even the < div > < / div > : an odd < / span > < span >} < button onClick = {this. The onClick} > + 1 < / button > < / a >)}Copy the code
  • &&
class App extends React.PureComponent { ... . } to render () {return (< > {this. State. N % 2 = = = 0 && < div > even < / div >} < button onClick = {this. The onClick} > + 1 < / button > < / a >)}Copy the code
  • But render cannot directly write for loop, because render is required to return, if write return in the for loop, only loop for the first time, directly exit the loop.

    You can use an array, and when you loop, you push the result into the array, and when you’re done, you return the array.

class App extends React.PureComponent { ... . } render() { let result=[] for (let i = 0; i < this.state.array.length; i++) { result.push(this.state.array[i]) } return result }Copy the code
  • Or usearray.map()Realize the circulation
class App extends React.PureComponent { ... . } render(){ return ( this.state.array.map(item=><div key={item}>{item}</div>) ); }}Copy the code

Note: All loops require a non-repeating key

4. componentDidMount

USES:

  • The code executed after the element is inserted into the page relies on the DOM
  • Here you can make AJAX requests to load data (official recommendation)
  • The first rendering executes this hook

Specific explanation:

ComponentDidMount () is called immediately after the component is mounted (inserted into the DOM tree, appearing on the page). Initialization dependent on DOM nodes should be placed here. This is a good place to instantiate the request (making an AJAX request to load the data) if you need to get data through a network request. Of course, the first rendering will execute this hook

Application scenario: Render a div on the page and display the width of the div.

To display the width of a div, you must obtain it if it already exists on the page. You can’t get it if you get it from constructor, because constructor is called after the element appears in memory, before it is mounted to the page. So you need to use this hook to get the width of the div after the component is mounted

class App extends React.PureComponent { constructor(props){ super(props) this.state={ n:1, width:undefined } } componentDidMount(){ const div=document.querySelector('#xxx') const Width = div. GetBoundingClientRect (). The width / / destructor. Const {width} = div. GetBoundingClientRect () enclosing setState ({width: the width}) / / destructor. this.setState({width}) } render(){ return ( <div id="xxx"> hello world {this.state.width}px </div> ); }}Copy the code

The second way to access DOM nodes in a page -Refs

Above we accessed DOM nodes by id. React provides a way to access DOM nodes in a page -Refs

Class App extends react. PureComponent {divRef=undefined Constructor (props){super(props) this.state={width:undefined} this.divref = react.createref () // 1. Refs} componentDidMount(){const div= this.divref.current // 3. current property calls the node const width=div.getBoundingClientRect().width this.setState({width:width}) } render(){ return ( <div ref={this.divRef}> // 2. Hello world {this.state.width}px </div>); }}Copy the code

The advantage is that there are no id conflicts. DivRef is bound to this, the instance, not state when it is created.

5.componentDidUpdate(prevProps, prevState, snapshot)

USES:

  • Execute code after view update
  • This hook will not execute on first render (because it has not been updated)
  • Here,setStateMay cause an infinite loop unless placed in if
  • ifshouldComponentUpdateIf false is returned, this hook is not fired
  • If you want to make an AJAX request, you can do so in thecomponentDidAmountIn the requestLoad the dataYou can also make AJAX requests in this hook, but forUpdate the data
    • Official documentation: If you compare the props before and after the update, you can also do the network request here. (For example, if the userID changes, new user information needs to be retrieved).
ComponentDidUpdate (prevProps) {// 用 于 props) : if (this.props. UserID! == prevProps.userID) { this.fetchData(this.props.userID); }}Copy the code

That is, if the user id has changed, it needs to initiate a network request to get new user information, then the network request will be done in componentDidUpdate, because the view is updated to know that the user information has changed.

6. componentWillUnmount()

USES:

  • Executed when the component is about to be removed from the page (unmounted) and then destroyed (out of memory)
  • Components that have been unmounted will not be mounted again

Such as:

  • incomponentDidMountIt’s listening for window Scroll
    • So you have to startcomponentWillUnmount()Cancel to monitor
  • incomponentDidMountIt creates a Timer
    • So you have to startcomponentWillUnmount()Cancel the Timer
  • incomponentDidMountAJAX requests are created inside
    • So you have to startcomponentWillUnmount()Cancel the request
  • Principle: He who pollutes, he who cures

conclusion

Take a phased look at when these hooks are executed and in what order:

  • constructor()Initialize the state and props to create the element
  • shouldComponentUpdate()Return false prevents updates, and don’t forget return true, otherwise it will become undefined
  • render()Render and create the virtual DOM
  • componentDidMount()The component appears on the page
  • componentDidUpdate()Component updated
  • componentWillUnmount()Components will die