23

I want to pass a function to a child component but I'm getting this error.

Invalid value for prop passedFunction on <div> tag.

class Parent extends Component {
    passedFunction(){}
    render() {
      <Child passedFunction={this.passedFunction}/>
    }
}

class Child extends Component {
    render() {
        <div onClick={this.props.passedFunction}></div>
    }
}

Basically what I'm trying to do.

var ReactGridLayout = require('react-grid-layout');

var MyFirstGrid = React.createClass({
passedFunction:function(){}
  render: function () {
    return (
      <ReactGridLayout className="layout" cols={12} rowHeight={30} width={1200}>
        <div key="a" data-grid={{x: 0, y: 0, w: 1, h: 2, static: true}}>a</div>
        <div key="b" data-grid={{x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4}}>b</div>
        <div key="c" data-grid={{x: 4, y: 0, w: 1, h: 2}} passedFunction={this.passedFunction}>c</div>
      </ReactGridLayout>
    )
  }
});

It seems it was introduced in React v16. Therefore, what is the correct way to pass a function from parent to child?

CWSites
  • 1,428
  • 1
  • 19
  • 34
Lunny
  • 852
  • 1
  • 10
  • 23
  • Do you have eslint enabled and/or are using proptypes? – bamtheboozle Jan 23 '18 at 17:48
  • Your example should probably work. The error you see is likely because you have `
    ` somewhere.
    – cfraser Jan 23 '18 at 17:48
  • I think I might have found the problem. My child was wrapping another custom component from another library. So I'm assuming you can't pass props to that custom component? – Lunny Jan 23 '18 at 17:50
  • 1
    There's no way we can answer that without knowing the library, the component, and maybe some code. – Kyle Richardson Jan 23 '18 at 17:50
  • I am using react-grid-layout and my child are wrappers for the griditems. – Lunny Jan 23 '18 at 17:55
  • I was able to avoid it by not passing the prop to the gridItem wrapper. But how is it possible to restrict the props being passed? – Lunny Jan 23 '18 at 18:13

4 Answers4

29

Instead of having to bind your function in the constructor of the parent Class, you can use an arrow function to define your method so it is lexically bound using an arrow function

class Child extends Component {
    render() {
        <div onClick={this.props.passedFunction}></div>
    }
}

class Parent extends Component {
    passedFunction = () => {}
    render() {
      <Child passedFunction={this.passedFunction}/>
    }
}

To Account for older version support of Javascript:

class Child extends Component {
    render() {
        <div onClick={this.props.passedFunction}></div>
    }
}

class Parent extends Component {
    constructor() {
        this.passedFunction = this.passedFunction.bind(this)
    }

    passedFunction() {}
    render() {
      <Child passedFunction={this.passedFunction}/>
    }
}
Benjamin Charais
  • 1,248
  • 8
  • 17
  • Hi I tried doing that but webpack gave me an error, is there any plugin I need for it? – Lunny Jan 24 '18 at 15:59
  • This should not require anything extra. The only thing I can think, is that you need to define the child before the parent, which is something I ignored in my original post, and I have now updated it for. – Benjamin Charais Feb 07 '18 at 23:22
  • it is 'passedFunction = () => {}' thats giving me the error, it doesnt seem compatible with my webpack configs – Lunny Feb 12 '18 at 17:38
8

You are missing bind on the Child component.

this.props.passedFunction.bind(this)
Ynahmany
  • 139
  • 5
  • Adding an official documentation on how to pass components to child components: https://reactjs.org/docs/faq-functions.html – supergentle Jan 23 '18 at 17:58
  • It would be good if you could further explain what has to happen here in terms of the correct assignment on the left hand side. – lopezdp Oct 22 '19 at 18:26
4

If you can bind this function like this it will works

class Parent extends Component {
   passedFunction = () => {};
   render() {
       <Child passedFunction={this.passedFunction} />;
   }
}

class Child extends Component {
   render() {
       <div onClick={this.props.passedFunction} />;
   }
}
Rajesh Bhartia
  • 690
  • 4
  • 10
0

I found out what was wrong. It was because of react-grid-layout. I have to pass the rest of the properties to child.

class Child extends Component {
    render() {
        var { passedFunction, ...otherProps } = this.props;
        return (
            <div onClick={passedFunction} {...otherProps}></div>
        );           
    }
}
Lunny
  • 852
  • 1
  • 10
  • 23