Home > front end >  React router conditional routes not working
React router conditional routes not working

Time:10-14

I have a couple of routes I want to show only when a certain condition is met. If this condition is met, and the routes are enabled navigating to them through the URL is not possible, and the Redirect always gets hit

constructor(props: {}) {
    super(props);
    this.state = {
        configuration: new Configuration({}),
}

async function GetConfiguration() {
    try {
        var response = await fetch("/getconfiguration");
        return await response.json();
    }
    catch (error) {
        console.log(error);
    }
}

async componentDidMount() {
    ...
    var configuration = await GetConfiguration();

    this.setState({ configuration: configuration });
    ...
}

render() {
...
<Router>
    <Switch>
        <Route exact path="/my-account">
            <div className='dw-side-menu'></div>
                ...
        </Route>
        {this.state.configuration.shouldRoute && <Route exact path="/my-company"><div>my company</div></Route>}
        {this.state.configuration.shouldRoute && <Route exact path="/user-management"><div>user management</div></Route>}
        <Redirect to="/my-account" />
    </Switch>
</Router>
...
}

The awkward thing is that, when I click on the Link somewhere else on the page, the routing to, e.g. /my-company, works - but not if I type the URL into the browser it only goes to the redirect, as if the routes are not there at all. Also if I hit refresh when on /my-company I get redirected back to the my-account. Without the conditions everything is working fine.

Without Redirect, entering the URLs and Refreshing the browser works as expected, just that I don't get redirected when a route is not recognized.

What am I doing wrong?

CodePudding user response:

As suspected in my comment, this.state.configuration.shouldRoute is undefined on first render.

One workaround for this would be to actually display a loading state until you have loaded the configuration, like so:

// in render(), before your other return
if(Object.keys(this.state.configuration).length === 0){
  // config has not been loaded yet
  return (<MyCoolLoadingComponent />)
}

If displaying a loading indicator before the config is loaded is an option, go with it. If it is not, you have to rethink your architecture.

CodePudding user response:

To make your code cleaner, with less bugs, put sections of codes into individual components. Then you could say:

class SideMenu extends component {
    render(
        <div className='dw-side-menu'></div>
                ...
    )
}
class MyCompany extends component {
    render(
        <div>my company</div>
                ...
    )
}
class UserManagement extends component {
    render(
        <div>user management</div>
                ...
    )
}
render() {
...
<Router>
    <Switch>
        <Route exact path="/" component={HomePage} />
        <Route path="/my-account" component={MyAccount} />
        <Route path="/my-company" component={MyCompany} />
        <Route path="/user-management" component={UserManagement} />
        <Redirect to="/my-account" />
    </Switch>
</Router>
...
}

Cleaner code with less issues. Hope this helps. You can as well use some of the powerful features in react-router-dom; location, history and match. Thanks.

  • Related