0%
July 12, 2021

Lazy React Router

react

Routing in This Blog Page

The routing of this react application is controlled by the following single router.ts file:

interface IRouter {
  path: string;
  component: () => JSX.Element;
  exact?: boolean;
  routes?: IRouter[];
}

const routers: IRouter[] = [
  {
    path: navRoutes.ROOT,
    component: MainContent,
    routes: [
      {
        path: navRoutes.ABOUT,
        component: About,
        exact: true,
      },
      {
        path: navRoutes.SKILLS,
        component: Skills,
        exact: true,
      },
      ...{
        path: `${navRoutes.BLOG}`,
        component: Blog,
        exact: false,
      },
    ],
  },
];

Note that for a sub-routing of navRoutes.BLOG (/blog) to work, exact: false is important.

MainContent is the largest container where we want to switch from one component to another.

I used to add another Switch in Blog component to achive this sub-routing, but recently I find a much convenient way. I call this a lazy routing since it can really achive routing in an extremely lazy but cleaner way by using useRouteMatch.

The Blog component now has the following structure:

export default () => {

  ...

  const match = useRouteMatch<{ matchedArticleTitle: string }>(
    `${navRoutes.BLOG}/:matchedArticleTitle`
  );
  const { matchedArticleTitle } = match?.params || { matchedArticleTitle: "" };

  ...

  const activeBlogArticleTitle = useAppSelector(
    (state: TRootState) => state.app.blog.activeBlogArticleTitle
  );
  const selectedArticle = articles.find(
    md => md.title === activeBlogArticleTitle
  );

  ...

  useEffect(() => {
    dispatch(appActions.updateBlog(
      { activeBlogArticleTitle: matchedArticleTitle }
    ));
  }, [matchedArticleTitle]);

  return (
    <div className="blog">
      ...
    </div >
  )
}

useRouteMatch catches the param in exactly the way we want. And this is cleaner than using Route in the sense that you can observe which route, in which way, affects this component directly inside the code of this component.

Now on matchedArticleTitle changed, our useEffect hook will update the state of activeBlogArticleTitle in our redux store. And we can change our content based on this unique article name (as selectedArticle is changed).