0

I am creating a react app with react-router@latest and with code splitting. Everything works fine except the layout component re-renders everything when ever I click on About link or a dashboard link. Please help me out how to fix this. I had already read many blog posts but didn't get any solution that works for me.

I had created a repository for that https://github.com/riyasat/ReactRouterTest.

Here are my components

Main Component

const Main = () => {
  // const Layout = React.lazy(()=>import('../Core/Layout'));
    return (
        <div>
      <ErrorBoundary>
            Router Test
            <Switch>
                    <Route exact path="/">
                        <Redirect to="en"></Redirect>
                    </Route>
                    <Route path="/:lang"
                    >
            <Layout/>
          </Route>

            </Switch>
      </ErrorBoundary>
        </div>
    );
};
export default Main;

Layout Component

import React, { Suspense, useEffect } from "react";
import { Redirect, Route, Switch, useRouteMatch } from "react-router-dom";

const Layout = () => {
    const { url, path } = useRouteMatch();
    const About =React.lazy(() => import("../Views/About"));
    const Dashboard = React.lazy(() => import("../Views/Dashboard"));

    useEffect(() => {
        console.log("Layout Mounted");
        return () => {
            console.log("Un Mounted");
        };
    });
    return (
        <div>
            This is Router
            <Switch>
                <Route exact path={`${path}`}>
                    <Redirect to={`${url}/about`} />
                </Route>
                <Route exact path={`${path}/about`}>
          <About/>
        </Route>
                <Route exact path={`${path}/dashboard`} >
          <Dashboard/>
        </Route>
            </Switch>
        </div>
    );
};
export default Layout;

About Component

const About = () => {

  return (
    <div>
      <Link to="dashboard">Dashboard</Link>   
    </div>
  )
}
export default About;

Dashboard Component

const Dashboard = () => {
 
  return (
    <div>
      <NavLink to={`about`}>About</NavLink> 
    </div>
  )
}
export default Dashboard;
Riy
  • 479
  • 1
  • 8
  • 16

1 Answers1

1

It's because the useRouteMatch causes the component it is in to re-render whenever there is a change in URL. If you remove that and change the url and path to a fixed value (i.e a string) then the Layout Component should not re-render when route change anymore

kunquan
  • 1,127
  • 1
  • 10
  • 24
  • I do not think this is the problem, I took this example from reactrouter.com official documentation and they have used same hook. But just for the sake of experiment I tried what you have suggested but still layout is re-rendring now my layout component looks like . Any more thoughts ? and yes I removed the hook as well. – Riy Nov 30 '20 at 06:56
  • 1
    @Riy check out this [demo](https://codesandbox.io/s/react-router-basic-forked-i2m5h?file=/example.js) I made. I remove the `useRouteMatch` and when I tried to change route the `Layout` component no longer re-render – kunquan Nov 30 '20 at 07:49
  • you are right if I add any hook from react-router it re-renders layout. In this way I would not be able to create a dynamic routes. e.g. my case is I have to use language pre fix in route and rest of the routes will come under the main route. [demo](https://codesandbox.io/s/react-router-basic-forked-wwiu1?file=/Core/Layout.js) I forked your example and made changes to that. Can you please help me how can I achieve that? thanks – Riy Nov 30 '20 at 10:29