Skip to content

Instantly share code, notes, and snippets.

@acdlite
Last active April 20, 2026 19:56
Show Gist options
  • Select an option

  • Save acdlite/a68433004f9d6b4cbc83b5cc3990c194 to your computer and use it in GitHub Desktop.

Select an option

Save acdlite/a68433004f9d6b4cbc83b5cc3990c194 to your computer and use it in GitHub Desktop.
Quick and dirty code splitting with React Router v4
// getComponent is a function that returns a promise for a component
// It will not be called until the first mount
function asyncComponent(getComponent) {
return class AsyncComponent extends React.Component {
static Component = null;
state = { Component: AsyncComponent.Component };
componentWillMount() {
if (!this.state.Component) {
getComponent().then(Component => {
AsyncComponent.Component = Component
this.setState({ Component })
})
}
}
render() {
const { Component } = this.state
if (Component) {
return <Component {...this.props} />
}
return null
}
}
}
const Foo = asyncComponent(() =>
System.import('./Foo').then(module => module.default)
)
const Bar = asyncComponent(() =>
System.import('./Bar').then(module => module.default)
)
const App = () =>
<BrowserRouter>
<Link to="/foo">Foo</Link>
<Link to="/bar">Bar</Link>
<Match pattern="/foo" component={Foo} />
<Match pattern="/bar" component={Bar} />
</BrowserRouter>
export default App
@BertieGo
Copy link
Copy Markdown

so dirty and so good, bro

@lynda0214
Copy link
Copy Markdown

Thank you for this brilliant code. I've been using this code very usefully.

Since System.import is deprecated, you have to use import.

Additionally, rather than doing module => module.default for every routes, you can remove some unnecessary codes by doing ({default: Component}) => ... in componentWillMount

Full Code:

function asyncComponent(getComponent) {
  return class AsyncComponent extends React.Component {
    static Component = null;
    state = { Component: AsyncComponent.Component };

    componentWillMount() {
      if (!this.state.Component) {
        getComponent().then(({default: Component}) => {
          AsyncComponent.Component = Component
          this.setState({ Component })
        })
      }
    }
    render() {
      const { Component } = this.state
      if (Component) {
        return <Component {...this.props} />
      }
      return null
    }
  }
}

const Foo = asyncComponent(() => import('./Foo'))
const Bar = asyncComponent(() => import('./Bar'))

Can't figure out why .default is needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment