Некоторый контекст
- У меня есть HOC с названием withCtx.Он предоставляет контекст для базового Comps
- У меня есть рабочее решение в конце этого поста, но это слишком много дополнительного кода только для HOC.
Проблема
Я испытываю эту проблему только в моей библиотеке npm, созданной с помощью Webpack 4. В приложении отлично работает точно такой же экспорт HOC.
Необработанный отказ (TypeError): объект (...) не является функцией
Мои догадки:
Webpackкажется, что функции передаются в HOC, в то время как приложение передает объекты (компоненты React).
Так что я предполагаю, что в 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;
};
Это НЕ работает с веб-пакетом
export default withCtx({
nextRouter: PropTypes.object,
currentRoute: PropTypes.object,
})(Toolbar);
Это НЕ работает с веб-пакетом(почему не выше?)
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'])]
});