React Router match path from query string fallback

343 Views Asked by At

I want to be able to serve a React app using React Router both on an Apache and NGINX server without having to change any default Apache/NGINX configs. The problem is that the application will only be served when you access the root folder, as any sub path leads to a 404 (app.com/ works but not app.com/settings).

For the Apache server, I include a .htaccess file that automatically loads index.html if the requested resource is not found. For NGINX as far as I understand there is no way to properly load the application in a sub-path unless you change the config file.

My solution for this would be to add the option in the app to store the Router path as a query string, instead of in location.pathname, something like app.com/?page=settings instead of app.com/settings.

Is there any way to add some sort of a middleware in the React router such that when accessing app.com/?page=settings the Router path will be set to /settings. Also, when the user navigates and the router should update the URL in the address bar, it should change it to app.com/?page=user/dashboard instead of app.com/user/dashboard.

I am looking for any solution that would allow the Router to work both with a path and with the path specified as a query string variable.

If needed, here is how my router looks:

<Router history={browserHistory}>
            <Route path={BaseRoutes.Home} exact>
                <Redirect to={BaseRoutes.Domains} />
            </Route>

            <Route path={[BaseRoutes.Stats, BaseRoutes.Settings, '/*']} component={SidebarMain} />

            <div className={`content-area ${classes.content}`}>
                <Switch>
                    <Route exact path={BaseRoutes.Stats} component={Stats} />
                    <Route exact path={BaseRoutes.Home} component={Domains} />
                    <Route exact path={BaseRoutes.Settings} component={Settings} />
                </Switch>
            </div>
</Router>;
1

There are 1 best solutions below

0
XCS On

Never mind, I realized I can just use HashRouter instead of Router for NGINX...

So, depending on whether the user's setting of having "pretty" URLs or hash based URLs I can either load the BrowserHistory Router or the HashRouter:

<Router history={browserHistory}> OR <HashRouter>

To switch between them I did:

let SupportedRouter: React.ElementType = HashRouter;
if (MY_CONDITION) {
    SupportedRouter = Router;
}

// Render
<SupportedRouter history={browserHistory}>
</SupportedRouter>

I had to cast them to React.ElementType, otherwise optionally passing history lead to TypeScript errors: https://github.com/microsoft/TypeScript/issues/28631#issuecomment-472606019