1

I am trying to passed a function from one component(CompB) to another function that is in the another component(CompA) so it will be executed when setState is completed.

However, I ran into Uncaught TypeError: CallBack is not a function error.

The code snippet is following:

var CompA = React.createClass({

  foo: function(form, CallBack){
    var that = this;
    $.ajax({
      url: '/someurl',
      type: 'someAction',
      data: $(form).serialize(),
      success: function(data) {
        that.setState({"id": data.id}, function(){
          CallBack();
        });
      },
      error: function(data) {
        console.log("Error")
      }
    });
  },

  InnerCallBack: function(SuccessCallBack){
    this.foo($("#some_form"), SuccessCallBack); 
  },


  render:function(){
    return(
      <CompB passedCallBack = {this.InnerCallBack} />
      <button onClick={this.submit}>Submit</button>
    )
  }
})

var CompB = React.createClass({
  addWords: function(){
    var bar = this.state.words;

    bar.push({
       "someData": "",
       "words": "dafadf"
    });

    this.setState({
      "words" : bar
    })
  },

  callbackWrapper: function(event) {
    event.preventDefault();
    this.props.passedCallBack(this.addWords());
  },

  render: function(){
    return(
      <button onClick={this.callbackWrapper}>
    )
  }
})

My guess and attempts: 1:The research I have done on SO suggested a binding problem. However, that post was about ES6. my version is ES5,which has the auto-binding as far as i know?

2: Right now I am suspecting it has to do with scoping? I am suspecting this line <CompB passedCallBack = {this.InnerCallBack} /> because no parameter is passed? but I thought in react passing a function as props does not require a parameter?

What I tried to achieve 1: I am trying to find out what caused this error and a way to fix it.

2: Another problem I have with this code snippet is that when the button from CompB is clicked, the onClick function from CompA is fired as well. I understood that it has something to do with DOM's event bubbling and tried to use evemt.preventDefault() to fix it, but it did not fix it.(This can be a seperate SO post,so I am not worrying about it at this point)

ZpfSysn
  • 807
  • 2
  • 12
  • 30
  • Tracing how `foo` is called shows that it is called via `this.props.passedCallBack(this.addWords());`, where the argument passed to `this.props.passedCallBack` (`InnerCallBack`) is supposed to be a callback function. `this.addWords` however **does not a return a function**. It returns `undefined`. If you mean to pass `this.addWords` as callback then don't call it: `this.props.passedCallBack(this.addWords);`. – Felix Kling Dec 20 '17 at 15:37
  • @T.J.Crowder: `React.createClass` automatically calls `.bind(instance)` on all methods. – Felix Kling Dec 20 '17 at 15:38
  • @FelixKling: That's weird, because I tried it before voting to close, and `this` did not have the right value. But I trust you, I must have mis-observed somehow. I've voted to reopen. – T.J. Crowder Dec 20 '17 at 15:38
  • @T.J.Crowder i thought React. createClass calls .bind ? – ZpfSysn Dec 20 '17 at 15:39
  • @T.J.Crowder: `¯\_(ツ)_/¯` If it didn't get the right `this` value then the OP would never get this error since `foo` would never be called. – Felix Kling Dec 20 '17 at 15:39
  • @FelixKling yes, `foo` is called via the `innercallback` function.And yes I meant to pasas `this.addWords` as a callback of `foo`. How should I call it then? And why does this.addWords return `undefined`? – ZpfSysn Dec 20 '17 at 15:42
  • 1
    *"How should I call it then?"* You don't. `this.addWords` is called inside the `foo` via `CallBack()`. You just have to pass the function itself to `passedCallBack`. *"And why does this.addWords return undefined?"* Because any function that doesn't explicitly `return` something returns `undefined`: `function foo() {}; console.log('Return value', foo());`. – Felix Kling Dec 20 '17 at 15:45

1 Answers1

2

Pass a function to another function resulted in “not a function” error

You are not passing a function.

  • foo is called as this.foo($("#some_form"), SuccessCallBack); in InnerCallBack.
  • InnerCallBack is called as this.props.passedCallBack(this.addWords());

I.e. you are calling addWords and pass its return value to passedCallBack. passedCallBack expects to be passed a function, but addWords does not return anything (hence it returns undefined). Therefore SuccessCallBack will be undefined.

If you intend to pass addWords as callback then don't call it:

this.props.passedCallBack(this.addWords);
//                                    ^^ no calling parenthesis here
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143