Reputation: 179
Lets say that i have this component:
export default class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
test: false
};
}
func1 = () => {
function update() {
this.setState({ test: true }); // not working
}
};
render() {
return <div />;
}
}
As you see i have func1 which is in arrow form,and there is another function update in function update()
form
So how do i call setState from inside function update as seen in example ?
EDIT: the reason why i am trying to do something like this is i am using a game engine inside react component called phaser.So actually if i make update function as an arrow function for some reason phaser cant understand it and throws undefined error.update function is called 60 times in second
export default class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
test: false
};
}
componentDidMount(){
this.func1()
}
func1 = () => {
var game = new Phaser.Game(canvas_width,canvas_height,Phaser.AUTO,'gameDiv',{ preload: preload, create: create, update: update });
function update() {
this.setState({ test: true }); // not working
}
};
render() {
return <div />;
}
}
SECOND EDIT: THANKS GUYS WRITING update = update.bind(this) before var game solved it
Upvotes: 1
Views: 4190
Reputation: 17638
You can use an arrow function again:
class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
test: false
};
}
func1 = () => {
const update = () => {
this.setState({ test: true }) // not working
}
return update;
}
componentDidMount() {
this.func1()();
}
render() {
console.log( this.state);
return (
<div></div>
)
}
}
ReactDOM.render(<Test />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
When you use a regular function you lose the scope of this
. When you use an arrow function you can use it without worrying about this
as you do in your first function. But, instead of an arrow function that would work:
func1 = () => {
const that = this;
return function update() {
that.setState({ test: true }); // not working
}
}
Or even with bind
as @Tholle suggested in his comment:
func1 = () => {
return ( function update() {
this.setState({ test: true }); // not working
}).bind(this);
}
Furthermore, you can define them separately and call the update
function inside the func1.
func1 = () => {
this.update();
};
update() {
this.setState({ test: true }); // not working
}
This works too, because you are auto-binding your func1
function to this
and your update
function is invoked from there, keepin this
scope.
Upvotes: 2
Reputation: 6592
you can pass this
in as an argument, perhaps calling it self
within the function. I.e self.setState
. You could also bind
or call
the function passing the this
as an argument. The important thing is that this
still references the correct React component.
also, I'm a little confused why you're defining a function which returns a function like that. Could you just pass the function in point free form instead and not need to worry about this issue? You still need to bind the function to this
..
export default class Test extends React.Component {
constructor(props) {
super(props);
this.func1 = this.func1.bind(this)
this.state = {
test: false
};
}
func1() {
this.setState({ test: true });
};
render() {
return <div callback={this.func1} />;
}
}
Upvotes: 1