27

I'm using react-router, so I use the <Link /> component for my links throughout the app, in some cases I need to dynamically generate the link based on user input, so I need something like window.location, but without the page refresh.

I found this little note - (https://github.com/rackt/react-router/issues/835) - i tried using this.context.router.transitionTo(mylink) but I'm having issues with context...

which led me to (https://github.com/rackt/react-router/issues/1059), however context returns and empty object, so when I try todo something like: this.context.router.transitionTo(mylink); I get Cannot read property 'transitionTo' of undefined (if I try to do something like set this.context = context within the constructor).

Not to drag on, but I'm also weary of messing too much with context as it is undocumented on purpose as it's still a work in progress, so I've read.

Has anyone come across a similar issue?

Ben
  • 4,595
  • 7
  • 30
  • 42

7 Answers7

19

After wasting time with react router, I finally switch to basic javascript.

  1. Create a component for your redirect:

    Route path="*" component={NotFound}

  2. In the component use window.location to redirect:

     componentDidMount() {
          if (typeof window !== 'undefined') {
               window.location.href = "http://foo.com/error.php";
          }
     }
    
Priyanshu Chauhan
  • 4,473
  • 3
  • 28
  • 31
  • the question is tagged react-router -- if you are advocating not using that tool you should give a detailed explanation about why it won't work – jcollum Oct 10 '18 at 18:51
  • 6
    Don’t fall into the [trap of thinking a library should prescribe how to do everything](http://amasad.me/2016/01/03/overcoming-intuition-in-programming/). If you want to do something with a location in JavaScript, you can use window.location. There is no reason why react-outer should be any different. – Priyanshu Chauhan Oct 11 '18 at 05:37
13

If you are using browserHistory for React-router, life is simpler.

import {browserHistory} from "react-router";

functionName() {
 browserHistory.push("/path-to-link");
}
  • 19
    Error: 'react-router' does not contain an export named 'browserHistory'. – Sean Mar 26 '18 at 01:12
  • The way to use browserHistory has changed. https://stackoverflow.com/questions/43822589/react-router-v4-browserhistory-is-undefined – Axonn May 20 '21 at 08:48
12

Found a solution here: https://github.com/rackt/react-router/issues/975, and here: https://github.com/rackt/react-router/issues/1499

Needed in constructor:

class SidebarFilter extends React.Component {

    constructor(props, context) {
        super(props, context);

Also need to add a static property:

SidebarFilter.contextTypes = {
  router: React.PropTypes.func.isRequired
};

Then I could call:

this.context.router.transitionTo(/path-to-link);
Ben
  • 4,595
  • 7
  • 30
  • 42
2

Take a look at the Navigation mixin from react-router. http://rackt.github.io/react-router/#Navigation

From the docs:

var Navigation = require('react-router').Navigation;

React.createClass({
  mixins: [Navigation],

  render: function() {
    return (
      <div onClick={() => this.transitionTo('foo')}>Go to foo</div>
      <div onClick={() => this.replaceWith('bar')}>Go to bar without creating a new history entry</div>
      <div onClick={() => this.goBack()}>Go back</div>
    );
  }
});
paulshen
  • 324
  • 1
  • 2
  • 7
  • 4
    Thanks @paulshen. Unfortunately I'm using ES6 classes, so I can't use mixins. I'm not sure if it's possible, but I'm trying to import the Navigation method, e.g. `import {Navigation} from 'react-router'`... trying to see if that's possible, running into some issues with `this.context` within the transitionTo that I'm trying to figure out now. – Ben Jul 21 '15 at 19:36
2

In such a situation i normally use hashHistory or browserHistory depending on what you are using and simply call hashHistory.push(<url>). If you are using ES6 classes you can also go for the withRouter Hoc provided by react-router as mentioned here. This higher order component exposes a prop in your component called router. Using this prop you can redirect using this.props.router.push(<url>).

If you have to use the router from the context you will have to provide the context types as mentioned in @Ben's answer.

Nahush Farkande
  • 3,756
  • 3
  • 21
  • 31
  • the link is broken, I came across a similar problem today, is there any better solution available now? – Saravana Oct 31 '19 at 03:34
2

Use Link from react-router-dom, in my snippet I was using the material-ui <Button>

import {Link} from "react-router-dom";
    
<Button color="primary" 
to="/join" component={Link}>
Join a Room
</Button>
Muhammad Dyas Yaskur
  • 4,300
  • 8
  • 27
  • 48
aHardReset
  • 21
  • 3
0

Use useHistory to get the history object and push to it to change the url

import { useHistory } from 'react-router-dom';

export default function ModificarUsuario({ url }) {
  const history = useHistory();
  
  function newRoute(){
    history.push('/my-route')
  }
}
Bill Tür
  • 2,815
  • 23
  • 33
  • 37