Webpack Import Code Splitting rendering <undefined>

Viewed 690

I am trying to do a component based code split. Webpack 3.

    loadDecisions = async () => {
    if (!this.TmplDecisions) {
      this.TmplDecisions = await import(
        /* webpackChunkName: "chunk-templates-decisions" */ 'src/components/decisions'
      );
    }

    return this.TmplDecisions;
  }

  renderDecisions () {
    if (this.TmplDecisions && this.TmplDecisions.default) {
      return <this.TmplDecisions.default 
        {...this.props} 
        logOpenEvent={this.logTagOpenEvent}
      />;
    } else return null;
  };

The component shows up fine in Dev tools debugger, but it gets rendered as <undefined></undefined>

Can someone help?

3 Answers

Your pathname should start with ./ for dynamic imports of relative modules to work.

eg: /* webpackChunkName: "chunk-templates-decisions" */ './src/components/decisions.js' (note ./ here, otherwise webpack treats src as npm module).

From the React docs :

You cannot use a general expression as the React element type. If you do want to use a general expression to indicate the type of the element, just assign it to a capitalized variable first.

So try to assign the type to a capitalized variable first.

Also add TmplDecisions to the state (or use a flag eg. tmplDecisionsLoaded ), so that React re-render after TmplDecisions is loaded.

  loadDecisions = async () => {
    if (!this.state.TmplDecisions) {
      const TmplDecisions = await import(
        /* webpackChunkName: "chunk-templates-decisions" */ 'src/components/decisions'
      );

      this.setState({ TmplDecisions });
      return TmplDecisions;
    } else {
      return this.state.TmplDecisions;
    } 
  }

  renderDecisions () {
    if (this.state.TmplDecisions && this.state.TmplDecisions.default) {
      const MyComponent = this.state.TmplDecisions.default;
      return <MyComponent
        {...this.props} 
        logOpenEvent={this.logTagOpenEvent}
      />;
    } else return null;
  };

Are you sure you are not returning a promise at first place which later pass to JSX? That would give you undefined.

componentDidMount() {
  const TmplDecisions = this.TmplDecisions && this.TmplDecisions.default;
  if (TmplDecisions instanceof Promise) {
    TmplDecisions.then((RealTmplDecisions) => this.setState({ TmplDecisions: RealTmplDecisions}));
    return;
  }
  if (TmplDecisions instanceof Function) {
    this.setState({
      TmplDecisions
    });
    return;
  }
}

// On shouldComponentUpdate you need to check 
// if state.TmplDecisions !== undefined 
// among whatever else you are doing there

renderDecisions () {
  if (this.state.TmplDecisions) {
    return <this.state.TmplDecisions 
      {...this.props} 
      logOpenEvent={this.logTagOpenEvent}
    />;
  } else return null;
};
Related