Reputation: 45
My Letter
component needs to be reused multiple times, with minor changes in what happens in its constructor. My idea was to pass a function as props to Letter
, so I can call it in the constructor. However, I'm having a problem with this
.
In the code below, when I invoke this.props.setMessage.call(this)
, this
refers to Container
and not Letter
, and so the state of Letter
remains unchanged. I can see that this
refers to Container
by inserting console.log(this)
in the body of the setMessage
function in Container
.
How do I bind this
such that the state of Letter
will change when I run this code?
Source:
export class Container extends React.component {
...
setMessage = () => {
this.state.message = 'hello';
}
render () {
return (
<div>
<Letter setMessage={this.setMessage} />
</div>
}
}
export class Letter extends React.component {
constructor (props) {
super(props);
this.props.setMessage.call(this); // doesn't work, 'this' should refer to Letter but refers to Container
}
render () {
...
}
}
Upvotes: 1
Views: 567
Reputation: 32511
That's because you're using an arrow function.
Arrow functions immediately and permanently bind to the lexical context. Or to put it simply in this case, this
will always be a Container.
To fix this, simply define it as a normal function.
export class Container extends React.Component {
...
setMessage() {
// As Mayank Shukla pointed out, this is how you should change state
this.setState({ message: 'hello' });
}
...
}
In general, setState
is the correct way of updating state. However, if you try to use setState
immediately in the constructor then you will get an error.
So just know that if you're setting that state anywhere but the constructor, setState
is the right way of doing so. In the constructor, you should assign the initial state directly, as you were doing before.
Upvotes: 6
Reputation: 1
Try
export class Container extends React.component {
...
setMessage() {
this.setState({
message: 'hello'
});
}
render () {
return (
<div>
<Letter setMessage={this.setMessage} />
</div>
}
}
export class Letter extends React.component {
constructor (props) {
super(props);
}
setMessage() {
this.props.setMessage();
}
render () {
...
}
}
"this" binds to the immediate scope when used in arrow functions Also, prefer to use this.setState over this.state. = ...
Upvotes: 0