React Router - Stay at the same page after refresh

2020-07-23 04:35发布

问题:

I'm learning React. I have page with 4 subpages and i use React Router to go through those pages. Everything works fine except for reloading page. When i go from page "home" to "about" or other it's ok, but when i refresh page then it render again page "about" for a second and then it change page to home (home is default/first page).I want it to stay at that page which is currently rendered, not go back to home after every refresh. There is my code in index.js file where i render whole app and use router:

<Provider store={store}>
    <Router path="/" history={browserHistory}>
        <Route path="/home" component={App}> 
            <Route path="/" component={Home}/>
            <Route path="/allhotels" component={AllHotels}/>
            <Route path="/addhotel" component={AddHotel} />
            <Route path="/about" component={About} />
        </Route>
        <Route path="/signin" component={SignIn} />
        <Route path="/signup" component={SignUp} />
    </Router>
</Provider>, document.getElementById('root')

In "App" i have Navigation and there i render rest of conent from Home, AllHotels etc.

There is code from App.jsx

class App extends Component {

render() {
    return (
        <div className="app-comp">
            <Navigation />
            <div> {this.props.children}</div>
        </div>
    )
  }
}

I also attach gif which shows my problem.

https://gifyu.com/image/boMp

In backend i use Firebase if it's important.

Thanks in advance.

回答1:

Check that firebase does not interfares with the client side routes :P

You can use Index routes to achieve this.

You have your navigation i.e the layout of all pages in your app component so make it the root route.

Then you want your home route to be your default route so make it your Index route.

You need to import IndexRoute from react-router package (from which you import Route).

Add this-

import { Router, Route, IndexRoute } from 'react-router';

and then make your routes like below.

Use this-

<Provider store={store}>
    <Router history={browserHistory}>
        <Route path="/" component={App}> 
            <IndexRoute component={Home} />
            <Route path="/home" component={Home}/>
            <Route path="/allhotels" component={AllHotels}/>
            <Route path="/addhotel" component={AddHotel} />
            <Route path="/about" component={About} />
        </Route>
        <Route path="/signin" component={SignIn} />
        <Route path="/signup" component={SignUp} />
    </Router>
</Provider>, document.getElementById('root')


回答2:

it's a Server-side vs Client-side issue check the following thread, it might give you some insights.. React-router urls don't work when refreshing or writting manually



回答3:

I found the reason of my problem. I use also Firebase in my project and it causes the problem. Thanks guys for help.

EDIT ======================================================================

Mabye I will write how I've fixed my problem and what was the reason of it. So i was checking if user is logged in or not in auth method. And there if user was authorized I was pushing / to browserHistory. It was mistake because every refresh method was executing and then also redirection was called as well. Solution is just to check if during executing auth method I'm on Signin page or not. If it is Signin page then I'm pushing / to browserHistory but if not then just don't push anything.

    firebaseApp.auth().onAuthStateChanged(user => {
     if (user) {
        let currentPathname = browserHistory.getCurrentLocation().pathname;
        if( currentPathname === "/" || currentPathname === "/signin"){
          browserHistory.push('/');
        }
        const { email } = user;
        store.dispatch(logUser(email));
     }
     else {
        browserHistory.replace('/signin');
     }
    })

I know that it's not pretty solution but it works and it was only home project which was created to learn react. (btw this project is using old react router 3.0 so probalby now using browserHistory is deprecated)



回答4:

Add into your webpack.config.js this option

devServer: {
    historyApiFallback: true
},


回答5:

Route tag returns the first matching component. I think you have interchanged the paths of home and app component.

try this.

<Provider store={store}>
    <Router path="/" history={browserHistory}>
        <Route path="/" component={App}> 
            <Route path="/home" component={Home}/>
            <Route path="/allhotels" component={AllHotels}/>
            <Route path="/addhotel" component={AddHotel} />
            <Route path="/about" component={About} />
        </Route>
        <Route path="/signin" component={SignIn} />
        <Route path="/signup" component={SignUp} />
    </Router>
</Provider>, document.getElementById('root')


回答6:

Below example you can refer for :

  • React Router Navigation
  • Browser Refresh Issue.
  • Browser Back Button Issue.

Please make sure you have installed react-router-dom

If not installed. Use this command to install npm i react-router-dom

index.js

   import React from "react";
   import ReactDOM from "react-dom";
   import { BrowserRouter, Route, Switch } from "react-router-dom";

   import Page1 from "./Page1";
   import Page2 from "./Page2";

    const rootElement = document.getElementById("root");
    ReactDOM.render(
      <BrowserRouter>
       <Switch>
        <Route exact path="/" component={Page1} />
        <Route path="/page2" component={Page2} />
      </Switch>
      </BrowserRouter>,
      rootElement
    );

Page1.js

   import React from "react";
   import {Link } from "react-router-dom";

    function Page1() {

        return (
          <div>
            <p>
              This is the first page.
              <br />
              Click on the button below.
            </p>
            <Link to="/page2"><button>
              Go to Page 2 
            </button>
            </Link>
          </div>
        );

    }

    export default Page1;

Page2.js

   import React from "react";

   function Page2() {

        return (
          <div>
            <p>This is the second page.</p>
          </div>
        );

    }

    export default Page2;