7

I have a page that validates a user and redirects them to a login page if validation is successful. However, the using redirect the URL changes but the new page for Login is not rendered. How can I get the new page to render?

App.js

var child;

render() {
if (this.state.toLogin && !this.state.mounted) {
    <Route exact path="/Login" component={Login} />;
    <Route exact strict path="/" render={({location}) => {
       if (location.pathname === window.location.pathname) {
             return <Redirect to="/Login"/>;
        }
    return null;
}}

return(
    <div className="App">
        <ReactCSSTransitionGroup
            transitionName="remove"
            transitionEnterTimeout={100}
            transitionLeaveTimeout={100}>
                {child}
        </ReactCSSTransitionGroup>
    </div>
    );
}

Index.js

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);

EDIT: Made changes as per answers but now the URL is not changing and the page is not rendering

Black
  • 3,680
  • 7
  • 29
  • 49
  • https://stackblitz.com/edit/react-router-starter-rb2cvc?file=index.js this works as expected, can you show what is your problem? – Just code Oct 08 '18 at 04:40
  • how do you assign a value to `var child`? Can you show full codebase of `App`? – Alex Oct 11 '18 at 04:51
  • checkout my answer @black – hannad rehman Oct 15 '18 at 12:22
  • It turns out I wasn't rendering things properly but appreciate all the answers – Black Oct 18 '18 at 02:24
  • If you came to this question because you're trying to redirect to an external page, this question is what helped me: https://stackoverflow.com/questions/42914666/react-router-external-link/44563899#44563899 – Pro Q Mar 24 '20 at 17:49

7 Answers7

5

if you are using react-router-dom wrap your component export in withRouter provided by react-router-dom .

and all component usage should be returned from render. then only react knows what to render.

import React from 'react'
import { withRouter, Redirect } from 'react-router-dom';

class App extends React.Component {

render() {
if (this.state.toLogin && !this.state.mounted) {
  return (
    <React.Fragment>
      <Route exact path="/Login" component={Login} /> 
      <Route exact strict path="/" render={({location}) => {
          if (location.pathname === window.location.pathname) {
              return <Redirect to="/Login"/>;
          }
          return null;
      }} />
  </React.Fragment>
  );
}

return (
  <div className="App">
    <ReactCSSTransitionGroup
        transitionName="remove"
        transitionEnterTimeout={100}
        transitionLeaveTimeout={100}>
            {child}
    </ReactCSSTransitionGroup>
</div>
)}

}
export default withRouter(App)
hannad rehman
  • 3,168
  • 1
  • 26
  • 44
  • Undoubtedly, your answer is correct. this was my damn issue too and `withRouter` help me. but I don't know why, Why the `withRouter` HOC fix this issue? – AmerllicA Oct 14 '18 at 17:36
  • 1
    @AngelHotxxx, I have mentioned in my answer why withRouter solves the problem, you can check it – Shubham Khatri Oct 14 '18 at 17:48
  • @AngelHotxxx for `react-router-dom` it needs some routing related props. which are used to change the browser route and add url to history object etc. that are given by this `withRouter` HOC – hannad rehman Oct 15 '18 at 09:27
0

You need remove "exact" and "component={Login}" of the Component and add new Component <Route exact path="/Login" component={Login} />

render() {
  if (this.state.toLogin && !this.state.mounted) {
      <Route exact path="/Login" component={Login} /> 
      <Route exact strict path="/" render={({location}) => {
          if (location.pathname === window.location.pathname) {
               return <Redirect to="/Login"/>;
          }
          return null;
  }} />
}

Luck!

  • I tried the change but I still don't see the page rendering. I've added the entirety of the `App.js` in case something is interfering – Black Oct 04 '18 at 06:00
0

Do not do that here, Use your authentication middle ware to do re directions according to the authorization/ rights.

Nilanka Manoj
  • 3,097
  • 3
  • 10
  • 37
0

You have missed a couple of returns. Your render function has to return your routes, and your routes have to be wrapped on some element.

  render() {
    if (this.state.toLogin && !this.state.mounted) {
      return (
        <React.Fragment>
          <Route exact path="/Login" component={Login} /> 
          <Route exact strict path="/" render={({location}) => {
              if (location.pathname === window.location.pathname) {
                  return <Redirect to="/Login"/>;
              }
              return null;
          }} />
      </React.Fragment>
      );
    }

    return //Something according to your logic
}
Yoan
  • 1,961
  • 10
  • 20
0

Make sure "component" and "path" keyword in route tag should be in Small Letter(component instead for Component

-1

In order for the Routes to works, the component which uses Route must receive the Route parameters

In your case the App component doesn't seem to receive the Route parameters as props. You could simply render it as a default Route or use withRouter HOC to wrap the App component

ReactDOM.render(
  <BrowserRouter>
    <Route component={App} />
  </BrowserRouter>,
  document.getElementById('root')
);
Shubham Khatri
  • 211,155
  • 45
  • 305
  • 318
-1

Seems like you do not return your routes. Try moving your routes to the place where you are initializing your router and wrap it with App:

<Router>
  <Route component={App}>
    <Route exact path="/Login" component={Login} />;
    <Route exact strict path="/" render={({location}) => {
       if (location.pathname === window.location.pathname) {
         return <Redirect to="/Login"/>;
       }
       return null;
    }/>
  </Route>
</Router>

And then in your App component just use children to render page content:

render() {
    return (
      <div className="App">
        <ReactCSSTransitionGroup
          transitionName="remove"
          transitionEnterTimeout={100}
          transitionLeaveTimeout={100}
        >
                {this.props.children}
        </ReactCSSTransitionGroup>
      </div>
    );
  }
Eugene Tsakh
  • 2,441
  • 2
  • 11
  • 25