Honestly, this is my day 1 in ReactJS. I'm learning some small-small things like state
. I've created a small program for the toggle button. It will simply display "Hello world!" or display nothing when the button is toggled. There's one thing that I didn't understand. My code gives me an error when I use this syntax:
toggleHandler() {
const currentStatus=this.state.display;
this.setState({
display: !currentStatus
})
}
this.state is undefined
But the same code works perfectly If I change the syntax to a fat arrow function:
toggleHandler=()=> {
const currentStatus=this.state.display;
this.setState({
display: !currentStatus
})
}
I'll not waste your time. I've created an stackblitz . Experts on the internet say that any call to this.setState()
is asynchronous. So I tried using call back function
and IIFE
but got myself more confused and over-complicated. Please correct me. I'm sorry this is a very childish question.
There are a couple of ways.
One is to add in the constructor. ES6 React.Component doesn't auto bind methods to itself . You need to bind them yourself in constructor. Like this
this.toggleHandler = this.toggleHandler.bind(this);
Another is arrow functions toggleHandler = (event) => {...}.
And then there is onClick={this.toggleHandler.bind(this)}
Yes, any setState call is asynchronous. You can check your log that it changes his status but not manipulate the dom. For manipulating the dom Any asynchronous call should be via a callback function.
you can bind any state with this arrow function or this.state.bind(this).
What the error message is telling you is that the this
object doesn't contain a property called state
. What exactly this
refers to is a constant source of confusion in JS, except when inside an arrow function. Inside an arrow function, this
always refers to the context the arrow function appears in.
The issue here is in the first example, this
refers to the context sent to the handler by the onClick event. This context does not contain a state
property. However, inside the arrow function, the this
keyword will refer to the JavaScript class that your arrow function exists in. This class does have the state
property.
To get around this, you can use bind
(which outputs a copy of your function with the context set to whatever you supply it with. Or just use arrow functions. If it were me I would take the latter approach since this
has better defined and more consistent behaviour inside an arrow function. If you do want to use bind
, you would do this in your event handler declaration like so:
onClick={this.toggleHandler.bind(this)}
The way you can use functions and previous state.
1- Binding in constructor
constructor() {
this.toggleHandler=this.toggleHandler.bind(this);
}
can define like this
toggleHandler=()=>{
this.setState(prev=>({
display: !prev.display
}))
}
2- arrow function (don't need to bind in constructor)
toggleHandler=()=>{
this.setState(prev=>({
display: !prev.display
}))
}
3- Inline binding
<Button onClick={this.toggleHandler.bind(this)}>Toggle</Button>
function code
toggleHandler=()=>{
this.setState(prev=>({
display: !prev.display
}))
}
4- Inline arrow function
<Button onClick={()=>this.toggleHandler()}>Toggle</Button>
function code
toggleHandler=()=>{
this.setState(prev=>({
display: !prev.display
}))
}
Note - Recommended to avoid inline functions for better performance
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.