0

Created a base React component to inherit from:

import { Component } from 'react';

class BaseComponent extends Component {
    constructor(props) {
        super(props);
    }

    _bindProps(...methods) {
        return methods.map(method => this[method].bind(this))
    }
}

export default BaseComponent;

And my child component:

class SomeChild extends BaseComponent {

    constructor(props) {
        super(props);
    }

    foo() {

    }

    render() {
        const props = this._bindProps('foo');
        <Child {...props} />
    }
}

However, I receive Cannot read property 'bind' of undefined on the line return methods.map(method => this[method].bind(this)). How can I achieve this, ie. passing down methods from a parent component to a child, and when it's called from the child, have it's this value reference the parent component.

benhowdle89
  • 36,900
  • 69
  • 202
  • 331

2 Answers2

0

class SomeChild extends BaseComponent {

    constructor(props) {
        super(props);
    }

    foo = () => {

    }

    render() {
        <Child foo={this.foo} />
    }
}

If your just doing the BaseComponent to bind(this) to methods and using es6 it would be simpler to just use arrow functions for your methods.

J. Mark Stevens
  • 4,911
  • 2
  • 13
  • 18
0

Janaka is right about just using arrow functions, but also you've a problem with your _bindProps implementation. It returns an array of bound functions but you need to return a key/val object of properties. Updating your _bindProps definition to:

_bindProps(obj) {
  Object.keys(obj).forEach(k => obj[k] = obj[k].bind(this));
  return obj;
}

And calling it with an object does the trick:

class BaseComponent extends React.Component {
  constructor(props) {
    super(props);
  }

  _bindProps(obj) {
    Object.keys(obj).forEach(k => obj[k] = obj[k].bind(this));
    return obj;
  }
}

class SomeChild extends BaseComponent {

  constructor(props) {
    super(props);
    this.name = 'Jack'
  }

  foo() {
    return this.name;
  }

  render() {
    const props = this._bindProps({
      foo: this.foo,
    });
    console.log('props', props);
    return <Child {...props} />
  }
}

You could tidy the above up a little but that does now do the right thing and if you call this.props.foo() in the child component you will get Jack returned back.

I'd be interested to know why you're doing this though? This isn't something I've typically had to do at any point.

Jack Franklin
  • 3,765
  • 6
  • 26
  • 34
  • I basically have two different "views" (forget MVC views, I mean literally views) for basically the same component. So I created two child components (for each "view") and then passed down all the callback methods from the 1 parent to the 2 children. The event handlers are added in the children, but they actually call methods in the parent – benhowdle89 Nov 30 '15 at 22:59