Reputation: 10307
I'm trying to implement lazy-loading components with react-loadable. I've followed their guide but I can't get it to work.
I've got 3 loadable components
const LazyOne = Loadable({
loader: () => import(/* webpackChunkName: 'lazy-1' */"./components/LazyOne"),
loading: <h1>wait</h1>
});
const LazyTwo = Loadable({
loader: () => import(/* webpackChunkName: 'lazy-2' */"./components/LazyTwo"),
loading: <h1>wait</h1>
});
const LazyThree = Loadable({
loader: () => import(/* webpackChunkName: 'lazy-3' */"./components/LazyThree"),
loading: <h1>espera</h1>
});
At first the webpack build would break because it threw an unexpected input error on the import. So I added this to my .babelrc
"plugins": [
// all my other plugins...
"syntax-dynamic-import"
]
Now the build is successfull and if I use webpack-bundle-analyzer I see all lazy builds built correctly!
But when I access my page that is rendered like so:
render() {
return (
<ErrorBoundary>
<LazyOne {...this.props} />
</ErrorBoundary>
);
}
This throws:
Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
I see nothing mentioning this anywhere in react-loadables github or even code-splitting sections in webpack. What am I doing wrong?
EDIT
I've changed things up a bit and noticed it fails to load the lazy chunk.
my url is like this: localhost:3000/some/rest/1/edit
and the app is trying to fetch: localhost:3000/some/rest/1/lazy-1.bundle.js
Where should I specify the path?
Upvotes: 4
Views: 2994
Reputation: 7388
Took me hours to figure out but it turns out that just adding 'async' can break all hell out in React.. and you don't get any good feedback why.
const renderB2bApp = (store, callback) => {
ReactDOM.render(
<Provider store={store}>
<B2BApp store={store} />
</Provider>,
appElement,
callback,
);
};
const B2BApp = async (props) => { {/* <--- async here!! remove it */ }
// ...
// it doesn't matter if you don't use `await` even just adding the async destroys it
}
If you need to do async stuff then you need to render something immediately and then use hooks or state to update the component. So do not add async inside the ReactDom.render
subcomponent!
Upvotes: 0
Reputation: 10307
When I solved all problems about the bundles being loaded by the main app. The error changed!
So I narrowed it down:
Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
Means the main bundle is not loading the lazy bundles properly (and most probably failing at loading them). For example in my case the generated lazy bundles: lazy-1, lazy-2 and lazy-3 were being put on the wrong folder by webpack. I just had to fix that
After this fix there is still another change to be made since the error will change to this with the code I presented:
React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
But why you might ask? It's simple! The loading param does not take JSX but it takes a component type like this:
// WRONG! AND WILL THROW ERROR
const LazyOne = Loadable({
loader: () => import(/* webpackChunkName: 'lazy-1' */"./components/LazyOne"),
loading: <h1>wait</h1>
});
// RIGHT!
const LoadingComponent = () => (<h1>wait</h1>);
const LazyOne = Loadable({
loader: () => import(/* webpackChunkName: 'lazy-1' */"./components/LazyOne"),
loading: LoadingComponent
});
And just like that my problems were solved (since my components were not throwing any errors)
Upvotes: 1