1

I have referred to couple of similar questions, but I have a situation little different.

Call a React Function from inside Render

How to Call a Function inside a Render in React/Jsx

React: Cant call a function inside child component

export default class CodeEditor extends React.Component {

  appendAssets(asset) {
    console.log(asset)
    this.refs.editor.editor.insert(`player.asset('${asset}')`)
    this.refs.editor.editor.focus()
  }


  render() {
    function sequenceHierarchy (data, outputArray) {
      level++
      data.forEach(function (asset){
        outputArray.push(<li className={`level_${level}`}><button onClick={_ => this.appendAssets(asset.name)}>{asset.name}</button></li>)
        if(asset.children.length) {
          sequenceHierarchy(asset.children, outputArray)
        }
      })
      level--
    }
  }

}

So the onClick of button inside sequenceHierarchy function has to call appendAssets. Of course since this wouldn't be able to call it as it is not the part of this component, I also tried with just appendAssets(asset.name), still it gives a error of Uncaught ReferenceError: appendAssets is not defined

Community
  • 1
  • 1
Deepak Bandi
  • 1,854
  • 4
  • 21
  • 37

1 Answers1

2

I strongly advise you to read this answer for understanding this keyword and its behaviors inside function.

Quoting from the linked answer:

this (aka "the context") is a special keyword inside each function and its value only depends on how the function was called, not how/when/where it was defined. It is not affected by lexical scope, like other variables.

(Please read whole linked answer before proceeding further)

You can either set a reference to the variable which refers to correct this. See this JSFiddle

let that = this; // assign this reference to variable that.
function sequenceHierarchy (data, outputArray) {
   data.forEach((item) => {
        outputArray.push(
          <li>
            <button onClick={that.appendAssets.bind(this, item)}>
               Append {item}
             </button>
          </li>
      );            
   })
}

or

You can use bind method to set correct this, while invoking sequenceHierarchy function as follows. See this JSFiddle

{sequenceHierarchy.bind(this, (['1', '2', '3'], []))} 

or

You can use ES6 arrow function to invoke sequenceHierarchy function like this.

{() => {sequenceHierarchy(['1', '2', '3'], [])}} 

All above methods will work fine.

Hope this helps :)

timbo
  • 13,244
  • 8
  • 51
  • 71
Hardik Modha
  • 12,098
  • 3
  • 36
  • 40