Loadable.Capture not reporting any modules
Asked Answered
K

2

11

This is essentially all my code. I am running Hapi and trying to use react-loadable to server render my React application.

I have added a lot of the missing pieces to the code here.

const location = req.url.pathname
const context = {}
const modules = []

const Router = () => (
  <Switch>
    <Route exact path="/" component={Home} />
    <Route path="/login" component={Login} />
    <Route path="/me" component={Profile} />
    <Route component={NotFound} />
  </Switch>
)

const App = () => (
  <StaticRouter location={location} context={context}>
    <main>
      <Header />
      <Router />
      <Footer />
    </main>
  </StaticRouter>
)

const preloadables = [ Home, Login, Profile, NotFound ]
await Promise.all(preloadables.map(preloadable => preloadable.preload()))

const html = ReactDOMServer.renderToString(
  <Loadable.Capture report={moduleName => modules.push(moduleName)}>
    <App/>
  </Loadable.Capture>
)

// render html

It renders the page correctly, as I see my React app rendered in my browser. Although I do not see any contents of the "Router" unless I disable cache on the server. So the first request renders no router, and the following ones do.

On the server, console.log('modules:', modules) returns modules: [] always. Regardless of cache. So even when I disable cache, refresh the page twice to see the router working, modules is still empty.

npm run start:server
Warning: setState(...): Can only update a mounting component. This usually means you called setState() outside componentWillMount() on the server. This is a no-op.

Please check the code for the LoadableComponent component.
modules []
modules []
modules []
modules []
modules []

I am a bit lost since it should be working.. everything looks okay.

Kassiekassity answered 7/7, 2018 at 15:36 Comment(3)
I'm in a similar boat even with preloadAll(). I'm going crazy as my code looks identical to every example I can find but modules always comes back empty even though the server rendering works perfectly.Schuyler
I will post my working code as answer this weekend @SchuylerKassiekassity
any news here? I have the same problem... (and preloadAll() does not help)Styracaceous
I
4

Today after somehow long struggle, solved it finally.

Before you get modules, you have to write your loadable component correctly. Official docs declare here

Loadable({
  loader: () => import('./Bar'),
  modules: ['./Bar'],
  webpack: () => [require.resolveWeak('./Bar')],
});

Or you can use babel plugin provided. However, as the situation for me, i'm using ts-node and with no luck of use that babel plugin, so only option 1 is available.

Write here for someone would encounter similar problem.

(p.s. lodable-component depends on babel plugin too)

Ieshaieso answered 1/3, 2019 at 8:21 Comment(2)
This should be the accepted answer. Thanks, you save my day!Patricio
@Patricio you're welcome, glad to help someone like you.Ieshaieso
K
2

Seems that even though you loaded the components, react-loadable is not aware of them.

If you used Loadable.preloadAll instead of loading components programmatically, it should solve your problem.

Your current approach will also get very verbose when number of routes increases, you will have to maintain the list of preloadables.

Kendrakendrah answered 11/10, 2018 at 11:37 Comment(1)
I have a similar issue, even match simpler since I'm not using any routing. I am using Loadable.preloadAll(), I've done some logs in the source and noticed all relevant modules are indeed loaded by it. The SSR app works properly on both client and server. The only problem is the modules array is empty as described in the opener's issue. Any idea what's going on?Krummhorn

© 2022 - 2024 — McMap. All rights reserved.