Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing two components - is Component X an instance of Component A

I have a generic component which maps its child components to filter only children of a certain type, as found below.

However, using the property type was a mere guess, and I can't find it documented. Not only that, logging it shows it being a function - which can't be executed. On top of that there's a couple issues that need to be worked around when using Browserify.

Another option would be to read child.prototype.displayName. But that too feels wrong.

Question: Basically, I'm looking for a solid way of comparing whether two ReactJS components are equal.

EXAMPLE

(Updated: not that bad after all)

var Foo = React.createClass({
    render: function() {
        return <div>Foo</div>;
    }
});

var Bar = React.createClass({
    render: function() {
        return <div>Bar</div>;
    }
});

var Main = React.createClass({
    render: function() {
        var filteredChildren = [];

        filteredChildren = React.Children.map(function(child) {
            if (child.type === Foo.type) {
                return child;
            }
        });

        return (
            <div>
                {filteredChildren}
            </div>
        );
    }
});

React.render(<Main><Foo /><Bar /></Main>, document.body);
like image 952
David Avatar asked Jan 07 '15 16:01

David


2 Answers

I think your example is correct.

Indeed, in React 0.12 child.type === Foo.type is the only comparison that works.
This is related to React 0.12 being in process of deprecating wrapper functions.

When 0.13 is out, child.type itself will be Foo.

Nitpick: don't use this.props.children.map, this won't work when there is less than two children.
Use React.Children.map instead.

like image 196
Dan Abramov Avatar answered Oct 16 '22 22:10

Dan Abramov


The kind of api you're making is frail and confusing. You shouldn't treat elements as data. If you need to filter, pass data to the component.

<Main things={[
  {type: 'Foo', element: <Foo />},
  {type: 'Bar', element: <Bar />},
  {type: 'Bar', element: <div>I'm lying but it doesn't matter</div>},
]} />
var Main = React.createClass({
    render: function(){
        var filteredChildren = this.props.things.map(function(thing){
            return thing.type === 'Foo' ? thing.element : false;
        });

        return <div>{filteredChildren}</div>;
    }
});
like image 3
Brigand Avatar answered Oct 16 '22 23:10

Brigand