【问题标题】:Comparing two components - is Component X an instance of Component A比较两个组件 - 组件 X 是组件 A 的实例吗
【发布时间】:2015-01-07 16:57:49
【问题描述】:

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

但是,使用属性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);

【问题讨论】:

  • 你想知道组件在什么意义上是相等的?相等是否意味着它们呈现相同的输出?
  • 不,它们可能(并且现在)完全不同。我需要知道它们是否是同一个 React.createClass() 的实例。

标签: javascript reactjs


【解决方案1】:

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

确实,在 React 0.12 中 child.type === Foo.type 是唯一有效的比较。
这与 React 0.12 正在处理 deprecating wrapper functions 有关。

当 0.13 出来时,child.type 本身将是 Foo

吹毛求疵:不要使用this.props.children.mapthis won't work when there is less than two children
请改用React.Children.map

【讨论】:

  • 感谢您的启发!这解释了为什么child.type 似乎是一个函数。至于吹毛求疵,你是完全正确的,确实应该使用 React.Children.map!
  • 虽然不是专门针对这个问题的例子,但如果你创建 ES6 类而不是使用 React.createClass,你可以使用实例:child.type.prototype instanceof Foo——我在my own similar question 中发现了这一点
【解决方案2】:

您正在制作的那种 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>;
    }
});

【讨论】:

  • 大多数时候这是真的。比较合法的情况很少见。例如,如果您的组件还导出子组件并希望对特定类型应用特殊处理,例如&lt;Menu&gt;&lt;Menu.Item&gt;some&lt;/Menu.Item&gt;&lt;Menu.Separator /&gt;&lt;/Menu&gt;.
  • 在这种情况下,您为什么需要知道哪个是哪个? Menu.Item 将呈现一个菜单项,而 Menu.Separator 将呈现一个分隔符。 Menu 只会渲染它的东西,并且(有条件地)包含 this.props.children。
  • 我有一个用例,我想将每个传递的children 包装在div 中,分隔符除外。虽然你是对的,但有了Menu.Item,我真的不需要这张支票——我懒得包装每件物品。
  • 丹描述的案例确实和我的很相似。在我的例子中,它是一个带有各种子组件(输入、选择等)的表单组件。出于表单验证的目的,所有孩子在被渲染之前都会获得额外的道具,但我遇到了一种输入类型需要额外道具的地方。
  • 补充:我不想为所有子组件添加额外的道具,只是为了能够过滤它们。我认为必须有一种更抽象的方式!
猜你喜欢
  • 2011-10-04
  • 1970-01-01
  • 2020-11-16
  • 2016-02-25
  • 1970-01-01
  • 2010-12-25
  • 1970-01-01
  • 2016-06-15
  • 1970-01-01
相关资源
最近更新 更多