How does 'this' work in Lifecycle methods? - javascript

I'm new to react js and have been reading the react docs. In one of the examples, a property (this.timerID) is defined within a lifecycle method (and not in the constructor) and it goes on to be used in another method. I'm having trouble understanding how 'this' in the property helps increase its scope.
The exact document is on, https://reactjs.org/docs/state-and-lifecycle.html. I have been conducting further research about 'this' on https://www.codementor.io/dariogarciamoya/understanding--this--in-javascript-du1084lyn?icn=post-8i1jca6jp&ici=post-du1084lyn. I don't know if its my understanding of ES6 class methods or 'this' that is causing a problem.
class Clock extends Component {
constructor(){
...
}
componentDidMount(){
this.timerID = setInterval(() => this.tick(), 1000)
}
componentWillUnmount(){
clearInterval(this.timerID);
}
}
Apologies if the question is a bit vague, and any help is appreciated.

this refers to the current instance of the component. So in your example you are setting the interval to your instance.

when you use this keyword with a variable or object then it is referred under the present scope of it. Here the ComponentDidMount is a class lifecycle method and when a variable is assigned with this keyword inside any method of a class, then it means that it is accessing the variable of the Class rather than its own variable.
Here, in your example, the this.timerID variable is used by ComponentDidMount in the scope of the entire class to change the state variable and then render the component. If you use var timerID in ComponentDidMount then it will work as same but if you want to use timerID in other functions then this.timerID will show as undefined as it will only available when mounting and its scope in only inside that method.
The thing is that the everything you are using must have a defined scope.
Here, this keyword just elaborated the scope for the variable to be used inside the class. Thats it, there are just proper ways to manage the variables/objects to get your work done.

Related

In React why is the render method bound to component instance but not custom methods?

In a class, why is the render method automatically bound to the component instance but custom methods e.g. event handlers aren't?
I understand using the bind keyword to make these event handlers work but was just trying to find an answer why "this" can be referenced in the render method but why it's also not automatically bound in event handler methods?
why is the render method automatically bound to the component instance
It isn't bound. It's just that react always calls the render function using the correct context.
For normal functions, the value of this is determined by how you call the function. In the following code, example. is the part that says what the value of this will be inside the function.
const example = {
value: 'abc',
printValue: function () {
console.log(this.value);
}
}
example.printValue(); // abc
But if you call the function in a different way, you can get a different value of this.
const example = {
value: 'abc',
printValue: function () {
console.log(this.value);
}
}
const temp = example.printValue;
console.log(temp === example.printValue); // true (they're literally the same function)
temp(); // undefined, or throw an exception depending on if we're in strict mode
So every time react calls the render function, it calls it the first way (or something equivalent to it), not the second way.
Citing React's docs:
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.
Defining them as arrow functions though, still at instance level, will change the scope to the component's instance. So all other methods like render, componentDidMount are part of the class' definition and are not event handler, which means this will point to the instance in them (the usual JavaScript behaviour for such methods).
And lastly, you can always call a method with a different scope with apply or call, changing what this refers to in those methods.

Still not understanding .this after reading articles

