32

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
  • 5,283
  • 9
  • 35
  • 44

10 Answers10

31

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
  • 5,297
  • 5
  • 35
  • 34
  • 3
    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
  • 13
    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
14

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
  • 5,283
  • 9
  • 35
  • 44
12

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

import {browserHistory} from "react-router";

functionName() {
 browserHistory.push("/path-to-link");
}
  • 20
    Error: 'react-router' does not contain an export named 'browserHistory'. – Sean Mar 26 '18 at 01:12
  • 1
    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
3

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
  • 6,914
  • 10
  • 48
  • 73
aHardReset
  • 31
  • 4
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
  • 374
  • 1
  • 2
  • 7
  • 5
    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
  • 5,290
  • 3
  • 25
  • 35
  • 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
1

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')
  }
}
1

the best way is to use useHistory from react-router-dom. First you have to import it :

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

Then , you have to declare an instance of it by doing this :

  let history = useHistory();

then inside an arrow function or whatever are your case do this :

history.push("Type here your route link not a domain not anythins else ... .")
Iheb Saad
  • 327
  • 2
  • 6
0

Hmmm. I ended up having to do this (I think I'm running an older version of react 16.14.0, react-router, react-router-dom, and history 5.3.0 and other dependencies for compatibility reasons):

import (createBrowserHistory) from 'history';

const broswerHistory = createBrowserHistory();

const SomeFunction = props => {
   browserHistory.push('Thepath');
   browserHistory.go('SamePath');
}

The push by itself just put the path into the browser address bar without going there. The go by itself just reloaded the current page.

Hope this helps someone out.

Owen
  • 426
  • 5
  • 15
0

You can use this to avoid reloading:

this.props.history.push({
  pathname: `/page/${id}/something`
})