Class components

  1. Create class components

    If the class defines the component, the class must inherit React’s built-in class: React.Component

    1
    class MyComponent extends React. Component{}

    Among them, the constructor can be omitted. render() must be written, and the return value of render(){return} must also be written. If returning a multi-level structure, it is best to wrap it with ().

    1
    2
    3
    4
    5
    class MyComponent extends React. Component{
    render(){
    return
    }
    }

  1. Location of render(){}

    render is placed on the prototype object of the class for use by the instance. Instances of class components are created by React.render(<MyComponent/>......).

    What happens after executing ReactDOM.render( <MyComponent/> ......)?

    1. When executing this code, React parses the component tags and finds the MyComponent component.

    2. Later, it is found that the component is defined using a class, and then an instance of the class is newly created, and the render() method on the prototype is called through the instance.

    3. Then, convert the virtual DOM returned by render into real DOM, and then render it on the page.


    The this in render() points to the instance object of the class. It can also be called an instance object of a class component.



    The props, refs, and state in the class component instance object are called the three major attributes of the component (instance). The context will also look at it. No other attributes are concerned. These attributes are obtained by inheritance.


  2. Simple components and complex components

    Simple components: components without state (functional components)

    Complex components: stateful components (class components)


  3. state state

    The state of the component drives the page. (Compared to Vue, Vue is a data-driven page)

    React puts the data in the state, and the change of the data will drive the display of the page.

    The state property is on the component instance object, not the class itself.


  4. State initialization

    The initialization of state should be written in the constructor (not shorthand). Because state is a property in the class, and modifying the property value must be written in the constructor (ES5). Shorthand in ES6. state can also be abbreviated outside the constructor.


    constructor(){} What arguments should it accept when it is not omitted (what to pass when new)? Class components are not new by themselves, but React.render helps us new. The official documentation in React states that props should be passed in, that is, constructor(props){}. It should be noted that props are written here because of syntax requirements. If not, the constructor will report an error. I will talk about it in detail later.


    Before simplified

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Weather extends React.Component{
    constructor(props){
    super(props)
    this.state = {isHot:true}
    }
    render(){
    console.log(this); //this is the instance object of the class
    return <h1>Today's weather is very {this.state.isHost?'hot':'cool'}</h1> //The ternary expression processes the state data
    }
    }

    After simplified

    1
    2
    3
    4
    5
    6
    7
    class Weather extends React.Component{
    state = {isHot:true} // Shorthand without writing a constructor (detailed in React.6.5)
    render(){
    const {isHot} = this.state //Use destructuring and copying to take out the keys in the state, and then you can write it shorter.
    return <h1>Today's weather is {isHost?'hot':'cool'}</h1>
    }
    }

    After initializing the state value, the state of the class component can be seen in the Components in the inspect.


  5. click event

    Event binding in native JS (three ways):

    1. .addEvent Listener("click", ()=>{})

    2. .onclick=()=>{}

    3. <button onclick="fn()">


    The third one is recommended in React, which is to bind events directly in tags. (The first two can actually be used, but there are too many document operations, so it is not recommended). React rewrites all events in native JS, and uses the small camel form, that is, onclick is onClick in React. In the event of React, the listener cannot be a string "", is different from native JS. Here it should be written as a variable form of {} .


    React events cannot be written directly onClick={fn()}. This is because fn() means that the function is executed when the event is assigned a value, which is to return the of the function execution The value is directly assigned to onClick instead of executing the function after clicking. This is equivalent to the logic of the second event binding method in native JS. So write onClick={fn}.


  6. this pointor problem (the click event writes the function body outside the class component)

    In the above click event, the function body of fn cannot be written outside the class component (such as below ReactDOM.render). This is because this in the function body points to undefined (Babel prohibits custom functions from pointing to window), but cannot point to the instance object of the class.


    Error analysis

    After writing this.state, an error may be reported: Cannot read property ‘state’ of undefined. means that state cannot be read on undefined. That is, in this.state, this points to undefined. In the same way, in a similar error report, you can directly find the a error in the a.b structure.


    What if you must write the function body outside the class and get the this pointing to the class instance? The idea here is to start with global variables. That is, the global variable let that, and then write that = this in the constructor of the class component. At this time, the outer-class function body can use that to point to the instance object. But this way of writing is unreasonable, because it is too cumbersome, and it will cause the code block of the class component to be scattered everywhere.


  7. This points to the problem (the function body is inside the class)

    Question 1: Where is the function changeWeather() placed in the class? is placed on the Weather prototype object. When changeWeather() is called from a Weather instance, the this in changeWeather() is the Weather instance.

    1
    2
    3
    4
    5
    6
    class Weather extends React.Component{
    constructor(props){...
    render(){...
    changeWeather(){
    console.log(this.state.isHot);
    }}

    Several wrong spellings in render()

    1. <h1 onClick={changeWeather}> This will report an error changeWeather is not defined. This is because only the instance can call the function in the class, which can be found by writing this.changeWeather according to the logic.

    2. <h1 onClick={this.changeWeather}> This will report an error cannot read property ‘state’ of undefined . This means that the left side of state is wrong again, that is, this points to undefined. What is the reason for this? (This error only occurs when the above code block is used. This problem does not occur when using non-constructor arrow functions)

      1. When calling changeWeather through the Weather instance, this in changeWeather is the Weather instance. But here changeWeather( ) is not called from the Weather instance.

        After binding the click event here, the heap address of this.changeWeather is directly bound to the click event of h1, similar to const x=p1.changeWeather in native JS. In this case, when h1 is clicked, the caller of changeWeather is not the Weather instance object, but the window.

        Therefore, since changeWeather is used as a callback of onClick, it is not called through an instance, but directly.

      2. All custom methods in the class have turned on strict mode locally, so they cannot point to window, but can only be undefined.


    Resolve this pointer

    The method in the example is used with <h1 onClick={this.changeWeather}>, that is to change the this point. Code is executed from right to left. this.changeWeather finds the changeWeather on the prototype object, and then bind turns this in the new function into the Weather instance object. This new function is then placed in the instance itself and named changeWeather.

    1
    2
    3
    4
    5
    constructor(props){
    super(props) //initialize state
    this.state = {isHot:false};
    this.changeWeather = this.changeWeather.bind(this);
    }

    That is, after writing this line of code, there is one more method on the instance object of Weather, which is called changeWeather. If it is not written, there is no such method on the instance object, only changeWeather on the prototype. When <h1 onClick= {this.changeWeather}> is clicked, the changeWeather here is not the one on the prototype, but the changeWeather on the instance itself. At this time, according to the search order, the method with the same name is used first on itself.



  1. Array data in state

    state = {todoList:[]}

    state = {todoList:[{},{},{}]}

    It should be noted here that the state in state can only be written as {} object, and the data in the object are all key-value pairs, written as key: value. If key: value is written as key=value, an error will be reported, that is, Parsing error: Invalid shorthand property initialiser.


Share