I'm a JS/React beginner who has read a few articles on the this keyword on JS, but remain confused.
Namely, I've consulted Tyler McGinnis's React and The Complete Javascript on Udemy.
This keyword is a fairly complex topic imo, but from these two sources I know .this refers to the global scope by default, but refers to the object in question when it is defined within a method. I also know that .call/apply/bind can give us a hint on what the .this refers to.
My question is, when do you actually write the .this keyword when you are writing your programs? The sources above seemed to focus on understanding why others might've used the keyword, but not necessarily when you need to do it. Thus, I always get confused when tutorials seemingly randomly throw in a this/bind etc everywhere
In terms of specific examples, I have :
1. One in the context of states:
I've encountered apps before learning about the .this concept which do not use the .this keyword. No specific examples for this, but shouldn't you use .this most of the time then?
Apologies if this is a silly question -- sometimes I wonder whether it is better to analyze/dissect the rationale for each part in coding or just to learn coding as just the way things are much like a child learns a language naturally without questioning grammar rules
In this example, we are passing down a prop called onDelete, but I do not understand why we need to bind. Does this mean we are binding the passed down onDelete to props.id which was also passed down?
The important part is you took the time to research. Personally I do not recommend using React to learn about this. When you extend a React component, your this prototype inherits from React.Component, so there's a lot of React-specific conventions there already. Instead, consider this example where I call this directly
function SimpleQueue({ size }) {
this.size = size
this.buffer = []
}
SimpleQueue.prototype.push = function(item) {
this.buffer.push(item)
if (this.buffer.length > this.size) {
this.buffer.shift()
}
return this
}
SimpleQueue is just a simple queue implementation using an internal array. You can think of this as a reference to the current instance of SimpleQueue, whatever that may be. I use this specifically in the example above to access the internal array as this.buffer. I can then use an instance of a SimpleQueue like so
const mySimpleQueue = new SimpleQueue({ size: 3 })
mySimpleQueue.push(1) // SimpleQueue { 1 }
mySimpleQueue.push(2) // SimpleQueue { 1, 2 }
mySimpleQueue.push(3) // SimpleQueue { 1, 2, 3 }
mySimpleQueue.push(4) // SimpleQueue { 2, 3, 4 }
Note: my example does not use class, but it is the same because classes are syntactic sugar for the prototype-based programming model
shouldn't you use .this most of the time then?
Yes, for class based react components, you should almost everywhere use this., for access props, state, handlers, calling methods etc.
constructor is an exception ... this.state is created, props are constructor argument.
Handlers declared using handleChange(e) {} syntax needs .bind(this) to be able:
to operate on this.state;
to use this.setState() (react component method derived from base class);
to use other methods defined in this component.
Usually event handlers are binded in constructor in the form like:
this.handleChange = this.handleChange.bind(this);
<button onClick={this.handleClick} />
Event handlers defined using ES6 'arrow syntax' fn = () => {} are autobinded to this.
Also handlers defined using 'normal function syntax' but assigned using 'arrow syntax' in render doesn't need binding:
<button onClick={(e) => this.handleClick(e)} />
Bad news - every render call crates new ref ... at least not optimal in react ... so ... use arrow declaration (or bind in constructor).
we are passing down a prop called onDelete, but I do not understand why we need to bind
Why? Probably passed handler not binded - rare requirement to bind handler to different object/component context (different this).
"this" is not a complex topic. people make it complex.
you have
handleTitleChange=(title)=>{
this.setState({})
}
When you say this.setState() you want this to refer the class component that you defined the handleTitleChange() inside. Arrow functions AUTOMATICALLY allow you to set “this” when the function is defined. That is why it is said that arrow functions are lexically bound to this. When our component is getting rendered by javascript for the first time, it checks inside and sees that there is handleTitleChange() points to arrow function. The moment it sees “this”, it is going to automatically bind “this” to the place where the arrow function is defined in the the first place. The context of that function is the TimerForm component.
But by default javascript does not set its scope of “this” on functions. "this" is dynamically scoped, it does not matter where the function is written, it matters how the function is called. That is why we have to actually explicitly state what context you want “this” to be for us. We want “this” to be our class component and the method in which we can do it is to define in our constructor(). If you write above code like this :
handleTitleChange(title){
this.setState({})
}
Now,in the above function this refers to the class but when you pass the reference to be called by another component or function, you are not passing its "this" anymore. New "this" will be assigned by object which calls "handleTitleChange(title)". We have to make sure that when we call handleTitleChange(title), its "this" value always points to TimerForm class. So we go to constructor(){}. Because our constructor() is the code that runs first before anything gets called. We want to make sure that the context of this is correct in all of our methods before any code gets written.
constructor(){
super()
console.log(this) // it will log TimerForm class
this.handleTitleChange=this.handleTitleChange.bind(this)
//bind(this) `this` refers to the TimerForm
}
bind() is a method on any function that returns a new function with a new execution context. now our handleTitleChange method learnt that this inside of it, will refer to the TimerForm class component.
to your 3rd question. props.onDelete is a function that's passed down, it's binding on this, which is the current execution context in <TouchableOpacity>, props.id is the argument of the onDelete function.
this is the old way, I believe an arrow function will do the same thing, () => props.onDelete(props.id)
And in react world/javascript land, function components/object destructing/arrow function are taking more ground these days, might be a reason you see less/none this in the codebase.

Declaring a variable inside a ES6 class.

