Webpack中的HOC引发未处理的拒绝(TypeError):对象(...)不是函数

时间:2018-10-22 17:20:41

标签: javascript reactjs webpack

某些上下文

  1. 我有一个名为withCtx的HOC。它为基础组件提供了上下文
  2. 我在本文的结尾处有一个可行的解决方案,但这仅仅是HOC的过多代码。

问题

我仅在使用Webpack 4构建的npm库中遇到此问题。在应用程序中,完全相同的HOC导出效果很好。

  

未处理的拒绝(TypeError):Object(...)不是函数

我的猜测:

Webpack似乎将函数传递给HOC,而应用似乎传递了对象(反应组件)。

所以我想我在Webpack中缺少一个插件,或者我应该在HOC中添加条件语句,以便以正确的方式呈现其传递的组件。

这是HOC:

export const withCtx = contextTypes => Component => {
    /* The context is passed as props. This way the component is
   completely decoupled from the context API.
  */

    console.log('typeof ----------', Component);
    const ContextConsumer = (props, context) => <Component {...props} {...context} />;
    ContextConsumer.contextTypes = contextTypes;

    return ContextConsumer;
};

这不适用于webpack

export default withCtx({
    nextRouter: PropTypes.object,
    currentRoute: PropTypes.object,
})(Toolbar);

此功能可用于webpack(为什么不使用上面的功能?)

const Toolbar_Extended = props => {
    const TB = withCtx({
        nextRouter: PropTypes.object,
        currentRoute: PropTypes.object,
    })(Toolbar);
    return <TB {...props} />;
};
export default Toolbar_Extended;

这确实也起作用...

export const withCtx = contextTypes => Component => {
    /* The context is passed as props. This way the component is
   completely decoupled from the context API.
  */

    let ContextConsumer = (props, context) => <Component {...props} {...context} />;

    ContextConsumer.contextTypes = contextTypes;

    if (typeof Component == 'function') {
        return props => {
            return <ContextConsumer {...props} />;
        };
    }

    return ContextConsumer;
};

// then
export default props => withCtx({
        nextRouter: PropTypes.object,
        currentRoute: PropTypes.object,
    })(Toolbar)(props);

有人可以启发我吗?

我为什么要传递PropTypes?因为我这样处理上下文。但是无论如何,我都会收到错误消息。有或没有PropTypes ...

// Providing HOCs you can easily solve the code fragility problem of the React context. You’ll only need to update one place if the API changes. Let’s illustrate a possible implementation:

const provideContext = 
  (childContextTypes, getChildContext) => (Component) => {
    class ContextProvider extends React.Component {
      static childContextTypes = childContextTypes;
      getChildContext = () => getChildContext(this.props);

      render() {
        return <Component {...this.props} />;
      }
    }
    return ContextProvider;
  };

const consumeContext = (contextTypes) => (Component) => {
  /* The context is passed as props. This way the component is
   completely decoupled from the context API.
  */ 
  const ContextConsumer = (props, context) =>
    <Component {...props} {...context} />;
  ContextConsumer.contextTypes = contextTypes;
  return ContextConsumer;
};

// Then, you can use it as follows:

const Child = ({color}) => (
  <div style={{backgroundColor: color}}>
    Hello context!!!
  </div>
);

const ChildwithContext = consumeContext({
  color: React.PropTypes.string
})(Child);

const MiddleComponent = () => <ChildwithContext />;

const App = provideContext(
  {color: React.PropTypes.string},
  () => ({color: 'red'})
)(MiddleComponent);

这是我的webpack配置

常用配置:

const path = require('path');
const webpack = require('webpack');
const fs = require('fs');

// Is the current build a development build
const IS_DEV = process.env.NODE_ENV === 'development';
var root = __dirname;

// Directories
const dirNode = 'node_modules';
const dirApp = path.join(root, 'src');
const dirAssets = path.join(root, 'assets');

// Optimizations
const dependencies = Object.keys(require('./package.json').dependencies);

const nodeExternals = require('webpack-node-externals');

let config = {
    entry: {
        index: path.resolve(root, './src/index')
    },
    externals: [nodeExternals()],
    resolve: {
        extensions: ['.tsx', '.ts', '.js', '.jsx'],
        modules: [dirNode, dirApp, dirAssets],
        alias: {
            // irrelevant to this question
        }
    },
    target: 'node',
    optimization: {
        splitChunks: {
            chunks: 'async',
            minSize: 30000,
            maxSize: 0,
            minChunks: 1,
            maxAsyncRequests: 5,
            maxInitialRequests: 3,
            automaticNameDelimiter: '~',
            name: true,
            cacheGroups: {
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    priority: -10
                },
                default: {
                    minChunks: 2,
                    priority: -20,
                    reuseExistingChunk: true
                }
            }
        }
    },
    plugins: [
        // irrelevant to this question
    ],
    module: {
        rules: [
            // BABEL
            {
                test: /\.(js|jsx)$/,
                loader: 'babel-loader',
                exclude: /(node_modules)/,
                options: {
                    compact: true
                }
            },
            // and much more ...
        ]
    }
};

module.exports = config;

构建配置

const path = require('path');
const merge = require('webpack-merge');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpackConfig = require('./webpack.config.common');

module.exports = merge(webpackConfig, {
    devtool: 'source-map',
    output: {
        path: path.join(__dirname, './dist'),
        filename: 'index.js',

        libraryTarget: 'umd',
        umdNamedDefine: true,
        globalObject: 'this'
    },

    plugins: [new CleanWebpackPlugin(['dist'])]
});

0 个答案:

没有答案