1

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

1
  • I can't understand how you use update function here? You are not invoking it also not returning from funct1. Commented Aug 11, 2018 at 21:58

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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} />;
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.