React多个子组件的条件渲染

27

我试图根据状态呈现多个子组件,但是我只能返回一个子组件(SyntaxError:相邻的JSX元素必须包装在封闭标记中)

每个子组件传递相同的props,如何保持DRY?

正常工作

export default ({changeState, myState, handleClick}) => (
    <Navigation>
            <span>Navigation</span>
            <button onClick={() => changeState()}>Navigation</button>
            { myState ?
                <NavigationItem handleClick={handleClick} title={'#Link-1'} />
              : null
            }
    </Navigation>
)

不要

export default ({changeState, myState, handleClick}) => (
    <Navigation>
            <h1>Navigation</h1>
            <button onClick={() => changeState()}>Navigation</button>
            { myState ?
                <NavigationItem handleClick={handleClick} title={'#Link-1'} />
                <NavigationItem handleClick={handleClick} title={'#Link-2'} />
                <NavigationItem handleClick={handleClick} title={'#Link-3'} />
              : null
            }
    </Navigation>
)
2个回答

51

直接返回多个元素是不可能的。

可能的解决方案:

1- 要么将所有元素包装在 div 或其他包装元素中。

2- 我们也可以返回多个元素的数组,因此将所有项放入数组中并返回该数组。

像这样:

{myState ?
    [
        <NavigationItem handleClick={handleClick} title={'#Link-1'} />,
        <NavigationItem handleClick={handleClick} title={'#Link-2'} />,
        <NavigationItem handleClick={handleClick} title={'#Link-3'} />
    ]
  : null
}

请看这个例子:

let b = true ? [1,2,3,4]: null;

console.log('b = ', b);

这会抛出错误:

let b = true? 1 2 3 4: null;

console.log('b = ', b);


谢谢,{myState && ...} 语法非常方便。 - Ben Kane

20

您也可以使用来自ReactJS的<Fragment>https://reactjs.org/docs/fragments.html

将所有元素用<div>包装起来的问题在于,您正在向DOM添加更多元素,有时这是不可能的(例如,在<table>中呈现<td><tr>时)。因此,这就是<Fragment>帮助我们的地方。

只需将所有元素包装在<Fragment>中即可。

{ myState &&
  <Fragment>
    <NavigationItem handleClick={handleClick} title={'#Link-1'} />
    <NavigationItem handleClick={handleClick} title={'#Link-2'} />
    <NavigationItem handleClick={handleClick} title={'#Link-3'} />
  </Fragment>
}
无论如何,这种“条件渲染”的方法在“代码可读性”方面更好: https://medium.com/@BrodaNoel/conditional-rendering-in-react-and-jsx-the-solution-7c80beba1e36 基本上,它提出使用一个<Conditional>元素,例如:
<Conditional if={myState}>
  <NavigationItem handleClick={handleClick} title={'#Link-1'} />,
  <NavigationItem handleClick={handleClick} title={'#Link-2'} />,
  <NavigationItem handleClick={handleClick} title={'#Link-3'} />
</Conditional>

^ 这看起来更舒服,哈哈 :D


那个“Conditional”组件似乎是一个不必要的抽象,增加了更多样板代码:(我觉得人们在尝试使用他们的“智能抽象”时过于努力。事实上,人们并不知道你的抽象做了什么,但大多数程序员都知道基本的JS语法...当你将那些代码移动到一个单独的项目中时,情况会变得更糟,现在人们必须进入那个项目才能看到为什么它不起作用。 - Doug
@Doug 是的,我同意。我总是只使用 {!!var && <div />}。但有时候(一些团队)要求所有东西都必须是声明式的,因此他们使用这种行为。 有时候他们不得不这样做是因为有一些动态代码生成和其他魔法/草药。 - Broda Noel
Fragment的短语法使代码更易读。然而,并非所有工具都支持它。 - Sourabh
@Sourabh 是的。即使在 Fragment 的短语法中,Github 也会打乱所有颜色。 - Broda Noel
1
我认为<Conditional>组件的概念是很好的。React应该像Vue.js一样,开箱即用地提供类似的功能。 - d512

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接