Reputation: 111080
With React-Router-4 how can I programmatically set the index route /
For example, if the user is not authenticated, this should trigger:
<Route path="/" component={LandingPage}>
If the user is authenticated:
<PrivateRoute path="/dashboard" component={Dashboard} />
For your information on PrivateRoute
const WithMainLayout = ({component: Component, ...more}) => {
return <Route {...more} render={props => {
return (
<MainLayout {...props}>
<Component {...props} />
</MainLayout>
);
}}/>;
};
const isLoggedIn = () => {
console.log('do it')
return true;
};
....
<WithMainLayout exact path="/" component={Home} render={() => (
isLoggedIn() ? (
<Redirect to="/dashboard" />
) : (
<Home />
)
)}/>
See above attempt, for some reason, the console.log
is not outputting anything in the isLoggedIn func.
Upvotes: 1
Views: 934
Reputation: 282040
So in your Updated Code the problem is that you return
<Route {...more} render={props => {
so what essentially happens is that the render
prop passed on to the WithMainLayout
component which is available with {...more}
is overwritten by you custom prop and hence isLoggedIn
is never called.
The solution is simple, you can just interchange the {...more}
and render={props => {}}
and also wrap your Home component with WithMainLayout
so that it doesn't miss the Layout
You code will look like
const WithMainLayout = ({component: Component, ...more}) => {
return <Route render={props => {
return (
<MainLayout {...props}>
<Component {...props} />
</MainLayout>
);
}} {...more} />;
};
const isLoggedIn = () => {
console.log('do it')
return true;
};
....
<WithMainLayout exact path="/" component={Home} render={() => (
isLoggedIn() ? (
<Redirect to="/dashboard" />
) : (
<WithMainLayout component={Home} />
)
)}/>
Upvotes: 2
Reputation: 6592
You use the history
prop. You can read about it here: https://reacttraining.com/react-router/web/api/history
Essentially you wrap your component in the withRouter
HOC, and it will pass the history
prop to your component which you'll see here: https://reacttraining.com/react-router/web/api/withRouter. It blends very well with React Recompose. I modified the "basic example" of the react router docs as an example here of using withRouter with the history
prop
// create-react-app test && cd test && npm i && npm install react-router-dom
// replace contents of App.js then `npm run start`
import React, { Component } from 'react';
import { withRouter } from 'react-router'
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom'
class BasicExample extends Component {
render() {
return(
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
</ul>
<hr/>
<Route exact path="/" component={withRouter(Home)}/>
<Route path="/about" component={About}/>
</div>
</Router>
)
}
}
class Home extends Component {
render() {
const {history} = this.props;
const handleClick = (e) => {
history.push("/about")
}
console.log(history)
return (
<div>
<h2>Home</h2>
<button onClick={handleClick}>To about</button>
</div>
)
}
}
const About = () => (
<div>
<h2>About</h2>
</div>
)
export default BasicExample;
If you're creating the link in your JSX, use the Link
component, which looks like this
<Link to="/">...</Link>
If you're doing it inside of your PrivateRoute
component, I think what you want is something more like the Redirect
component: https://reacttraining.com/react-router/web/api/Redirect
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
props.isAuthorized ? (
<Component {...props}/>
) : (
<Redirect to={{
pathname: '/',
state: { from: props.location }
}}/>
)
)}/>)
Upvotes: 1
Reputation: 4931
I would put on onEnter
method on the IndexRoute
, and programmatically send the user to the correct location as needed:
<IndexRoute onEnter={handlePath}>
where the handler looks something like this, with userIsAutheticaed
is replace by the appropriate code:
function handlePath(route, replace) {
if (userIsAuthenticated) {
replace('/dashboard');
} else {
replace('/');
}
}
Upvotes: 1