I am using react-router for client side routing. I have a button and when some one clicks the button, I want to redirect the user to a different url. For e.g I want to redirect the user to "http://www.google.com". I used navigation mixin and used this.transitionTo("https://www.google.com"). But when I do this I get this error Invariant Violation: Cannot find a route named "https://www.google.com".
I can use window.location but is that the right way to go?
Use the window. location. replace() method to redirect to an external url in React, e.g. window.
Use the Navigate element to set a default route with redirect in React Router, e.g. <Route path="/" element={<Navigate to="/dashboard" />} /> . The Navigate element changes the current location when it is rendered. Copied!
As pointed out in the comments to this answer, default way of solving this would be to use anchor element (the a
tag) with href
attribute that points at the destination URL that you'd like to route the user to. A button that has appearance of a button but behavior or an anchor is pretty much a web anti-pattern. See more info in this answer: https://stackoverflow.com/a/1667512/1460905.
That said, there certainly is a potential scenario when a web app needs to perform some action and only then redirect the user. In this case, if primary action the user takes is submitting some data or really performing an action, and redirect is more of a side-effect, then the original question is valid.
In this case, why not use location
property of window
object? It even provides a nice functional method to go to external location. See the ref.
So, if you have a component, say
class Button extends Component {
render() {
return (
<button onClick={this.handleClick.bind(this)} />
);
}
}
then add handleClick
that would make the component look like
class Button extends Component {
handleClick() {
// do something meaningful, Promises, if/else, whatever, and then
window.location.assign('http://github.com');
}
render() {
return (
<button onClick={this.handleClick.bind(this)} />
);
}
}
No need to import window
since it's global. Should work perfectly in any modern browser.
Also, if you have a component that is declared as a function, you may possibly use the effect hook to change location when state changes, like
const Button = () => {
const [clicked, setClicked] = useState(false);
useEffect(() => {
if (clicked) {
// do something meaningful, Promises, if/else, whatever, and then
window.location.assign('http://github.com');
}
});
return (
<button onClick={() => setClicked(true)}></button>
);
};
You don't need react-router
for external links, you can use regular link elements (i.e. <a href="..."/>
) just fine.
You only need react-router
when you have internal navigation (i.e. from component to component) for which the browser's URL bar should make it look like your app is actually switching "real" URLs.
Edit because people seem to think you can't use an <a href="..."
if you need to "do work first", an example of doing exactly that:
render() {
return <a href={settings.externalLocation} onClick={evt => this.leave(evt)}/>
}
async leave(evt) {
if (this.state.finalized) return;
evt.preventDefault();
// Do whatever you need to do, but do it quickly, meaning that if you need to do
// various things, do them all in parallel instead of running them one by one:
await Promise.all([
utils.doAllTheMetrics(),
user.logOutUser(),
store.cleanUp(),
somelib.whatever(),
]);
// done, let's leave.
this.setState({ finalized: true }), () => evt.target.click());
}
And that's it: when you click the link (that you styled to look like a button because that's what CSS is for) React checks if it can safely navigate away as a state check.
preventDefault()
,You can try and create a link element and click it from code. This work for me
const navigateUrl = (url) => {
let element = document.createElement('a');
if(url.startsWith('http://') || url.startsWith('https://')){
element.href = url;
} else{
element.href = 'http://' + url;
}
element.click();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With