Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a function with parameters through props on reactjs

I have a function that comes from a parent all the way down to a the child of a child in a component hierarchy. Normally this wouldn't be too much of a problem, but I need to receive a parameter from the child. I am currently getting this error message:

Uncaught (in promise) TypeError: this.props.myFunction is not a function. 

Here is an example code to what I a doing:

class SomeComponent extends Component{      constructor(props){         super(props);         //does whatever stuff                 this.myFunction = this.myFunction.bind(this);      }      //(only applicable to raw and normal forms)     myFunction(param){         console.log('do something: ', param);     }      render(){      return (<div><ChildComponent1 myFunction={()=>this.myFunction()}/></div>)     } }  class ChildComponent1{       render(){   return (<div><ChildComponent2 myFunction={()=>this.props.myFunction()}/></div>)     } }  class ChildComponent2{       render(){   return (<Button onClick={()=>this.props.myFunction(param)}>SomeButton</Button>)     } } 

So just to sum it up: I am passing myFunction as a prop from SomeComponent all the way down to ChildComponent2, in which I want it called whenever a button is clicked and to pass a parameters from ChildComponent2.

Thanks!

like image 530
theJuls Avatar asked Dec 28 '16 20:12

theJuls


People also ask

Can you pass state through props React?

Passing state as props from parent to child components is a core concept of React. By keeping state in only a few components and passing it to as many children as needed in the form of props, you will be able to write code that is easier to maintain, and you will thank yourself down the road.


Video Answer


2 Answers

I don't see why you would get that error, but you should be doing myFunction={this.myFunction} and myFunction={this.props.myFunction}:

class SomeComponent extends Component{      constructor(props){         super(props);         //does whatever stuff                 this.myFunction = this.myFunction.bind(this);      }      //(only applicable to raw and normal forms)     myFunction(param){         console.log('do something: ', param);     }      render(){      return (<div><ChildComponent1 myFunction={this.myFunction}/></div>)     } }  class ChildComponent1{       render(){   return (<div><ChildComponent2 myFunction={this.props.myFunction}/></div>)     } }  class ChildComponent2{       render(){   return (<Button onClick={()=>this.props.myFunction(param)}>SomeButton</Button>)     } } 

Wrapping the function call inside another (arrow) function is just unnecessary and won't forward the parameter properly (since all your intermediate arrow functions do not accept a parameter).

like image 177
Felix Kling Avatar answered Sep 17 '22 01:09

Felix Kling


An alternative and IMO more clean way to do it would be like this:

class SomeComponent extends Component{     myFunction = param => {         console.log('do something: ', param);     }      render(){      return (        <div>          <ChildComponent1 onClick={this.myFunction}/>        </div>)     } }  class ChildComponent1{       render(){         return (<div><ChildComponent2 onClick={this.props.onClick}/></div>)       } }  class ChildComponent2{       render(){         const { onClick } = this.props // destructure         return (<Button onClick={()=>onClick(param)}>SomeButton</Button>)       } } 
like image 42
Norfeldt Avatar answered Sep 21 '22 01:09

Norfeldt