React history.push() is updating url but not navigating to it in browser
Asked Answered
C

13

91

I've read many things about react-router v4 and the npm history library to this point, but none seems to be helping me.

My code is functioning as expected up to the point when it should navigate and do a simple redirect when the url is changed using the history.push() method. The URL IS changing to the specified route, but not doing the redirect on the button push.

I would like for the button push to do a simple redirect without the {forceRefresh:true}, which then reloads the whole page.

import React from 'react';
import createBrowserHistory from 'history/createBrowserHistory';

const history = createBrowserHistory({forceRefresh:true});

export default class Link extends React.Component {
  onLogout() {
    history.push("/signup");
  }
  render() {
      return(
        <div>
          <h1>Your Links</h1>
          <button onClick={this.onLogout.bind(this)}>Log Out</button>
        </div>
      )
  }
}
Caddish answered 22/3, 2017 at 2:37 Comment(0)
B
46

Check if you don't have nested BrowserRouter tags.

I had this issue on react-router v4 but I solved it after changing the app to only have the BrowserRouter at the top most level like the example below.

ReactDOM.render(
  <BrowserRouter >
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);
Babbittry answered 3/5, 2017 at 13:46 Comment(2)
I have this same problem, but still no solutionCoulombe
Thanks for the answer. I had several BrowserRouter in different modules that make up the entire app. I had to remove BrowserRouter tag from all the modules and keep the only one at the App level to have it working successfully.Aloisia
W
75

You shouldn't need to downgrade to v3, React-Router 4.0.0 is totally capable of accomplishing what the OP asked for.

const history = createBrowserHistory();

is a custom history object so you should use <Router> to synchronize it with react-router instead of <BrowserRouter>, which is what I assumed you were using.

Try this instead:

import React, {Component} from 'react';
import { Router } from 'react-router';
import { Route } from 'react-router-dom';
import createHistory from 'history/createBrowserHistory';

const history = createHistory();   

class App extends Component {
   constructor(props){
      super(props);
   }
 
   render(){
       return (
           <Router history={history}>   //pass in your custom history object
                <Route exact path="/" component={Home} />
                <Route path="/other" component={Other} />
           <Router />
       )
   }
}

Once your custom history object is passed in via Router's history prop, history.push should work just as expected in anywhere of your app. (you might want to put your history object in a history config file and import it into places where you want to route programmatically).

For more info, see: React Router history object

Wonderwork answered 8/4, 2017 at 10:17 Comment(7)
Wow thank you! This is the only answer I've seen that explains that you need to use <Router/> instead of <BrowserRouter/> when using the history package.Shrapnel
This is the most correct solution I found in my search of last 4 daysCopter
Many thanks, history now works with <Router> but basename stopped working in it. In <BrowserRouter> basename works but history not working :-(Zicarelli
Thanks a lot man. It wasnt working with BrowserRouter but after changing to Router and adding my history as param it worked like a charmLycurgus
Excellent Answer, Key reason written for noobs like meFrottage
you might need the BrowserRouter for your UI to be easier synced with URL. In that case, the best way is to use useHistory and limit the ability to change url to ReactComponent onlyGlorygloryofthesnow
Brilliant answer.Miser
B
46

Check if you don't have nested BrowserRouter tags.

I had this issue on react-router v4 but I solved it after changing the app to only have the BrowserRouter at the top most level like the example below.

ReactDOM.render(
  <BrowserRouter >
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);
Babbittry answered 3/5, 2017 at 13:46 Comment(2)
I have this same problem, but still no solutionCoulombe
Thanks for the answer. I had several BrowserRouter in different modules that make up the entire app. I had to remove BrowserRouter tag from all the modules and keep the only one at the App level to have it working successfully.Aloisia
B
8

Please ensure that you are using

const history = createBrowserHistory({forceRefresh:true});

not

const history = createBrowserHistory();

I was able to update the page once I added "{forceRefresh:true}"

Bratislava answered 26/8, 2020 at 18:43 Comment(3)
It reloads the entire page I guess this is not the expected bahviourEwold
It will also update the state as well as. This is not a correct wayMightily
You are a lifesaver man, just what I was looking forSheedy
R
6

import Router from react-router-dom not BrowserRouter

// index.js

    import React from "react";
    import ReactDOM from "react-dom";
    import App from "./App";
    import { Router } from "react-router-dom";
    import history from './utils/history'


    ReactDOM.render(
      <Router history={history}>
        <App />
      </Router>,
      document.getElementById("root"));

    serviceWorker.register();


// history.js 

import { createBrowserHistory } from 'history';

export default createBrowserHistory();

on other components that you need to navigate import history and push

import History from '../utils/history'

History.push('/home')

Radix answered 18/11, 2019 at 4:20 Comment(0)
M
5

Rendering this would refresh on route change

 `ReactDOM.render(
    <AppContainer>
      <BrowserRouter children={routes} basename={baseUrl} forceRefresh={true}/>
    </AppContainer>,
    document.getElementById("react-app")
  );`

react-router-dom : 4.2.2

Mulligan answered 3/7, 2018 at 5:7 Comment(0)
C
2

If you are using strict mode while rendering, Remove it and try again

example:

if your render method look like this

const root = ReactDOM.createRoot(
  document.getElementById('root')
);

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
);

change it to this

const root = ReactDOM.createRoot(
  document.getElementById('root')
);

root.render(
  <App />,
);
Cluff answered 19/9, 2022 at 13:34 Comment(0)
N
1

If you don't want to change router or version you could force the page to reload after updating history.

Eg:

history.push({
    'pathname': '/signup',
    'key': 'value'
})   
document.location.reload()
Namesake answered 29/3, 2022 at 21:20 Comment(0)
C
0

I have the same problem.

After some search i have found this react-router issue

I have currently downgrade react-router to the v3 and i use browserHistory from the react-router package and it's work fine.

Climb answered 23/3, 2017 at 17:32 Comment(1)
Yeah, that's what I did too, I'm planning to stick with v3 for bit now. Thanks!Caddish
S
0

If you are using functional component then try to push using useHistory Hook.

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

export default function Link{

  let history = useHistory();

  onLogout() {
    history.push("/signup");
  }

  return(
        <div>
          <h1>Your Links</h1>
          <button onClick={this.onLogout.bind(this)}>Log Out</button>
        </div>
      )
}
Schleicher answered 17/6, 2021 at 17:55 Comment(0)
A
0

you can use

forceRefresh={true}

in you code inside The BrowserRouter or inside Router

Almucantar answered 19/11, 2021 at 8:24 Comment(0)
C
0

in case somebody here with react-router-dom v6

I had the same problem and I had to downgrade to v5

and problem fixed.

Cosetta answered 31/1, 2022 at 17:53 Comment(0)
H
0

The feature is removed in react-router-dom v6. The best way would be to

  1. Create a state with default value of null and modify that state after async action, then
  2. Create an if statement inside of component that checks state and redirects.
  3. Add an dispatch action that resets the value of state to null
Hulbig answered 17/5, 2022 at 13:22 Comment(1)
please give us some exampleElisavetpol
F
0

for using history prop, you should use Router imported from "react-router" instead of BrowserRouter imported from "react-router-dom"

then history.push('/home') works as you want.

Figurative answered 3/6, 2022 at 8:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.