Как загрузить React компонент динамически?

211
17 марта 2018, 19:39

Помогите разобраться с проблемой, как загрузить React компонент динамически. Я на ходил статьи по этому поводу, но не могу добиться рабочего результата.

Ошибка: Critical dependency: the request of a dependency is an expression

Вот что имеется

package.json

{
  "name": "react-playground.loc",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^16.2.0",
    "react-dom": "^16.2.0",
    "react-loadable": "^5.3.1",
    "react-redux": "^5.0.6",
    "react-router": "^4.2.0",
    "react-router-dom": "^4.2.2",
    "redux": "^3.7.2",
    "redux-thunk": "^2.2.0"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-plugin-dynamic-import-webpack": "^1.0.2",
    "babel-plugin-transform-object-rest-spread": "^6.26.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "webpack": "^3.10.0"
  }
}

webpack.config.js

const webpack = require('webpack'),
  path = require('path'),
  devAppDir = path.resolve(__dirname, './app/dev/js'),
  distAppDir = path.resolve(__dirname, './app/dist/js'),
  isDevelopment = !process.env.NODE_ENV || process.env.NODE_ENV === 'development';
var config = {
  entry: {
    'app': path.resolve(devAppDir, 'app.jsx')
  },
  output: {
    path: distAppDir,
    publicPath: path.resolve(__dirname, './app/dist/'),
    filename: '[name].js',
    chunkFilename: '[name].[chunkhash].js'
  },
  resolve: {
    extensions: ['*', '.js', '.jsx'],
    modules: ['node_modules'],
    alias: {
    }
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
        options: {
          presets: ['env', 'react'],
          plugins: ['transform-object-rest-spread', 'dynamic-import-webpack']
        }
      }
    ]
  },
  plugins: [
    new webpack.NoEmitOnErrorsPlugin()
  ],
  devtool: isDevelopment ? 'cheap-inline-module-source-map' : false,
  watch: isDevelopment
};
module.exports = config;

app.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import Main from './components/Main';
const App = () => (
  <BrowserRouter>
    <Main />
  </BrowserRouter>
);
ReactDOM.render(
  <App />,
  document.getElementById('app')
);

Main.jsx

import React from 'react';
import General from './General';
const components = [
  {
    id: 1,
    name: 'General',
    component: General
  },
  {
    id: 2,
    name: 'Roles',
    component: null
  },
  {
    id: 3,
    name: 'Forms',
    component: null
  }
];
export default class Main extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      componentId: 1
    };
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick(e) {
    this.setState({
      componentId: +e.target.dataset.id
    });
  }
  render() {
    var { componentId } = this.state;
    function renderComponent () {
      for (let i = 0; i < 3; i += 1) {
        if (componentId === components[i].id) {
          if (components[i].component) {
            let Component = components[i].component;
            return <Component />;
          } else {
            import(`./${components[i].name}`).then(_ => {
              console.log(_);
            }).catch(error => 'An error occurred while loading the component');
            return <div>Loading...</div>;
          }
        }
      }
      return <div>Not found</div>;
    }
    return (
      <div>
        <div>
          <ul>
            <li><button type="button" data-id="1" onClick={this.handleClick}>component 1</button></li>
            <li><button type="button" data-id="2" onClick={this.handleClick}>component 2</button></li>
            <li><button type="button" data-id="3" onClick={this.handleClick}>component 3</button></li>
          </ul>
        </div>
        <div>
          {renderComponent()}
        </div>
      </div>
    );
  }
}
Answer 1

Вот это вот пробовали?

import Loadable from 'react-loadable';
const LoadableOtherComponent = Loadable({
  loader: () => import('./OtherComponent'),
  loading: () => <div>Loading...</div>,
});
const MyComponent = () => (
  <LoadableOtherComponent/>
);

Отсюда

READ ALSO
Обращение к имени переменной

Обращение к имени переменной

Добрый деньВопрос: пусть есть let foo = 123; и let bar = 'foo'; Как из bar обратиться к содержимому foo?

244
Нашёл задачку, как решить? [требует правки]

Нашёл задачку, как решить? [требует правки]

Нужно реализовать метод closestElement который принимает два параметра @param arrayToLook {arrayNumber} не пустой массив целых чисел от -10000 до 10000 @param valueToCheck {Number}...

297
Как создать блок дугой? (с картинкой - примером)

Как создать блок дугой? (с картинкой - примером)

Как создать блок дугой (внутрь блока) (потратил 5 часов на решение задачи и не нашел ответа)

202