Reputation: 7543
I'm relatively new to React and I'm wondering what's the standard here.
Imagine I have a react-router like this one:
<Router history={history}>
<Route path="/" component={App}>
<Route path="home component={Home} />
<Route path="about" component={About} />
<Route path="inbox" component={Inbox} />
<Route path="contacts" component={Contacts} />
</Route>
</Router>
And now I want to remove two routes if prop.mail
is set to false
, so a sane way of doing that would look like this:
<Router history={history}>
<Route path="/" component={App}>
<Route path="home component={Home} />
<Route path="about" component={About} />
{ if.this.props.mail ?
<Route path="inbox" component={Inbox} />
<Route path="contacts" component={Contacts} />
: null }
</Route>
</Router>
But there are 2 routes and React returns error:
expressions must have one parent element.
I don't want to use multiple ifs here. What's the preferred React way of handling this?
Upvotes: 92
Views: 210385
Reputation: 599
You can leverage short hand fragments to return a list of children along with Logical '&&' Operator for conditional rendering. Nice and clean! š
{this.props.mail &&
<>
<Route path="inbox" component={Inbox} />
<Route path="contacts" component={Contacts} />
</>
}
Upvotes: 49
Reputation: 10695
If you're using <Switch>
, then using <div>
and <React.Fragment>
to wrap your routes will break it.
I like the idea of a <ProtectedRoute>
component:
import { Component } from 'react';
import { Redirect, Route } from 'react-router-dom';
class ProtectedRoute extends Component<any> {
render() {
const { component: Component, allow, ...props } = this.props;
if (!allow) {
return <Redirect to={{ pathname: '/signin' }} />;
}
return <Route {...props} render={(props) => <Component {...props} />} />;
}
}
export default ProtectedRoute;
Then use it like below:
<Router history={history}>
<Route path="/" component={App}>
<Route path="home" component={Home} />
<Route path="about" component={About} />
<ProtectedRoute path="inbox" component={Inbox} allow={this.props.mail} />
<ProtectedRoute path="contacts" component={Contacts} allow={this.props.mail} />
</Route>
</Router>
Upvotes: 0
Reputation: 26089
2020 update
I have checked out every solution from answers. Here is the breakdown for regular React:
1. React Fragment
When i wanted to use it once, without adding additional DOM node - it worked. When i tried to use second React.Fragment got really bad errors. Wasn't able to fix it.
2. View
I was unable to import View properly. I don't know if this is only for Reactjs, or Native, but this does not work
3. Div
What actually worked was to put HTML into Div
Upvotes: 4
Reputation: 71
just try enclosing the code after the return statement in an element like <div>....code </div>
,etc.
eg:-
const Div =()=>{
return
<div>
<Button name="Save" ></Button>
<Button name="Edit"></Button>
<Button name="Cancel"></Button>
</div>}
Upvotes: 6
Reputation: 301
You must been use a fragment tag e.g(div, <>,...).
Check this short solution:
{ if.this.props.mail ?
<>
<Route path="inbox" component={Inbox} />
<Route path="contacts" component={Contacts} />
</>
: null }
Upvotes: 16
Reputation: 29
Faced the same error in a similar situation (React Native).
export default class App extends React.Component {
render() {
return (
<StatusBar barStyle="default" />
<AppContainer />
);
}
}
As indicated in the error prompt the JSX expression requires to have one parent element, hence wrap the elements in the return expression with a parent element. The flex: 1
style was added to allow the <View>
element assume the height of the entire screen.
export default class App extends React.Component {
render() {
return (
<View style={{flex: 1}}>
<StatusBar barStyle="default" />
<AppContainer />
</View>
);
}
}
Upvotes: 2
Reputation: 104369
Put them in an array (assign the keys also):
{ if.this.props.mail ?
[
<Route key={0} path="inbox" component={Inbox} />,
<Route key={1} path="contacts" component={Contacts} />
]
: null }
With latest React version, you can try React.Fragment
also, like this:
{ if.this.props.mail ?
<React.Fragment>
<Route path="inbox" component={Inbox} />,
<Route path="contacts" component={Contacts} />
</React.Fragment>
: null }
Upvotes: 131