【问题标题】:React conditional rendering bug even with single parent and child list [duplicate]即使使用单个父子列表也能反应条件渲染错误[重复]
【发布时间】:2018-09-09 07:47:06
【问题描述】:

学习了一点 React,但在我看来,React 本身存在条件渲染错误。

假设我有一个像这样的Foo 组件:

foo.js

import React, { Component } from 'react';

class Foo extends Component {
  render() {
    const isLoggedIn = this.props.isLoggedIn;

    return(
      <div>
        { isLoggedIn ? (
          <div>one</div><div>two</div>
        ) : (
          <div>one</div><div>two</div><div>three</div>
        )}
      </div>
    );
  }
}

export default Foo;

我是这样使用它的:

app.js

import React, { Component } from 'react';
import Foo from './components/foo';

class App extends Component {
  render() {
    return (
      <div>
          <Foo isLoggedIn={false} />
      </div>
    );
  }
}

export default App;

这会产生错误:

Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag

请注意上面的 Foo 组件,只返回一个父 div 而不是数组。如果它是一个数组,那么是的,我同意这个错误。

React 文档示例中给出的官方示例是这样的:

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      {isLoggedIn ? (
        <LogoutButton onClick={this.handleLogoutClick} />
      ) : (
        <LoginButton onClick={this.handleLoginClick} />
      )}
    </div>
  );
}

https://reactjs.org/docs/conditional-rendering.html

这对任何人来说都像是 React 中的错误吗?

更新

根据这里给出的答案和 cmets,React 的隐含行为是 render() 函数内部的三元运算符,在幕后带有它自己的 render 调用,就像一个虚拟组件,这意味着一个额外的层的&lt;div&gt; 需要包裹在我的子元素列表中。

Emberjs Foo 组件

我的困惑源于我过去做过一些 Emberjs 开发,并且像这样的组件按预期工作:

<h3>Foo component</h3>

{{#if isLoggedIn}}
  <div>one</div><div>two</div>
{{else}}
  <div>one</div><div>two</div><div>three</div>
{{/if}}

还是感谢大家的解释。

【问题讨论】:

  • 我没有返回一个元素 Shubham 的列表,我返回的是一个包含子元素的单个父 div 节点,根据 React 的文档,这非常好。
  • 我猜你正在返回多个元素,可能不是来自渲染,而是在这里的条件渲染&lt;div&gt;one&lt;/div&gt;&lt;div&gt;two&lt;/div&gt;
  • 我来自不同的背景,但我不知道 React 中的三元运算符被视为另一个“虚拟组件”,在后台有自己的渲染调用。
  • 是的,它们被视为单独的 JSX 元素块。考虑到其他问题解决了您的问题,我将其标记为重复

标签: reactjs


【解决方案1】:

你有一个语法错误

          <div>one</div><div>two</div><div>three</div

应该是

          <div>one</div><div>two</div><div>three</div>

【讨论】:

  • 抱歉错字了,但是改错后还是会出现这个错误。
【解决方案2】:

您是否尝试添加?

return(
      <div>
        { isLoggedIn ? (
          <Fragment><div>one</div><div>two</div><Fragment>
        ) : (
          <Fragment><div>one</div><div>two</div><div>three</div><Fragment>
        )}
      </div>
    );

【讨论】:

  • Fragment 也可以像 ivp 的回答一样在元素列表周围额外包裹 &lt;div&gt;,但真正的问题是为什么这是必要的?
  • 请注意:片段也是正确答案。但是,片段的概念在早期版本中不存在。因此不适用于使用较旧反应版本的代码。
【解决方案3】:

您正在返回条件中的 2 或 3 个 div。相反,您应该将它们包装到 div 中并返回。

注意下面的 wrapper div。

{ isLoggedIn ? (
      <div className='wrapper'><div>one</div><div>two</div><div>
    ) : (
      </div className='wrapper'><div>one</div><div>two</div><div>three</div></div>
    )}

还要注意下面有小错字

<div>one</div><div>two</div><div>three</div

【讨论】:

  • 如果我将另一层 div 包裹在多个元素中,这似乎可以解决问题,但我想知道为什么它是必要的?
  • React 中的一个简单规则。无论你在哪里返回,总是返回元素,而不是多个元素。在您的示例中,您在真实条件下返回 2 个 div,在错误条件下返回 3 个 div。
  • @Zhang,我希望这个解释有帮助。 :)
  • 那么只是 React 的其中一个细节,没有记录在某处,而是从艰难的过程中学到的?
  • 我无法对完整的反应文档发表评论,因为我还没有阅读它的每一行:)。但无论我读过什么,质量都非常好,我很确定文档中的某处提到了这一点(可能是间接的)。
【解决方案4】:

你需要包装条件中渲染的元素

return(
  <div>
    { isLoggedIn ? (
      <div><div>one</div><div>two</div></div>
    ) : (
      <div><div>one</div><div>two</div><div>three</div></div>
    )}
  </div>
);

注意嵌套条件元素周围的额外div

【讨论】:

    【解决方案5】:

    语法错误:相邻的 JSX 元素必须包含在封闭标记中?

    您以不正确的方式返回多个同级 JSX 元素。

    在 Foo:

    return(
          <div>
            { isLoggedIn ? (
              <div>one</div> //are siblings without 
              <div>two</div> //wrapping in container element.
            ) : (
              <div>one</div> //are siblings without 
              <div>two</div> //wrapping in 
              <div>three</div>//container element.
            )}
          </div>
        );
    

    正确的做法:

    return (
                <div>
                    {isLoggedIn
                        ? (
                            <div> //add wrapper
                                 /...
                            </div>
                        )
                        : (
                            <div> //add wrapper
                                //...
                            </div>
                        )}
                </div>
            );
    

    或者

    如果您使用的是 React16,那么您也可以使用 React.Fragement

    例如

    <React.Fragment>
      <div>one</div>
      <div>two</div>
    </React.Fragment>
    

    【讨论】:

      猜你喜欢
      • 2019-11-24
      • 2020-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-16
      • 1970-01-01
      • 2017-08-28
      • 2021-10-27
      相关资源
      最近更新 更多