Open chrisdew opened 10 years ago
We don't have a declarative way to do this currently, the manual way to do this would be to insert a fallback route in a hierarchy and fire a new route based on the current location.
Do you mind if I ask what your use case is?
Do you think <redirect ...>
should be a feature of react-router-component?
Is there an architectural reason why it hasn't been implemented, or is it a matter of time and priorities?
I have an application with several pages which are peers - i.e. /foo
, /bar
, /baz
and /quuz
.
I want the root route /
to be redirected to /baz
so that when we change the default page, user's /baz
bookmarks will still work.
If we used BazPage
as the handler
for /
, users' bookmarks would break when we changed the default page.
I see. That makes sense to me. It is just a matter of time and priorities. I think it should be rather simple to create a component that reads the current URL on mount, reaches out to its parent router and reroutes. Would be very happy to accept a PR. On Oct 15, 2014, at 5:37 PM, Chris Dew notifications@github.com wrote:
I have an application with several pages which are peers - i.e. /foo, /bar, /baz and /quuz.
I want the root route / to be directed to /baz so that when we change the default page, user's /baz bookmarks still work.
If we used BazPage as the handler for /, users' bookmarks would break when we changed the default page.
— Reply to this email directly or view it on GitHub.
Just posting my interim solution, in case it helps anyone.
function createRedirect(url) {
return React.createClass({
mixins: [NavigatableMixin],
componentDidMount: function () {
console.log('redirecting to', url);
return this.navigate(url);
},
render: function () {
return <p>redirecting to <a href={url}>{url}</a></p>;
}
});
}
<Pages className="App" path={this.props.path}>
<Page path="/" handler={DashboardPage} />
...
<Page path="/commissioning" handler={this.state.logged_in ? CommissioningPage : createRedirect("/login")}/>
<Page path="/login" handler={LoginPage}/>
<NotFound handler={NotFoundHandler} />
</Pages>
Note: This is only "mostly" functional. If for some reason if you request the redirected page directly (i.e. by typing in the URL), then it change the page location, but will display the blue link instead of showing the content of the new page. I have no idea why this is.
@chrisdew Have you found a solution to this particular problem yet? I face the same problem, page location being correct, but showing the wrong component.
@STRML I've started to work on this but I suspect I'm going about this in the wrong way.
I've gotten the following scenario to work:
/some/path -> /another/path
But when interpolation is involved, the redirect takes the literal path template (not interpolated):
/user/1234 -> /user/:userId/home //where path={"/user/:userId"} and redirectPath={"/user/:userId/home"}
The relevant code here:
Thoughts?
Not sure if I am abusing navigate()
, but I am trying to use this same approach from componentWillMount()
in order to create authentication mixins and I have the same issue there with the new route not being rendered in response to the redirect.
In my application this component handles redirects by just <Redirect path={newPath}/>
import React from 'react';
import Router from 'react-router-component';
import Loading from 'common/components/Loading';
export default React.createClass({
displayName: 'Redirect',
mixins: [Router.NavigatableMixin],
propTypes: {
force: React.PropTypes.bool,
location: React.PropTypes.string
},
performRedirect (props) {
let loc = props.location;
let location = global.location;
let currentFragment = location && location.hash;
if (props.force) {
console.debug('Forceful redirect to: %s', loc);
return location.replace(loc);
}
if (loc && loc.indexOf('#') === -1 && currentFragment) {
loc = loc +
(currentFragment.charAt(0) !== '#' ? '#' : '') +
currentFragment;
}
// let routes = this.context.router.props.children.map(x=>x.props.path || 'default');
// console.debug('Redirecting to %s, routes: %o', loc, routes);
console.debug('Redirecting to %s', loc);
this.navigate(loc, {replace: true});
},
startRedirect(p) {
clearTimeout(this.pendingRedirect);
this.pendingRedirect = setTimeout(()=> this.performRedirect(p), 1);
},
componentDidMount () {
this.startRedirect(this.props);
},
componentWillReceiveProps (props) {
this.startRedirect(props);
},
render () {
return (<Loading message="Redirecting..."/>);
}
});
Works for me; I ended up taking your code and turning it into a mixin that wraps NavigatableMixin
. The key component is the setTimeout()
, so long as you call .navigate()
outside of the React render loop the router will re-render the page correctly. Seems like a workaround for a bug within the framework but certainly works well enough for now.
For a related redirect issue https://github.com/STRML/react-router-component/issues/24#issuecomment-135113492, here's what I use that so far works even when directly typing the url:
https://gist.github.com/saidimu/2758402f7916f4e35dee
// jshint unused:true
var React = require('react');
var NavigatableMixin = require('react-router-component').NavigatableMixin;
var Redirect = React.createClass({
mixins: [NavigatableMixin],
_redirect: function(url) {
this.navigate(url);
},
propTypes: {
url: React.PropTypes.string.isRequired,
},
componentDidMount: function() {
console.log('Redirecting to %s: ', this.props.url);
this._redirect(this.props.url);
},
render: function() {
return null;
}
});//Redirect
module.exports = Redirect;
@chrisdew @jbach I wonder if the issue you faced is because of not rendering null
?
@saidimu Redirects replace the current route... you should add {replace: true}
as the second argument to navigate
@jsg2021 Where is the replace
parameter documented? I see no appreciable difference between omitting it, {replace: true}
and {replace:false}
@saidimu It's not documented. Its internal implementation. You are calling parts of the router that were not meant to be exposed. (much like context
in React) See this line.
The only difference will be your history in the browser will not include the route the redirect was on...
ex:
if /foo/bar
renders a redirect to /foo/baz
, when you arrive at /foo/baz
hitting the back button will take you to the page before you got to /foo/bar
because the redirect replaces that entry in the history.
The Redirect
component I shared above is a complete example that is heavily used in my company's application.
I'm looking for react-router-component's equivalent of https://github.com/rackt/react-router 's
<Redirect ...>
.If there isn't one, how do most users of react-router-component currently do their redirects?