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>
)
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);
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
export default ({changeState, myState, handleClick}) => (
<Navigation>
<h1>Navigation</h1>
<button onClick={() => changeState()}>Navigation</button>
{ myState ?
<div>
<NavigationItem handleClick={handleClick} title={'#Link-1'} />
<NavigationItem handleClick={handleClick} title={'#Link-2'} />
<NavigationItem handleClick={handleClick} title={'#Link-3'} />
</div>
: null
}
</Navigation>
)
You should wrap the JSX into a <div/>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.