How to make a lazy loading high order component in React

3.9k views Asked by At

So here is the main idea, HOC that is be able to load any wrapped in component with React.lazy and React.Suspense. Is it possible??? So, I already was able to write some, but not sure that I was able to made properly...

import React, { Suspense, lazy, useState, useEffect } from "react"

export function withLazyImport(LazyComponent) {
  return (props) => {
    const [loadedComponent, setLoadedComponent] = useState(null)

    useEffect(() => {
      setLoadedComponent(lazy(() => import(<LazyComponent {...props} />)))
      //eslint-disable-next-line
    }, [])

    return (
      <Suspense fallback="Lazy component is loading ...">
        {loadedComponent}
      </Suspense>
    )
  }
}
4

There are 4 answers

0
Dilshod Turobov On BEST ANSWER

you can try using already existing solutions like Loadable Components

0
Amir Rezvani On

this also worked for me:

import { Suspense, FC, LazyExoticComponent } from "react";

function withLoadable<P extends object>(Component: LazyExoticComponent<FC>) {
  return function Loadable(props: P) {
    return (
      <Suspense fallback={"loading"}>
        <Component {...props} />
      </Suspense>
    );
  };
}

export default withLoadable;

1
Pavlo Kozlov On

I don't understand why do you use useEffect. The resulted component will not pass new props to the lazy component because props are passed on did mount.

I came up with another solution based on the example provided by the author of this question

import React, { Suspense } from 'react';

export const withLazyComponent = (LazyComponent) => {
  return (props) => (
    <Suspense fallback="Lazy component is loading ...">
      <LazyComponent {...props} />
    </Suspense>
  )
}

And then you use it like:

const LazyComponent = withLazyComponent(React.lazy(() => import('path/to/component')));
0
Elvis Duru On

Here's how to achieve it in TypeScript

import { Loader } from "../components/loader";
import { Suspense } from "react";

/**
 * HOC to wrap a component in a Suspense component.
 */

export default function withSuspense<P>(Component: React.ComponentType & any) {
  return function WithSuspense(props: P) {
    return (
      <Suspense fallback={<Loader />}>
        <Component {...props} />
      </Suspense>
    );
  };
}