Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React conditional rendering of multiple child components

I'm trying to render multiple child components depending on state however I'm only able to return one child component (SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag)

Each child component passes the same props, how could this code be kept DRY?

Works

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

Don't

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> ) 
like image 795
silversurfer Avatar asked Aug 31 '17 20:08

silversurfer


People also ask

Can we render two child components in React?

React allows us to render one component inside another component. It means, we can create the parent-child relationship between the 2 or more components.

Can you render multiple components in React?

In Vue and React, we can only render one element. Even if we have multiple elements to render, there can only be a single root element. This means if we want to render two or more elements, we have to wrap them in another element or component.

How many ways you can conditionally render in React?

7 Ways to Implement Conditional Rendering in React Applications | DigitalOcean.


2 Answers

Directly we can't return more than one elements.

Possible Solutions:

1- Either you need to wrap all the elements in a div or any other wrapper element.

2- We can return an array of multiple elements also, So put all the items in an array, and return the array.

Like this:

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

Check this example:

let b = true ? [1,2,3,4]: null;    console.log('b = ', b);

This will throw error:

let b = true? 1 2 3 4: null;    console.log('b = ', b);
like image 144
Mayank Shukla Avatar answered Sep 20 '22 09:09

Mayank Shukla


You can also use <Fragment> from ReactJS: https://reactjs.org/docs/fragments.html

The problem about wrapping all the elements with a <div>, is that you are adding more elements to the DOM, and sometimes it's impossible (for example, when you are rendering a <td> or <tr> inside a <table>. So, here is where <Fragment> comes to help us.

Just wrap all those elements in a <Fragment> and it'll be enough. Meaning:

{ myState &&   <Fragment>     <NavigationItem handleClick={handleClick} title={'#Link-1'} />     <NavigationItem handleClick={handleClick} title={'#Link-2'} />     <NavigationItem handleClick={handleClick} title={'#Link-3'} />   </Fragment> } 

Anyways, this another "Conditional Rendering" approach is better in "code readability" sense: https://medium.com/@BrodaNoel/conditional-rendering-in-react-and-jsx-the-solution-7c80beba1e36

It basically proposes the use of a <Conditional> element, like:

<Conditional if={myState}>   <NavigationItem handleClick={handleClick} title={'#Link-1'} />,   <NavigationItem handleClick={handleClick} title={'#Link-2'} />,   <NavigationItem handleClick={handleClick} title={'#Link-3'} /> </Conditional> 

^ This looks better for my eyes :D

like image 30
Broda Noel Avatar answered Sep 19 '22 09:09

Broda Noel