+ 3

Why cant I access 'this' in this react code? The problem is only in the increment method. The other methods work just fine. Why?

import React, { Component } from 'react'; import ReactDOM from 'react-dom'; class Counter extends Component { state = { count: 1 }; handleIncrement() { console.log(this.state.count); } render() { return ( <div> <span className = {this.getBadgeClasses()}> {this.formatCount()}</span> <button onClick={this.handleIncrement} className = "btn btn-secondary btn-sm" > Increment </button> </div> ); } getBadgeClasses() { let classes = "badge m-2 badge-"; classes += this.state.count === 0 ? "warning" : "primary"; return classes } formatCount(){ let {count} = this.state; return count === 0 ? 'Zero' : count } } ReactDOM.render(<Counter />, document.getElementById("root"));

30th Apr 2020, 3:28 PM
Sajid
Sajid - avatar
19 Respostas
+ 8
I know that beginners learn from tutorials, mostly using class component to build react app, which was the only way to do before react release react hooks. Bear in mind, most tutorials were built before react hooks released. Nowadays react official advises us to focus on learning react hooks which using functional components. sajid chowdhury I just rebuilt your counting app using react hooks. You can compare how much better React Hook in writing easy to understand, cleaner code by comparing the 2 methods. React Hooks get rid of the extra 'this', this.state and constructor function which are needed on class functions. And we do not have lose of context issue on React Hook since we don't have to define components in class. https://code.sololearn.com/WAYFbLK8m1W6/?ref=app https://code.sololearn.com/Wdt22iNig4Lu/?ref=app
1st May 2020, 4:22 AM
Calviղ
Calviղ - avatar
+ 5
The reason why the event method need to be reassigned with bind(this) in the constructor is because of the event would lose its context when it's invoked. If you don't like to use bind method, arrow function can also help assignment of current context to the event method. Eg. <button onClick={ ()=>this.handleIncrememt } ....>
1st May 2020, 12:51 AM
Calviղ
Calviղ - avatar
+ 3
sajid The purpose of the bind() method is to set the parent class so that 'this' keyword can know which class to refer to. So .bind(this) means, you are referring to the same class. And hence later, when you'll use 'this' keyword to call a method, it will know it's parent class and work properly. Method in a react component won't work as long as you don't 'bind' them. There are few ways to 'bind' methods in a component. You can check the main react documentation too regarding 'binding'. Calviղ showed one way already. You can also bind the method when you call it. Like so : <span className={this.getBadgeClasses()}> {this.formatCount.bind(this)}</span> Another thing you can do is to use the arrow function when defining the method. const formatCount = () => { // code }
30th Apr 2020, 10:34 PM
Arb Rahim Badsa
Arb Rahim Badsa - avatar
+ 3
Calviղ explained it very well so i'll just drop some home reading resources 😬 https://reactjs.org/docs/handling-events.html Which provides the following link: https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/
1st May 2020, 8:04 AM
Burey
Burey - avatar
+ 2
They didn't add parentheses so the function is not called inmediately They explained the "this" issue as well: " You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called. This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method. " I wouldn't say it's the best resource to learn from. There are plenty of resources you can find, but the quality of them is sometimes hard to determine (especially when you are starting to learn). Most of them are made by people like you and me that just want to pass some knowledge along.
1st May 2020, 10:31 AM
Burey
Burey - avatar
+ 2
👌
1st May 2020, 10:52 AM
Burey
Burey - avatar
+ 1
Move state into constructor, and also bind all methods with this in constructor as well. constructor(props) { super(props); this.state = { count: 0 }; this.handleIncrement = this.handleIncrement.bind(this); this.formatCount = this.formatCount.bind(this); this.getBadgeClasses = this.getBadgeClasses.bind(this); }
30th Apr 2020, 5:02 PM
Calviղ
Calviղ - avatar
+ 1
Arb Rahim Badsa only the handle increment method didn't work. All methods do not need to binded. You're probably wrong about this. I perhaps should have mentioned the line. I will do it now.
30th Apr 2020, 11:00 PM
Sajid
Sajid - avatar
+ 1
sajid chowdhury Lol, I ain't wrong either. Those are the ways that react recommends. But I think you forgot to add '()' after the handleIncrement method. Perhaps this could be the reason. Lol
30th Apr 2020, 11:11 PM
Arb Rahim Badsa
Arb Rahim Badsa - avatar
+ 1
sajid chowdhury Maybe because it doesn’t know it’s parent 🤷‍♀ Let's mention Burey sir.
30th Apr 2020, 11:28 PM
Arb Rahim Badsa
Arb Rahim Badsa - avatar
+ 1
Your call to handleIncrement is happening only when a window event is targeted, in this case, the button click, so 'this' refers to the window object. There are 2 ways to prevent this normal behaviour in react. You can call 'super()' in the constructor and explicitly do the bindings for every method or you can simply use arrow functions like that : handleIncrement = () => console.log(this.state.count)
2nd May 2020, 4:05 AM
Maher Najar
Maher Najar - avatar
0
Calviղ I asked why it's not working. I didn't ask for the solution
30th Apr 2020, 8:39 PM
Sajid
Sajid - avatar
0
Arb Rahim Badsa no, I didn't use () because I'm not calling the method. I'm simply passing the method as a reference.
30th Apr 2020, 11:17 PM
Sajid
Sajid - avatar
0
sajid chowdhury And I guess that is why you need to bind 🤔.
30th Apr 2020, 11:23 PM
Arb Rahim Badsa
Arb Rahim Badsa - avatar
0
Arb Rahim Badsa but why does passing a method as a reference require it to bind?
30th Apr 2020, 11:25 PM
Sajid
Sajid - avatar
0
Burey sir could you please help a bit?
30th Apr 2020, 11:32 PM
Sajid
Sajid - avatar
0
Calviղ I guess it was released recently. I was following a 1 year old tutorial from mosh and I really want to complete it. So, should I because it doesn't use react hooks? I understood now. Basically this behaves differently depending on how the function is called. If the method is called on an object, this refers to the current object. If it's called as a stand alone function, this refers to the window object or undefined if in strict mode. Thanks for your explanation.
1st May 2020, 9:38 AM
Sajid
Sajid - avatar
0
Burey I just saw the documentation. And I'm think why they didn't they explain why removed parentheses from here: <button onClick={activateLasers}> Activate Lasers </button> Is this the best resource for learning react?
1st May 2020, 9:42 AM
Sajid
Sajid - avatar
0
Burey Thank you very much. It helps a lot.
1st May 2020, 10:36 AM
Sajid
Sajid - avatar