Multi layout react routing with 404 component and without re-rendering layout on URL change

Viewed 201

I have a Router component in my react app. Which will have 4 different types of layout.
1- Public routes like login and signup that have no layout.
2- User routes that will have UserLayout component.
3- Admin routes that will have AdminLayout component.
4- Anything other than those above should render Error404 component.
Here's my Router component:

<BrowserRouter>
                    <Switch>
                        <Route path="/" exact render={() => <Redirect to='/user/signin' />} />
                        <Route path='/oauth/:token' component={Oauth} />
                        <Route path='/user/signin' component={Signin} />
                        <Route path='/admin/signin' component={Signin} />
                        <Route path='/user/signup/:username' component={Signup} />
                        <Route path='/user/signup' component={Signup} />
                        <Route path='/oauth' exact render={() => <Redirect to={'/user/dashboard'} />} />
                        <Route path='/user/reset' component={Reset} />
                        <ProtectedRoute path='/user/auth2fa' component={TwofactorForm} />
                        <ProtectedRoute path='/admin' exact component={Error404} />
                        <ProtectedRoute path='/user' exact component={Error404} />

                        <Route path='/user'>
                            <UserLayout>
                                <Switch>
                                    //bunch of user routes
                                </Switch>
                            </UserLayout>
                        </Route>

                        <Route path='/admin'>
                            <AdminLayout>
                                <Switch>
                                    //bunch of admin routes
                                </Switch>
                            </AdminLayout>
                        </Route>


                        <ProtectedRoute component={Error404} />
                    </Switch>
            </BrowserRouter>

My problem is the 404 page. If someone goes to /user* URL that does not match the routes inside layout, they will see an empty user layout page. Same thing goes for /admin*. And if I nest the Error404 component at the end of Switch inside layout components, the result would be a layout page with a 404 page inside of it which is not what I want. How can I achieve this?

Important note: I don't want the layout components to get re-rendered on URL change. Because they are stateful and I use the header to connect to websockets, which is not ideal to reconnect to websocket on every URL change

1 Answers

You can not do this in easy ways. The best thing to do to fix this is to add condition on the data you get from the server that if data is empty, after you can use condional rendering and set if data is null you return some jsx that show this page has no data ;

// if user select /user/23
    {data?<div>empty ! </div>}

but if you select route like /usersdadsa and didnt catch any error or didnt redirect to notfound page you have to set react router in this approach //if user select /udasuasdusad

                <Route path='*' component={notfound} />

and put it in the end of your routes , when user select your route , react router try to match the user route with your routes and if any route doesnt match so they found your last route that tell react router to all path should render notfound component

Related