【问题标题】:React Router | Component not getting rendered反应路由器 |组件未呈现
【发布时间】:2017-12-26 17:48:15
【问题描述】:

我有一个包含多条路线的 SPA。我正在尝试使用 Webpack 2 和 React Router 4 基于路由实现代码拆分。我能够根据路由创建不同的块。例如,对于主页,我有 vendor.jsmain.jshome.js。所有三个文件都已成功加载,但我没有看到任何输出。 null 正在呈现。下面是使用的 React 开发者工具和代码的截图。我可以知道我在这里缺少什么吗?

应用组件/App.js

import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import NotificationContainer from '../containers/NotificationContainer';

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

    render() {
        return (
            <div>
                <NotificationContainer />
                <BrowserRouter>
                    <Switch>
                        <Route
                            exact
                            path="/"
                            getComponent={(nextState, callback) => {
                                // import('./homepage/index').then(module => callback(null, module.default));
                                require.ensure(
                                    [],
                                    require => {
                                        callback(null, require('./homepage/index').default);
                                    },
                                    'home'
                                );
                            }}
                        />
                        <Route
                            path="/login"
                            getComponent={(nextState, callback) => {
                                require.ensure(
                                    ['../containers/LoginContainer'],
                                    require => {
                                        require('../containers/LoginContainer');
                                    },
                                    'login'
                                );
                            }}
                        />
                        <Route
                            path="/forgetPassword"
                            getComponent={(nextState, callback) => {
                                require.ensure(
                                    ['../containers/ForgetPasswordContainer'],
                                    require => {
                                        require('../containers/ForgetPasswordContainer');
                                    },
                                    'forgetPassword'
                                );
                            }}
                        />
                        <Route
                            path="/generateNewPassword"
                            getComponent={(nextState, callback) => {
                                require.ensure(
                                    ['../containers/GenerateNewPasswordContainer'],
                                    require => {
                                        require('../containers/GenerateNewPasswordContainer');
                                    },
                                    'generateNewPassword'
                                );
                            }}
                        />
                        <Route
                            path="/signup"
                            getComponent={(nextState, callback) => {
                                require.ensure(
                                    ['../containers/SignupContainer'],
                                    require => {
                                        require('../containers/SignupContainer');
                                    },
                                    'signup'
                                );
                            }}
                        />
                        <Route
                            path="/contact"
                            getComponent={(nextState, callback) => {
                                require.ensure(
                                    ['./Contact'],
                                    require => {
                                        require('./Contact');
                                    },
                                    'contact'
                                );
                            }}
                        />
                        <Route
                            path="/tech"
                            getComponent={(nextState, callback) => {
                                require.ensure(
                                    ['./Tech'],
                                    require => {
                                        require('./Tech');
                                    },
                                    'tech'
                                );
                            }}
                        />
                        <Route
                            path="/error"
                            getComponent={(nextState, callback) => {
                                require.ensure(
                                    ['./Error'],
                                    require => {
                                        require('./Error');
                                    },
                                    'error'
                                );
                            }}
                        />
                        <Route
                            path="/user/dashboard"
                            getComponent={(nextState, callback) => {
                                require.ensure(
                                    ['../containers/DashBoardContainer'],
                                    require => {
                                        require('../containers/DashBoardContainer');
                                    },
                                    'dashboard'
                                );
                            }}
                        />
                        <Route
                            path="/movie/:movieId"
                            getComponent={(nextState, callback) => {
                                require.ensure(
                                    ['../containers/MovieContainer'],
                                    require => {
                                        require('../containers/MovieContainer');
                                    },
                                    'movieContainer'
                                );
                            }}
                        />
                        <Route
                            getComponent={(nextState, callback) => {
                                require.ensure(
                                    ['./Error'],
                                    require => {
                                        require('./Error');
                                    },
                                    'error'
                                );
                            }}
                        />
                    </Switch>
                </BrowserRouter>
            </div>
        );
    }
}

export default App;

Webpack 配置

const webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');
var BundleAnalyzer = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
    entry: './src/index.js',
    output: {
        path: __dirname + '/public/assets/js',
        filename: '[name].js',
        chunkFilename: '[name].js',
        publicPath: 'assets/js/'
    },
    plugins: [
        new BundleTracker({ filename: './webpack-stats.json' }),
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify('production')
            }
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            filename: '[name].js',
            minChunks: module => /node_modules/.test(module.resource)
        }),
        new webpack.LoaderOptionsPlugin({
            minimize: true,
            debug: false
        }),
        new webpack.optimize.UglifyJsPlugin({
            beautify: false,
            mangle: {
                screw_ie8: true,
                keep_fnames: true
            },
            compress: {
                screw_ie8: true,
                warnings: false
            },
            comments: false
        }),
        new BundleAnalyzer({ analyzerMode: 'static' })
    ],
    resolve: {
        modules: ['node_modules'],
        extensions: ['*', '.js', '.jsx']
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                options: {
                    plugins: [
                        [
                            'transform-semantic-ui-react-imports',
                            {
                                convertMemberImports: true,
                                addCssImports: false,
                                importMinifiedCssFiles: false,
                                addLessImports: false,
                                addDuplicateStyleImports: false
                            }
                        ]
                    ],
                    presets: [['es2015', { modules: false }], 'react', 'stage-2', 'node6']
                }
            }
        ]
    },
    node: {
        console: true,
        fs: 'empty',
        net: 'empty',
        tls: 'empty'
    }
};

首页组件 |主页/index.js

import React, { Component, PropTypes } from 'react';
import LayoutContainer from '../../containers/LayoutContainer';
import Hero from './Hero';
import About from './About';
import Working from './Working';

class Homepage extends Component {
    render() {
        return (
            <LayoutContainer scrollBound={600}>
                <div className="homepage-container">
                    <p>Here</p>
                    <Hero />
                    <About />
                    <Working />
                </div>
            </LayoutContainer>
        );
    }
}

export default Homepage;

【问题讨论】:

    标签: javascript reactjs webpack react-router code-splitting


    【解决方案1】:

    您并非在所有情况下都调用callback,因此组件不会返回到路由。例如,这个:

    <Route
      path="/login"
      getComponent={(nextState, callback) => {
        require.ensure(['../containers/LoginContainer'], require => {
          require('../containers/LoginContainer');
        }, 'login');
      }}
    />
    

    ...应该是:

    <Route
      path="/login"
      getComponent={(nextState, callback) => {
        require.ensure(['../containers/LoginContainer'], require => {
          callback(null, require('../containers/LoginContainer'));
        }, 'login');
      }}
    />
    

    【讨论】:

    • 我在 / 中调用回调,因为在主路由中仍然在渲染 null
    • 我正在尝试查找getComponent 的文档,但我没有看到它。也许这对react-router 来说根本不起作用了。
    【解决方案2】:

    除非react-router 的文档是个大骗子,否则路由不再有getComponent 方法。不过,滚动您自己的延迟加载组件并不算太糟糕。我必须为更奇特的路由器做一个,这种方法也适用于react-router@4。首先,创建一个简单的 HOC:

    export default function DeferredComponent(loadingFn) {
      return class DeferredComponentInstance extends React.Component {
        constructor() {
          super(...arguments);
          this.state = {
            InnerComponent: Spinner
          };
        }
    
        componentDidMount() {
          loadingFn((err, component) => {
            if (err) {
              throw err;  // Maybe render an error component instead?
            }
    
            this.setState({ InnerComponent: component });
          });
        }
    
        render() {
          const { InnerComponent } = this.state;
          return <InnerComponent { ...this.props }/>;
        }
      };
    }
    

    ...现在你可以像这样使用它了:

    <Route
      path="/login"
      component={DeferredComponent(cb => {
        require.ensure(['../containers/LoginContainer'], require => {
          cb(null, require('../containers/LoginContainer').default);
        });
      })}
    />
    

    【讨论】:

    • 是的,我猜getComponent 现在真的不支持了。虽然网络上到处都是它的教程。无论如何,我将它与我自己的一些变体一起使用以使其工作。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2019-02-21
    • 1970-01-01
    • 2018-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-22
    • 2019-03-04
    相关资源
    最近更新 更多