Using TypeScript with React HOC, React.lazy and forwarRef

Viewed 746

I want to write an HOC that wrap a component by using React.lazy and React.Suspense in TypeScript, but I don't know how to fix the types errors.

type AsyncComponentFactory<P> = () => Promise<{ default: ComponentType<P> }>;

export function loadable<P>(factory: AsyncComponentFactory<P>): ComponentType<P> {
  const LazyComponent = React.lazy(factory);

  const WrappedWithLoadableComponent = forwardRef<P>((props: P, ref) => (
    <React.Suspense fallback={'loading'}>
      <LazyComponent {...props} ref={ref} />
    </React.Suspense>
  ));

  WrappedWithLoadableComponent.displayName = 'LazyExoticComponent(loadableComponent)';

  return WrappedWithLoadableComponent;
}

const JobsView = loadable(() => import(/* webpackChunkName: "JobsView" */ '@views/Jobs'));

Error

1 Answers

I might be wrong, but I think this is due to limitation of react. See the type of forwardRef:

    function forwardRef<T, P = {}>(render: ForwardRefRenderFunction<T, P>): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;

React expects PropsWithoutRef and you are trying to use ref. I think it is wrong. You should use this example:

import React, { ForwardRefRenderFunction } from 'react'

type IMyComponentProps = { a: string }
const MyComponentRenderFn: ForwardRefRenderFunction<HTMLDivElement, IMyComponentProps> =
    (props, ref) => <div ref={ref}>Hoopla</div>

const MyComponent = React.forwardRef(MyComponentRenderFn);
const myRef = React.createRef<HTMLDivElement>();

<MyComponent a="foo" ref={myRef} />

All credits goes to this answer

Related