I am trying to call a static method from within another static method in a React component:
class HelloWorld extends React.Component {
static add(a, b){
return a + b;
}
static getDerivedStateFromProps(props, state){
const sum = this.add(2, 2);
return {
sum
}
}
render() {
return <div>Hello World</div>
}
}
Live demo:
But I get the error that this
is undefined, even though MDN says:
In order to call a static method within another static method of the same class, you can use the this keyword.
Why is this
in a static method undefined and how to call the method add
within getDerivedStateFromProps
in this example?
I am trying to call a static method from within another static method in a React component:
class HelloWorld extends React.Component {
static add(a, b){
return a + b;
}
static getDerivedStateFromProps(props, state){
const sum = this.add(2, 2);
return {
sum
}
}
render() {
return <div>Hello World</div>
}
}
Live demo: https://codesandbox.io/s/rmxy909ovo
But I get the error that this
is undefined, even though MDN says:
In order to call a static method within another static method of the same class, you can use the this keyword.
Why is this
in a static method undefined and how to call the method add
within getDerivedStateFromProps
in this example?
5 Answers
Reset to default 8If static method is called with respective context as HelloWorld.getDerivedStateFromProps()
, this
will refer to class constructor inside getDerivedStateFromProps
, this === HelloWorld
.
This is not the case for getDerivedStateFromProps
. It is a hook, its purpose as class static method is to associate provided function with specific component. It's called as a callback by the render without this
context provided. It was designed like that specifically to isolate it from class instance and prevent possible misuses that are common in legacy lifecycle hooks (componentWillReceiveProps
, etc).
The real problem here is that add
shouldn't be HelloWorld
method because it doesn't belong to the class. Since it cannot access component instance, it's only a function that uses the class as a namespace. Using classes as namespaces is antipattern in modern JS. Instead, it could be:
function add(a, b){
return a + b;
}
class HelloWorld extends React.Component {
static getDerivedStateFromProps(props, state){
const sum = add(2, 2);
return {
sum
}
}
...
}
A static method needs to be accessed on the class not an instance. So try this:
HelloWorld.add(2,2);
IMPORTANT UPDATE: This answer is incorrect, sorry. I should have double-checked that @ChrisG's comment was correct before posting it. @estus's answer is the correct answer.
If you paste your code into the Babel playground you can see that calling HelloWorld.getDerivedStateFromProps()
directly indeed works as you intended, even compiling to ES5.
Original (incorrect) answer:
(Note that this answer is only partially incorrect; using this
to call one static method from another is indeed valid syntax in normal circumstances.)
While I personally don't find it as readable as using the class name (HelloWorld
) explicitly, the code you originally posted is valid, and MDN is correct. As @ChrisG pointed out in his comment, the problem is that it doesn't work in code transpiled by Babel to ES5. If you change the target so it transpiles to ES6, it should work, although of course it won't work in browsers that don't support ES6.
Yes, You can't find this object in static method. But you can achive this in other hand. You can declare a global variable and assign "this object" reference to that in constructor. You can check below code:-
import React, {Component} from 'react';
var _this;
class Toastr extends Component{
constructor(props){
super(props)
this.state={
visible: 'hide'
}
_this = this
}
static handleShow = (isSuccess, message, code) => {
_this.setState({visible: 'show', message: message})
setTimeout( function(){
_this.setState({visible: 'hide'})
}, 3000)
}
render(){
return(
<div aria-live="polite" aria-atomic="true" className="toast-conatiner">
<div className="toast-position">
<div className={`toast ${this.state.visible}`} role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-body">
<span className={this.state.isSuccess ? 'text-success' : 'text-danger'}>{this.state.message}</span>
</div>
</div>
</div>
</div>
);
}
}
export default Toastr;
You call static method from another see below code.
static getDerivedStateFromProps() {
HelloWorld.add()
}
HelloWorld.add()
(it does work in the browser, apparently not for transpiled ES6 though) – user5734311 Commented Oct 17, 2018 at 11:55