“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.
\