I want to understand how we can declare a variable inside the class?
For example, Until now, I have been declaring it like this
let displaySearchCrypto = []
let updateCoinData = [];
class cryptoTicker extends PureComponent {
and using it throughout my class (I mean inside my class like this)
componentDidUpdate() {
updateCoinData = [...this.props.cryptoLoaded];
if (updateCoinData[i]["short"] == tradeMsg.coin ) {
//Search for changed Crypto Value
updateCoinData[i]["long"] = tradeMsg["message"]["msg"]["long"]
updateCoinData["short"] = tradeMsg["message"]["msg"]["short"]
or
search = () => {
displaySearchCrypto.push({
no: {i},
key: this.props.cryptoLoaded[i]["long"],
short: this.props.cryptoLoaded[i]["short"],
long: this.props.cryptoLoaded[i]["long"],
price: this.props.cryptoLoaded[i]["price"],
mktcap: this.props.cryptoLoaded[i]["mktcap"],
perc: this.props.cryptoLoaded[i]["perc"],
vwapData: this.props.cryptoLoaded[i]["vwapData"]
})
But, Since I am going to use inside a single class only, I think I shouldn't declare in global scope class. So my question is, How to declare a variable inside the class?
You don't declare variables inside a class. You declare variables within a constructor or method, or you create properties of an instance (or the class itself, "static" properties, which are properites on the constructor function).
If you're using modules, your first code block won't create globals, it will create module-globals (global only to code in that module). If that module contains only that class, and you mean for the variables and the arrays they refer to to be shared by all instances of that class, you can keep doing it that way.
But I suspect you want them to be properties of the instance, not shared between instances, in which case you define those properties in the constructor:
constructor(props) {
super(props);
this.displaySearchCrypto = [];
this.updateCoinData = [...this.props.cryptoLoaded];
}
Then use them by referring to the instance (usually via this.).
Yes I think T.J Crowder anwsers this very nicely. However I would like to add the following:
The task of Objects and classes is to provide abstractions of certain entities. In the case of ReactJS these objects are react components. The advantage of putting all the data related to a certain component inside an object provides the following advantages:
Everything inside the object is automatically namespaced, this helps in preventing potential naming conflicts
We can hide some of the implementation details inside the object. Then use this object in another place where we don't have to bother with how a certain methods are implemented, we just have to know how to interact with it.
Also remember:
Classes have:
No variables but properties which are associated with the object.
No functions but methods which are associated with the object.
Furthermore it is important to know that JS uses prototypal inheritance. The class keyword is merely syntactic sugar build on top prototypal inheritance.

why should I use bind(this) with a method in a class?

Given the documentation
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
I'm currently following a tutorial about creating a blockchain using node.js
https://developers.caffeina.com/chiccocoin-learn-what-is-a-blockchain-by-creating-one-in-nodejs-12929a89208b
But what I don't understand in the following example (code provide by the tutorial I'm following) is why should I bind the keyword 'this' to a method which belong to a class. Given the function newBlock() belong of the class Blockchain, it should have access to the 'this' and all of the variable related to the class Blockchain.
class Blockchain {
constructor () {
this.chain = []
this.newBlock = this.newBlock.bind(this)
this.newBlock(100, 1)
}
newBlock (proof, previousHash) {
const block = this.chain.length + 1
}
}
Does anyone can explain me why should I use bind(this) with a method in a class ? Actually it may be possible that I misunderstood the purpose of bind(this) so that would be great if you could point me out what did I misunderstand.
Thanks :)
Bind will create a copy of the function which will guarantee that the reference of "this" in function newBlock will point to Blockchain. If a new function (let's call it function readBlocks) were to invoke newBlock, it's this context would instead point to readBlocks instead of Blockchain. Binding will allow you to use newBlock without worrying about it's this context being dynamic.
class definition the way you did, in javascript, is still doing prototypal inheritence behind the scenes. This class definition is malleable and you can add more methods to it by just adding more methods to it's prototype. So the class syntax is more like syntactic sugar (not completely, but for most practical purposes) for the normal prototypal inheritence done using functions.
Given that background, this binding in javascript was always done at runtime (except for arrow functions). The context in which a particular method is called determines the this binding. It's not bound at the time of defining the method. But that rule does not hold if you prebind the method to a particular context, like you did in your example with .bind.
If you had not done that, someone could have called the method newBlock like this
let a = new Blockchain()
let b = new Blockchain()
a.newBlock.call(b, proof, previousHash)
And since binding of this is done at runtime, in the above case, the method newBlock will be called with this refering to object b. But that will not happen if you prebind the method using .bind.
It's tricky. But main takeaway is that the runtime binding rules of this in javascript still hold for the new class syntax. Hope it helped.

Having trouble understanding the dynamics of this vs self vs nothing.

Consider the following chunk of code:
function Bar() {
var _self = this;
this.addPin = function (param1) {
console.log('addPin');
}
function endPin(param1) {
console.log('endPin');
}
_self.addPin(1);
this.addPin(1);
addPin(1); // failse
endPin(2);
this.endPin(2); // fails
}
var foo = new Bar();
foo.addPin(1); // works
foo.endPin(1); // does not work
From what I understand from playing with this code, the function declaration of endPin effectively makes it a private method to any outside callers. While this.methodHere type of declaration makes it a public method.
What I am not clear on is the usage of this in the class itself. this refer to the instance of the class. Why, in that case, can't I use this.endPin inside the class. Conversely, why do I have to use this.methodHere syntax when referring to addPin (which was declared using this.methodHere syntax).
Finally the difference between this and _self - I've read that _self preserves the original state of the class (or this). How does it do that if it's a reference supposedly pointing to the same memory location? How is this different from _self in this particular example?
You have asked a lots of questions here, so lets try and break them down.
this refer to the instance of the class. Why, in that case, can't I
use this.endPin inside the class.
Because endPin is not part of the class, it a local function inside your constructor.
Conversely, why do I have to use this.methodHere syntax when referring
to addPin (which was declared using this.methodHere syntax).
Because addPin is part of the class, basically the reverse of the first question. Doing func() does not automatically call the function of class.
How is this different from _self in this particular example?
In this case it's not, but if you used _self inside your local function, it would capture scope so it's still pointing to this of the class, instead of the functions scope.
You can't use the this.endPin because the function is not defined in the class itself but inside a function.
If you write:
function Bar() {
// do whatever
this.endPin(2); // now it should work
}
function endPin(param1) {
console.log('endPin');
}

Categories