Doniyor Otamurodov
Doniyor Otamurodov

Reputation: 121

How to make a lazy loading high order component in React

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>
    )
  }
}

Upvotes: 4

Views: 4768

Answers (4)

Amir Rezvani
Amir Rezvani

Reputation: 1504

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;

Upvotes: 0

Elvis Duru
Elvis Duru

Reputation: 11

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>
    );
  };
}

Upvotes: 1

Pavlo Kozlov
Pavlo Kozlov

Reputation: 1101

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')));

Upvotes: 4

Dilshod Turobov
Dilshod Turobov

Reputation: 127

you can try using already existing solutions like Loadable Components

Upvotes: 0

Related Questions