First off, thanks for the great library.
I am currently building a server-side rendered application, using Loadable Components (5.12.0) for 'component-level' code-splitting. The application contains a componentSwitch component which consumes an array of objects provided by a CMS - the component iterates over this array and returns a <Component /> for each object using an id key to target the relevant directory
const Component: LoadableComponent<any> = loadable(() =>
import(`../presentation/${id}`)
)
return (
<ErrorBoundary key={guid}>
<Component {...data} />
</ErrorBoundary>
)
This works just fine when the IDs returned from the server match-up to components in the application, but if the CMS returns an ID which doesn't have a matching component present in the application I get the following error;
Uncaught Error: Cannot find module './SomeComponent'
Initially I wrapped the Loadable import in a try/catch, but Loadable doesn't throw an error if the imported module cannot be found, instead it returns the following;
// console.log(SomeComponent)
$$typeof: Symbol(react.forward_ref)
render: 茠 (props, ref)
preload: 茠 (props)
load: 茠 (props)
I attempted to hack around this by running the load method on the returned Loadable before returning the <Component /> from the switcher:
try {
Component.load();
} catch (error) {
return null;
}
This hack gets shut of the original error(s), but results in a server/client mismatch warning;
Warning: Expected server HTML to contain a matching <main> in <div>
Right now I am building an array[str] of IDs for each component present in the directory, e.g. ['Hero', 'Statement'] - I then check if the incoming ID is present in the array, if so create a Loadable, else return null. I am satisfied with this approach, however I would much prefer to check if the module exists in a more 'dynamic' fashion.
Any guidance will be very much appreciated.
Hey @iamdcj :wave:,
Thank you for opening an issue. We'll get back to you as soon as we can.
Please, consider supporting us on Open Collective. We give a special attention to issues opened by backers.
If you use Loadable at work, you can also ask your company to sponsor us :heart:.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I faced with a similar case, and I don't know how I can fix it.
Please can this be re-opened.
use import { lazy } from '@loadable/component' and loadable will throw an error __to a nearest Error boundary__, where you can react on it.
I am currently building a server-side rendered application.
Suspense and Error boundaries are client-side only implementations.
I see. Right now in case of "module not found" during SSR loadable would _think_ - "oh, that is client-side, let's call import!"
So what is expected behaviour - be able to "try" file first (like Component.load();) or fallback to ErrorComponent?
I appreciate the reopening of the ticket, but it feels like my opening comment has been lost/ignored.
fallback to ErrorComponent?
I'm not sure if 'ErrorComponent' refers to a boundary, but boundaries do not catch on the server-side. If it was a client-side only solution this report wouldn't exist.
be able to "try" file first (like Component.load();)
My opening comment touches on this scenario;
I attempted to hack around this by running the load method on the returned Loadable before returning the
from the switcher:
try {
Component.load();
} catch (error) {
return null;
}
This hack gets shut of the original error(s), but results in a server/client mismatch warning;
Warning: Expected server HTML to contain a matching <main> in <div>
I liked this approach; it allowed me to dynamically check a component existed in the codebase without maintaining an array of component IDs, however the server/client mismatch could not be ignored.
I am no longer engineering the application which prompted me to open this ticket, but others seem to be having similar issues. I can only really comment on what I wanted at the time, and that was the ability to have a component switch which loads a component using an CMS-generated, API-provided key(id), for example;
const someComponent = loadable(() => import(../presentation/${id})
If the API provided key is used to load a component from a directory which does not exist, then it is caught on the server and we simply return null.
It wasn't a hardship for me to maintain an array of known components, e.g. ['Hero', 'Statement']- this solution allowed me to check that the API provided key matches-up to an existing component in the application, and thus prevent any of the reported issues.
I didn't have the time to fork and figure out a solution back when I reported the issue, and I don't see me using loadable-components on the server any time soon. I will close this again, and let others report their specific issue.
Thanks again for the great work on Loadable Components, it is really appreciated.