问题 比较两个组件 - 组件X是组件A的实例


我有一个通用组件,它映射其子组件以仅过滤特定类型的子组件,如下所示。

但是,使用该属性 type 只是一个猜测,我无法找到它记录。不仅如此,记录它表明它是一个功能 - 无法执行。最重要的是,使用Browserify时需要解决几个问题。

另一种选择是读取child.prototype.displayName。但这也错了。

问:基本上,我正在寻找一种比较两个ReactJS组件是否相等的可靠方法。

(更新:毕竟不是那么糟糕)

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);

5655
2018-01-07 16:57


起源

在什么意义上你想知道组件是否相等?是否意味着它们会产生相同的输出? - Brett DeWoody
不,他们可能(并且是)完全不同。我需要知道它们是否是同一个React.createClass()的实例。 - David
有关: bountysource.com/issues/... - David


答案:


我认为你的例子是正确的。

的确,在React 0.12中 child.type === Foo.type 是唯一有效的比较。
这与React 0.12正在进行中有关 弃用包装函数

当0.13出局时, child.type 本身就是 Foo

Nitpick:不要使用 this.props.children.map当少于两个孩子时,这将不起作用
使用 React.Children.map 代替。


14
2018-01-08 01:00



谢谢你的光线!这解释了原因 child.type 似乎是一种功能。至于挑剔,你是完全正确的,事实上应该使用React.Children.map! - David
虽然没有特别关注此问题示例,但如果您创建ES6类而不是使用React.createClass,则可以使用以下实例: child.type.prototype instanceof Foo  - 我发现了 我自己的类似问题 - mjohnsonengr


你正在做的那种api是脆弱和混乱的。您不应将元素视为数据。如果需要过滤,请将数据传递给组件。

<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>;
    }
});

2
2018-01-08 12:36



大部分时间都是如此。在比较合法的情况下,极少数情况下。例如,如果您的组件也导出子组件并希望对特定类型应用特殊处理,例如 <Menu><Menu.Item>some</Menu.Item><Menu.Separator /></Menu>。 - Dan Abramov
为什么你需要知道在这种情况下哪个是哪个? Menu.Item将呈现一个菜单项,Menu.Separator将呈现一个分隔符。菜单只会渲染它的东西,并且(有条件地)包含this.props.children。 - FakeRainBrigand
我有一个用例,我想把每个传递包裹起来 children 在一个 div,除了分隔符。虽然你是对的,但是 Menu.Item 我真的不需要这个检查 - 我太懒了包装每个项目。 - Dan Abramov
Dan描述的案例确实与我的非常相似。在我的例子中,它是一个包含各种子组件的表单组件(输入,选择等)。为了表单验证的目的,所有的孩子在渲染之前都会获得额外的道具,但我遇到了一个输入类型需要额外道具的点。 - David
添加:我不想为所有子组件添加额外的道具只是为了能够过滤它们。我想必须有一个更抽象的方式! - David