某些上下文
问题
我仅在使用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'])]
});