SEVO
SEVO

Reputation: 41

Redirect does nothing in react-router-dom

import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom";
class App extends Component {
  constructor(){
    super();
    this.state = {
      windowWidth: window.innerWidth,
      navOpen: true,
      user: {
        id: '',
        name: '',
        email: ''
      }
    };
  }

  signIn = (data) => {
    if(data){
      this.setState({user: {
        id: data.id,
        name: data.name,
        email: data.email
      }});
      return <Redirect to='/'/> /*Right here when it come to here the page does nothing and no errors?*/
    }
  }

render() { 
    return(
      <div className='app'>
      <Router>
        <NavBar onNavClick={this.onNavClick} navOpen={this.state.navOpen}/>
        <Switch>
          <Route path="/" exact component={() => <Home />} />
          <Route path="/about" exact component={() => <About />} />
          <Route path="/contact" exact component={() => <Contact />} />
          <Route path='/catalogue' exact component={() => <Catalogue />} />
          <Route path='/login' exact component={() => <Login signIn={this.signIn} onRouteChange={this.onRouteChange}/>}/>
        </Switch>
      </Router>
      </div>
      );
  }
}
export default App;

I have tried again and again but it will not change the page to the root and will not come with any errors with it. I have looked everywhere but its just the same thing. The log in page just runs sign in function. What am I doing wrong?

Upvotes: 2

Views: 1520

Answers (3)

Drew Reese
Drew Reese

Reputation: 203408

Issues

  1. You can't just return JSX from a function callback like that and expect it to be rendered, you will need to use the history object and issue an imperative redirect, i.e. history.replace("/");.
  2. The redirect won't work from the signIn callback since the App component is outside the routing context provided by Router being rendered by App.
  3. You are using the Route's component prop to render components but you are using an inline function, this will actually unmount and remount the components anytime App rerenders.

Solution

  1. Move the Router component higher in the React tree in order for App to be able to access the same routing context the Routes are. You will need to also pass the history object to App. This would be trivial if App were a functional component where you could use the useHistory React hook, but since it isn't you will need to use the slightly less trivial withRouter Higher Order Component and inject the route props.

    Access history from injected props:

    signIn = (data) => {
      if (data) {
        this.setState({user: {
          id: data.id,
          name: data.name,
          email: data.email
        }});
        this.props.history.replace("/");
      }
    }
    

    Decorate App with withRouter HOC:

    export default withRouter(App);
    

    Wrap App in the Router.

    <Router>
      <App />
    </Router>
    
  2. Fix the routes by using the component prop correctly, and using the render prop when you need to pass additional props.

    <Switch>
      <Route path="/about" component={About} />
      <Route path="/contact" component={Contact} />
      <Route path='/catalogue' component={Catalogue} />
      <Route
        path='/login'
        render={() => <Login signIn={this.signIn} onRouteChange={this.onRouteChange}/>}
      />
      <Route path="/" component={Home} />
    </Switch>
    

Upvotes: 1

TeslaXba
TeslaXba

Reputation: 357

Please take a look at the history https://reactrouter.com/web/api/history. For example, you can write history.push("/location"); the page will be redirected, and the states still don`t get lost. For me, it has been the easiest way to handle the redirecting in react.

Upvotes: 0

samuel potter
samuel potter

Reputation: 209

for the / for the home you need to specify

<Route exact path="/" component={Home} />

Upvotes: 0

Related Questions