为什么组件在 ReactJS 中只能返回一个节点?(有根本原因吗?)

IT技术 twitter-bootstrap reactjs
2021-05-16 22:20:18

从文档:

JSX 根节点的最大数量

目前,在一个组件的渲染中,你只能返回一个节点;例如,如果您有一个要返回的 div 列表,则必须将组件包装在 div、span 或任何其他组件中。

别忘了 JSX 会编译成普通的 js;返回两个函数并没有真正的语法意义。同样,不要将一个以上的孩子放在三元组中。

上面的解释说“当前”,这表明一个组件可能会返回一个导致两个节点而不是一个节点的函数。这只是技术限制,还是融入了哲学?

我是如何想到这个问题的:我在尝试使用 React 渲染 Bootstrap 菜单的情况下,Bootstrap 使用子选择器,而不是后代选择器,这很有意义。


旁白:我如何解决我的特定问题:

我最感兴趣的是 React 的架构,但如果你好奇这就是我的情况。

目前在 Bootstrap 中,您可以创建一个下拉菜单:

<li role="presentation" class="dropdown pull-right">
    <a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="true"> Menu <span class="caret"></span> </a>
    <div id="macroMenu" class="react-component">
        <ul class="macroInsertion dropdown-menu" role="menu">
            <li>
                <form class="navbar-form navbar-left" role="search">
                    <div class="form-group">
                        <input type="text" class="form-control search-filter" placeholder="Search" />
                    </div>
                </form>
            </li>
            <li>
                <a href="#">Menu 1</a>
            </li>
            <li>
                <a href="#">Menu 2</a>
            </li>
            <li class="divider"></li>
            <li>
                <a href="#">Menu 3</a>
            </li>
        </ul>
    </div>
</li>

默认的 Bootstrap 样式表有像 .pull-right > .dropdown-menu 和 .open > .dropdown-menu 这样的选择器,如果你在容器和包含之间插入单个元素,它们就不起作用。这是有道理的,因为它可能更快,并且 Bootstrap 有时可能会处理双嵌套选择器,但它破坏了我们的系统,因为它在中间有 .react-component。

就我而言,我手动找出了 .react-component 破坏了什么,并创建了新样式来解决缺失的行为。

1个回答

这是目前的技术限制。然而,有一些(随意的)谈论允许这样做:

var Foo = React.createClass({
  render(){
    return [<Bar />, <Baz />];
  }
});

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

<Quux />会导致这种结构:

<div>
    <span />
    <Bar />
    <Baz />
</div>

这对于处理 HTML 中的一些僵化(表格、列表、标题)很有用,也适用于在兄弟姐妹很重要的情况下(例如display: inline-block)或您无法控制样式和直接子级 ( >) 或兄弟级选择器 ( ~or +)的样式.

如果您确实遇到了这些情况之一,您很可能只是在实现渲染,因此使用实用程序函数而不是组件将是一个很好的解决方法。

var Foo = function(props){
    return [<Bar />, <Baz />];
}

var Quux = React.createClass({
  render(){
    return <div>{flatten( <span />, Foo({}) )}</div>;
  }
});


// usually you get this from underscore or similar
var flatten = function(){ return Array.prototype.reduce.call(arguments, function(acc, x){ return acc.concat(x) }, []) };