Home Java React.lazy? But what if you don’t have a component?

React.lazy? But what if you don’t have a component?

by admin

This code splitting is, frankly, getting a little annoying. We all go around and around in circles, and that’s the main problem.
Code splitting started as Module level splitting, and ended up as Component level splitting.
And the problem here is solely in the head – React.lazy is good, but so is import didn’t go anywhere… So why code splitting only about components?
React.lazy, React-Loadable, Loadable-Components, Imported-component – there are plenty of libraries out there that wrap the loading of a module in some kind of sugar, solely to handle the loading of a component a bit more user-friendly and show it when ready. The minimum code for "async-loader" is.

const loadable = (loaderFunction)=>class AsyncComponent extends React.Component {state = { ResultComponent: null, error: false, };componentWillMount(){loaderFunction.then(result => this.setState({ ResultComponent: result.default || result}))// "es6" default export.catch(() => this.setState({ error: true });}render() {const { error, ResultComponent } = this.state;// Display loaded componentreturn ResultComponent? <ResultComponent {...this.props}/>: (error ? <ErrorComponent /> : <LoadingComponent /> )}}

Suspense and React.lazy are just another way of working with a state. Nothing more.

But what do you do if you don’t have a component?

There doesn’t seem to be a problem with that – import(‘someStuff’).then(‘go-on’) But then again there’s questions about how to place this correctly in React’s lifecycle, what to do if the promis is frozen after the component dies, and so on. And everyone has the same components in their head.
I did a mini poll – NO ONE else uses this, the oldest version of code splitting. Doesn’t know how to eat it in modern conditions. And all in all it’s bad.

That said, there is a solution, and again in 4 lines – renderProps

It’s very simple – even if the code splitting object is not a Component but a Module, it will still be a Component.

const loadableModule = (loaderFunction) =>class AsyncComponent extends React.Component {state = { ResultComponent: null, error: false, };componentWillMount() {loaderFunction.then(result => this.setState({ module: result.default || result})) // "es6" default export.catch(() => this.setState({ error: true });}render() {const { error, module } = this.state;return module// pass it as a render prop!? this.props.children(module)// pass it as a render prop!: (error ? <ErrorComponent /> : <LoadingComponent /> )}}

Same pattern, only turned towards loading the code and "providing" that code as renderProps.

Works out of the box :

  • loadable-components ( loadable.lib )
    import loadable from '@loadable/component'const Moment = loadable.lib(() => import('moment'))function FromNow({ date }) {return (<div><Moment fallback={date.toLocaleDateString()}>{({ default: moment }) => moment(date).fromNow()}</Moment></div>)}
  • react-lodable ( react-loadable-library )
    import {importedLibraryDefault} from 'react-loadable-library';const Moment = importedLibraryDefault( () => import('momentjs'));<Moment>{ (momentjs) => <span> {momentjs(date).format(FORMAT)}</span> }</Moment>
  • react-imported-component ( react-imported-library )
    // interface-compatible with react-loadable-library, plus Suspense support

It’s cheap, and it’s very surly. It allowed me to cut an extra 20%. But most importantly, it allowed me to set up code-splitting very declaratively, which will load only what I need, when I need it.
Now it’s your turn, %username%.

And who will rewrite this on hooks?

You may also like