Last active
March 6, 2024 15:26
-
-
Save lvnam96/49bef633617a4f080c1d4add23836e05 to your computer and use it in GitHub Desktop.
Resolve issue of passing `ref` on `dynamic()` (lazy) loaded component in NextJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 />; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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).