How to make react router replace component only after the matched route asynchronously loaded..?

296 Views Asked by At

So here's the situation - When a Link is clicked the nprogress bar will start and I want react-router to only replace the current component with the matched route once that's done loading asynchronously.. just like in instagram..

enter image description here

But I am only getting this -

enter image description here

Here's my HOC to load component asynchronously --

import React, { useEffect, useState } from "react";
import nprogress from "nprogress";
import "nprogress/nprogress.css";

export default importComponent => props => {
  const [loadedComponent, setComponent] = useState(null);

  // this works like componentwillMount
  if (!nprogress.isStarted()) nprogress.start();

  if (loadedComponent) nprogress.done();

  useEffect(() => {
    let mounted = true;

    mounted &&
      importComponent().then(
        ({ default: C }) => mounted && setComponent(<C {...props} />)
      );

    // componentUnMount
    return () => (mounted = false);
  }, []);

  // return the loaded component
  const Component = loadedComponent || <div style={{ flexGrow: 1 }}>..</div>;
  return Component;
};

I didn't find a solution to this anywhere on the internet.. so I am asking this question here in stackoverflow. I am hoping someone here can solve this.

1

There are 1 best solutions below

0
On

Edit: 15-Nov-2021

The old approach doesn't work with routes that uses route params or query such as useLocation, useRouteMatch, etc.

The one I am using now is to use React.lazy, React.Suspense and updating the fallback prop whenever a page is rendered. So when the next page is being loaded, the fallback will be shown which is basically the same component instance as current page. Moreover, with this new approach, you can render the next page whenever you like; after fetching data from backend, or after animation, etc.

Here is a demo and source code.