Redirect to url on commponentDidMount in App.js

I am trying to implement a feature when the user logs into the app and they have not completed their profile, they should be redirected to a certain URL, So everywhere they try to go (except logout) they should be redirected to the complete-profile URL.

I'm handling routing with react-router-dom package.

App.js

class App extends Component {
  async componentDidMount() {
    const logged = isLoggedIn();
    if (logged) {
      const completed = await hasCompleted();
      if (!completed) this.props.history.replace("/complete-profile"); //error showing here
    }
  }

  render() {
    return (
      <React.Fragment>
        <NavBar />
        <main className="container">
          <Switch>
            <Route path="/complete-profile" component={CompleteProfile} />
            <Route path="/login" component={Login} />
            <Route path="/register" component={Register} />
            <Route path="/logout" component={Logout} />
            <Route path="/" exact component={Home} />
          </Switch>
        </main>
      </React.Fragment>
    );
  }
}

So basically what I'm trying to do here in componentDidMount method is: I first check if the user is logged in. Then check if the user has completed their profile, and if it's not completed then it should redirect to /complete-profile URL.

But with this method I'm facing an error with this.props.history.replace because it does not take any props when this method is getting called I guess, and the error that is showing is this:

Unhandled Rejection (TypeError): Cannot read property 'replace' of undefined

Which is the proper way to implement this one?

Because I dont think that I should implement these 4 lines of code checking for completed profile in every single component.

Redirect to url on commponentDidMount in App.js App.js class App extends Component { async componentDidMount() { const logged  Don't wait for componentDidMount to finish before rendering, that would be a misuse of the library, wait for your authUser to finish. You can do that by utilising your isAuthenticating state property in combination with promises.

Have a look at the description of the Route component. You'll see that three props are injected for each component that's rendered using <Route /> in your code for example. <Route path="/login" component={Login} /> These props are match location history

In your code App is not rendered using Route. Because of this, you don't have access to these three injected props. That's the reason why you get the error that history is undefined.

To redirect the user, use something like the below instead, where you conditionally render a redirect or the UI depending if data is present.

class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      fetchingStatus: true,
      completed: false
    };
  }

  async componentDidMount() {
    const logged = isLoggedIn();
    if (logged) {
      const completed = await hasCompleted();
      if (!completed) this.setState({ fetchingStatus: false, completed: true })
    }
  }

  render() {
    const { fetchingStatus, completed } = this.state;
    // Render nothing, or a spinner as loading indicator
    if (fetchingStatus) return null; // waiting for details...
    // if data was fetched and registeration not completed, render redirect.
    if (!fetchingStatus && !completed) return <Redirect to="/complete-profile" />
    // Render switch and nav.
    return (
      <React.Fragment>
        <NavBar />
        <main className="container">
          <Switch>
            <Route path="/complete-profile" component={CompleteProfile} />
            <Route path="/login" component={Login} />
            <Route path="/register" component={Register} />
            <Route path="/logout" component={Logout} />
            <Route path="/" exact component={Home} />
          </Switch>
        </main>
      </React.Fragment>
    );
  }
}

More on React Router's redirect component here

How to use window.location to do redirects in JavaScript from one url application and we will leave the decision whether to use a redirect or not, to you. Or, if you are using a separate .js file, put the following code into that  But my main problem, I'm using One Signal push notifications in app.js, and I create a deep links for push notifications. So I declare one signal listener in app.js and deep links function (redirect by path) When I get one signal params I redirect to intended screen.

This sort of TypeError becomes intimately familiar when working with React. It occurs when you attempt to use methods from an object that is "undefined".

You can ensure that this.props.history is not undefined like this:

 if (this.props.history && !completed)
   this.props.history.replace("/complete-profile"); //error showing here

The npm package 'Lodash' may also be of use in avoiding these kinds of complications.

hash: used for single page apps and single page websites; host: the URL's domain; hostname: similar to host; href: the full URL; origin: the URL's  Exactly so you will be redirecting to login from Products page, you need to redirect like const location = { pathname: '/login' state: { from: 'Products' } } this.props.history.push(location) So that you know from where you were redirected and can redirect back – Shubham Khatri Jun 21 '17 at 9:40

This just a cheap trick. If you want to go to any url (including react or any other front end framework), just do :

window.location.replace(str)

str can be absolute path like "https://abcd.com", or relative-path like ("/complete-profile" which will become baseurl + "/complete-profile")

if (logged) {
      const completed = await hasCompleted();
      if (!completed) window.location.replace("/complete-profile"); //error showing here
}

Also @zacks method also works

The one that can be considered canonical to navigate to a new URL is. window.​location = 'https://newurl.com'. If you want to redirect to a  URL parameters are a fundamental aspect of React Router and a fundamental aspect of building web applications. In this post, we'll break down the 'URL Parameters' example on the React Router documentation to learn how you to effectively leverage URL parameters in your React app.

How to create a Ripple Effect on Click the Button ? Using Leaflet.js to show maps in a webpage · Create a Reflex Game using JavaScript · Design a typing speed  History in react-router listens to the browser’s address bar for anything changing and parses the URL from the browser and stores it in a location object so the router can match the specified route and render the different components for that path. We then use tags in order to specify what path we would like a component to be rendered on. In this case, we are using ‘/’ path for the components in calculate.js and ‘/result’ path for the components in result.js.

In this short article we'll cover how to redirect to internal and external pages, Let's say you want to navigate the app to the url https://www.yoursite.com/blog . Let the component mount even if the redirect will happen, but conditionally render it, returning null from render() if 'login' is missing from localStorage. If you do it this way, I'd suggest saving the local storage data in the component rather than getting it twice, for example:

Note: The difference between href and replace, is that replace() removes the URL of the current document from the document history, meaning that it is not  First way using the Redirect component. Login.js. import React from 'react'; import { Redirect } from 'react-router-dom'; class Login extends React.Component { onSubmit = () => { if(userFound){ return < Redirect to ="/posts/" /> } } render() { return ( <form> <input placeholder="email" type="email" /> <input placeholder="password" type="password" /> < button onClick ={this. onSubmit }> Login </ button > </form> ) } } export default Login;

Comments
  • You can try this stackoverflow.com/questions/37516919/…
  • There is a withRouter HOC in react-router-dom. What if you wrap your App with it before export ? Does it make your code work ? Add those two lines : import { withRouter } from 'react-router-dom' export default withRouter(App)
  • This looks great. Thank you!
  • Well this looks great of what I'm looking for. But there's one little issue. When it redirects to /complete-profile still completed is false, so it tries to redirect all the time to that url, its like an infinite loop. How can i access the current url so it wont redirect it ones it goes to /complete-profile
  • Yep, but what's the point of it if this.props.history is null? I need that property history in order to change the url.
  • React modules often go through multiple cycles as a page loads. Implementing sanity-testing is frequently necessary to contend with incomplete information such as undefined props.