为什么组件在 ReactJS 中只能返回一个节点?(有根本原因吗?) [英] Why can components only return one node in ReactJS? (Is there a fundamental reason?)

查看:24
本文介绍了为什么组件在 ReactJS 中只能返回一个节点?(有根本原因吗?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自文档:

<块引用>

最大 JSX 根节点数

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

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

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

我是如何想到这个问题的:我正试图使用​​ React 呈现 Bootstrap 菜单,而 Bootstrap 使用子选择器,而不是后代选择器,这很有意义.

<小时>

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

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

目前在 Bootstrap 中,您可以制作下拉菜单:

</表单><li><a href="#">菜单 1</a><li><a href="#">菜单 2</a><li class="divider"></li><li><a href="#">菜单 3</a>

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

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

解决方案

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

var Foo = React.createClass({使成为(){return [<Bar/>, <Baz/>];}});var Quux = React.createClass({使成为(){返回<div><span/><Foo/></div>;}});

并且 将导致这种结构:

<跨度/><酒吧/><巴兹/>

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

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

var Foo = function(props){return [<Bar/>, <Baz/>];}var Quux = React.createClass({使成为(){return <div>{flatten( <span/>, Foo({}) )}</div>;}});//通常你从下划线或类似的地方得到这个var flatten = function(){ return Array.prototype.reduce.call(arguments, function(acc, x){ return acc.concat(x) }, []) };

From the docs:

Maximum Number of JSX Root Nodes

Currently, in a component's render, you can only return one node; if you have, say, a list of divs to return, you must wrap your components within a div, span or any other component.

Don't forget that JSX compiles into regular js; returning two functions doesn't really make syntactic sense. Likewise, don't put more than one child in a ternary.

The explanation above says "currently," which suggests that a component that could potentially return a function that results in two nodes instead of one. Is this just a technical limitation, or is this baked into the philosophy?

How I thought of this question: I'm in a situation where I'm trying to render a Bootstrap menu using React, and Bootstrap uses child selectors, instead of descendent selectors, which makes perfect sense.


Aside: How I solved my particular problem:

I'm mostly interested in the architecture of React, but in case you're curious this was my situation.

Currently in Bootstrap you can make a dropdown menu:

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

The default Bootstrap stylesheet has selectors like .pull-right > .dropdown-menu and .open > .dropdown-menu though, which don't work if you insert a single element in between container and contained. This makes sense because it's presumably faster and Bootstrap may sometimes deal with double-nested selectors, but it broke our system to have .react-component in the middle.

In my case, I manually figured out what .react-component was breaking and made new styles to account for the missing behavior.

解决方案

It's a technical limitation currently. However there has been some (casual) talk about allowing this:

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

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

And <Quux /> would result in this structure:

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

This is useful to deal with some rigidity in HTML (tables, lists, head), and also for styling where siblings matter (e.g. display: inline-block) or where you have no control over the styling and direct child (>) or sibling selectors (~ or +) are used.

If you do run into one of these cases, you're most likely just implementing render, so using a utility function instead of a component would be a good workaround.

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) }, []) };

这篇关于为什么组件在 ReactJS 中只能返回一个节点?(有根本原因吗?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