“This is the second day of my participation in the First Challenge 2022.

React this points to the problem

First, set up a React environment

npx create-react-app hello-react
Copy the code

Write a base code in the index.js file

class App extends React.Component{ constructor(){ this.name } handleClick(event){ console.log(this); Render (){return (<button onClick={this.handleClick}> Click Me </button>); } } ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') );Copy the code

There is a very strange phenomenon in this.

As usual with the onClick event in JSX in the Render function, the context object of the method in the bound class should point to the class instance,

But the actual result is undefined.

It feels a little counterintuitive.

But you can actually see this if we convert JSX to object operations

Simulate the Render function

The react rendering process is actually quite complicated including

JSX -> virtual Dom -> render function

Let’s simplify this by looking at the Dom rendering function that is the final product of this simulation

renderDom() { var btn = document.createElement("button"); var t = document.createTextNode("Click Me"); btn.appendChild(t); function createCallback(fn) { return () => fn.apply() } btn.addEventListener("click", createCallback(this.handleClick));  document.getElementById("root").appendChild(btn); return }Copy the code

You might be interested in the createCallback function, but I’ll save that for the React principle. The handleClick method is not bound directly.

Then create your own renderDom function instead of the ReactDom. Render function

 const app = new App()
 app.renderDom()
Copy the code

Declare the app instance and render it once.

The reason this does not point to an instance

Because the React callback uses the Apply method, the specified context is the context object, not the instance.

function createCallback(fn) {
      const context = undefined
      return () => fn.apply(context);
}
Copy the code

And of course you can’t have this pointing to an app instance

Solution 1: Bind on the constructor

Bind all methods to the app instance in the constructor

constructor(props) { super(props); HandleClick = this.handleclick.bind (this)}Copy the code

Solution 2: Bind the render function

The second approach is similar to the first, except bind on the render function.

render() {
    return (
      <button onClick={this.handleClick.bind(this)}>
        Click Me
      </button>
    );
}
Copy the code

Solution 3: Handle uses the arrow function

Another idea is to use arrow functions and lexical scopes.

handleClick = (event) => { // debugger console.log("click", this); // 'this' is undefined}Copy the code

Method 4: Bind event functions using arrow functions

The last one is similar to the one above using the arrow function but in JSX

render() {
    return (
      <button onClick={() => this.handleClick}>
        Click Me
      </button>
    );
}
Copy the code

The interview guide

React’s this problem is lost. The cause of the loss and the solution involve all aspects of the problems pointed to by this. Is a touchstone for Javascript fundamentals.

\