React & React-router 异步组件安装多次(componentDidMount 调用多次)

Lou*_*is 5 javascript asynchronous reactjs react-router react-router-v4

我正在使用 Webpack 3.7.1 和 React 15.6.1,并且动态加载不同的组件。

我做了什么

  • 使用AsyncComponentimport()异步生成块并加载组件
  • 正确配置webpack.config 文件以便创建块(代码分割)

问题

  • 组件被重新渲染(安装)多次。如果我在任何组件的任何 componentDidMount() 中控制台记录某些内容,它会在我的控制台中出现 2 次或更多次!以前没有这样做:当我只是正常导入组件时......

我更改为异步组件之前的行为

  • 组件已正确加载并且仅安装一次......

我的 Webpack.config 文件

module.exports = {
  devServer: {
    historyApiFallback: true
  },
  entry: {
    app:"./src/index.js",
    vendor: [
      "axios",
      "react",
      "react-dom",
      "react-redux",
      "react-router",
      "react-router-dom",
      "redux"
    ]
  },
  output: {
    path: __dirname + '/public/views',
    filename: '[name].js',
    chunkFilename: '[chunkhash].chunk.js',
    publicPath: "/views/"
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: "babel-loader",
        exclude: [/node_modules/, /pdfmake.js$/]
      },
      {
        test: /\.json$/,
        loader: "json-loader"
      }
    ]
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor",
      minChunks: Infinity
    }),
    new webpack.NamedModulesPlugin(),
    new HtmlWebpackPlugin({
      filename:  __dirname + "/views/index.ejs",
      template: __dirname + "/views/template.ejs",
      inject: 'body',
      chunks: ['vendor', 'app'],
      chunksSortMode: 'manual'
    }),
    new PreloadWebpackPlugin({
      rel: "preload",
      include: ["vendor", "app"]
    }),
    new webpack.optimize.OccurrenceOrderPlugin(),
  ]
};
Run Code Online (Sandbox Code Playgroud)

我的 AppContainer.js 文件

 /**
 * General container of the website
 */
class AppContainer extends Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    console.log("MOUNTING APP CONTAINER")
  }



  render() {
    const HomePage = AsyncComponent(() =>
      import(/* webpackChunkName:"HomePage"  */ "../components/homepage/homepage")
    );


    return (
      <div>
        <Switch>
          <Route exact path="/" component={HomePage} />
        </Switch>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

组件本身更复杂(执行 API 调用并且有更多路由),但出于堆栈目的而在此处进行了简化;)

我的 AsyncComponent.js 文件

import React, { Component } from "react";

export default function asyncComponent(importComponent) {
    class AsyncComponent extends Component {
      constructor(props) {
        super(props);

        this.state = {
          component: null
        };
      }

      async componentDidMount() {
        const { default: component } = await importComponent();

        this.setState({
          component: component
        });
      }

      render() {
        const C = this.state.component;

        return C ? <C {...this.props} /> : null;
      }
    }

    return AsyncComponent;
  }
Run Code Online (Sandbox Code Playgroud)

我猜这个问题来自 AsyncComponents/chunks 生成,因为在使用 AsyncCOMponents 并将我的代码分割成块之前我没有遇到这个问题......但我不知道它到底来自哪里

非常感谢您的帮助

Ros*_*len 3

尝试将 的声明移至HomePage之外renderrender可以被调用任意多次,并且返回的每个组件在 React 中看起来都会有所不同。

/**
* General container of the website
*/
const HomePage = AsyncComponent(() =>
  import(/* webpackChunkName:"HomePage"  */ "../components/homepage/homepage")
);

class AppContainer extends Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    console.log("MOUNTING APP CONTAINER")
  }

  render() {
    return (
      <div>
        <Switch>
          <Route exact path="/" component={HomePage} />
        </Switch>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

一般来说,我建议不要在 React 组件内进行异步工作。您的渲染层应该是同步的,以便您的 UI 具有可预测的生命周期。