简体   繁体   中英

How do you load React components asynchronously based on different server side states?

I want to be able to load React components asynchronously based on different user types. For example, as User A navigates around the app, their set of components are loaded via async. Then when User B uses the app they received a different set of components also loaded via async.

At the moment I'm using React Router and Redux. I also use Webpack to create component chunks which load async like this:

<Route
  path="/"
  getComponent={(location, callback) => {
    require.ensure([], (require) => {
      callback(null, require('./app/App.jsx').default);
    }, 'App');
  }}
>

But when I try to expand this to dynamically load the components it doesn't work. I've created an array of objects which contains all the components I want to load...

{
  components: [
    {
      id: 0,
      name: 'Dashboard',
      src: './dashboard/Dashboard.jsx',
      indexRoute: true,
      path: '/',
    },
    {
      id: 1,
      name: 'Quote',
      src: './quote/Quote.jsx',
      indexRoute: false,
      path: '/quote',
    },
  ],
}

I then use map to create routes for each one of these components...

const routes = components.map((component) => {

  if (component.indexRoute) {
    return (
      <IndexRoute
        getComponent={(location, callback) => {
          require.ensure([], (require) => {
            callback(null, require(component.src).default);
          }, component.name);
        }}
        key={component.id}
      />
    );
  }

  return (
    <Route
      path={component.path}
      getComponent={(location, callback) => {
        require.ensure([], (require) => {
          callback(null, require(component.src).default);
        }, component.name);
      }}
      key={component.id}
    />
  );
});

But when I insert my created routes into the main route...

<Route
  path="/"
  getComponent={(location, callback) => {
    require.ensure([], (require) => {
      callback(null, require('./app/App.jsx').default);
    }, 'App');
  }}
>
  {routes}
</Route>

I get the following error:

Uncaught TypeError: __webpack_require__(...).ensure is not a function

and warning:

require function is used in a way in which dependencies cannot be statically extracted

I presume this is because Webpack needs to know what chunks it has to compile at build time? Is this the problem and is there a way round this? Or even a better solution?

Thanks

For anyone who comes across this at a later stage, I managed to work around this by creating a object with all the async components my app could possibly load. Each components route definition has it's require.ensure function defined like such...

const asyncComponents = [
  {
    id: 0,
    name: 'Dashboard',
    require: (location, callback) => {
      require.ensure([], (require) => {
        callback(null, require('./dashboard/Dashboard.jsx').default);
      }, 'Dashboard');
    },
  },
];

export default asyncComponents;

Doing it this way will inevitably face scaling problems at some point as you have to maintain a separate list of all your components. It works for now though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM