Skip to content

Instantly share code, notes, and snippets.

@lvnam96
Last active March 6, 2024 15:26
Show Gist options
  • Save lvnam96/49bef633617a4f080c1d4add23836e05 to your computer and use it in GitHub Desktop.
Save lvnam96/49bef633617a4f080c1d4add23836e05 to your computer and use it in GitHub Desktop.
Resolve issue of passing `ref` on `dynamic()` (lazy) loaded component in NextJS
// Issue: https://github.com/vercel/next.js/issues/4957
/**
* Usage is the same as `dynamic()` from NextJS with 1 exception: `ssr` IS ALWAYS FALSE
* @param {() => any} importCallback Ex: () => import('./LazyComponent.jsx')
* @param {{ loading?: () => import('react').ReactNode }} options This can be similar to options of `dynamic()` from NextJS
*/
export const clientOnly = (importCallback, { loading } = {}) => {
const LazyComponent = lazy(importCallback);
return forwardRef(function ClientOnlyComponent(props, forwardedRef) {
const [isClient, setIsClient] = useState(false);
useEffect(() => {
setIsClient(true);
}, []);
return (
isClient && (
<Suspense fallback={loading?.()}>
<LazyComponent
{...props}
ref={forwardedRef}
/>
</Suspense>
)
);
});
};
// NormalComponent.jsx
const LazyComponent = clientOnly(()=> import('./componentA'));
// later, use component A as normal in NextJS:
export const NormalComponent = () => {
//...
return <LazyComponent />;
};
@lvnam96
Copy link
Author

lvnam96 commented Mar 6, 2024

Official workaround vercel/next.js#4957 (comment)

I still came up with this solution because I don't want to expose a special prop to contain ref (instead of official React.forwardRef) on my lazy-loaded component (then I have to write documentation/comment to explain why).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment