Meteor/React ES6 class method binder

Just published this!
https://www.npmjs.com/package/meteor-react-prebind

I highly recommend pre-binding your class methods vs binding at the time of props-passing, i.e.:

<div onClick={this.doSomething.bind(this)} />

Though it should be ok in many cases, sometimes it’s bad.

Enjoy, and feel free to contribute improvements/fixes.

4 Likes

This looks nice and espeially the ability to declare non-binds is also helpful.

I’ve also grown fond of the new babel stage-1 function-bind syntax :: which is super helpful and declarative. As soon as you see the :: you know you have bound to the class context

<div onClick={::this.doSomething} />
2 Likes

Though I would point out that using the :: syntax is exactly the same as:

<div onClick={this.doSomething.bind(this)} />

And so you’re not avoiding potential re-renders by using that syntax.

Yes, that’s right, if doSomething is a function passed from a prop, and thanks for pointing that out!

I use this :

BaseComponent

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

        this.bindMethodsToThis();
    }

    getMethodNames() {
        const excludes = [
            'constructor',
            'componentWillMount',
            'render',
            'componentDidMount',
            'componentWillReceiveProps',
            'shouldComponentUpdate',
            'componentWillUpdate',
            'componentDidUpdate',
            'componentWillUnmount',
            'bindMethodsToThis'
        ];
        const props = Object.getOwnPropertyNames(this.constructor.prototype);
        const names = [];
        for (let p of props) {
            const p2 = this[p];
            if (typeof p2 === 'function' && excludes.indexOf(p) === -1) {
                names.push(p);
            }
        }
        return names;
    }

    bindMethodsToThis() {
        const methods = this.getMethodNames();
        
        methods.forEach((item) => {
            this[item] = this[item].bind(this);
        });
    }
}

SomeComponent

export class SomeComponent extends BaseComponent {
    handleClick() {
        alert('automatically bind to this');            
    }

    render() {
        return (
            <div>
                <button onClick={this.handleClick}>Click</button>
            </div>
        );
    }
}

Yep, that’s essentially the same thing! Just make sure it works when your component is wrapped in a higher-order function in dev and production.

1 Like