Почему не работает передача children [РЕШЕНО]
const path = require ( 'path' );
const HTMLWebpackPlugin = require ( 'html-webpack-plugin' );
const { CleanWebpackPlugin } = require ( 'clean-webpack-plugin' );
// const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require ( 'mini-css-extract-plugin' );
const OptimizeCssAssetsPlugin = require ( 'optimize-css-assets-webpack-plugin' );
const TerserWebpackPlugin = require ( 'terser-webpack-plugin' );
const { BundleAnalyzerPlugin } = require ( 'webpack-bundle-analyzer' );
const isDev = process.env.NODE_ENV === 'development';
const isProd = !isDev;
const optimization = () => {
const config = {
splitChunks: {
chunks: 'all'
}
};
if ( isProd ) {
config.minimizer = [
new OptimizeCssAssetsPlugin (),
new TerserWebpackPlugin ()
];
}
return config;
};
const filename = ext => isDev ? `[name].${ ext }` : `[name].[hash].${ ext }`;
const cssLoaders = ( extra ) => {
const loaders = [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: isDev,
reloadAll: true
}
}, 'css-loader'
];
if ( extra ) {
loaders.push ( extra );
}
return loaders;
};
const babelOptions = preset => {
const opts = {
presets: [
'@babel/preset-env'
],
plugins: [
'@babel/plugin-proposal-class-properties'
]
};
if ( preset ) {
opts.presets.push ( preset );
}
return opts;
};
const plugins = () => {
const base = [
new HTMLWebpackPlugin ( {
template: './public/index.html',
minify: {
collapseWhitespace: isProd
}
} ),
new CleanWebpackPlugin (),
new MiniCssExtractPlugin ( {
filename: filename ( '.css' )
} )
// new CopyWebpackPlugin ([
// {
// from:'',
// to: ''
// }
// ])
];
if ( isProd ) {
base.push ( new BundleAnalyzerPlugin () );
}
return base;
};
module.exports = {
context: path.resolve ( __dirname, 'src' ),
mode: 'development',
entry: [ '@babel/polyfill', './index.jsx' ],
output: {
path: path.resolve ( __dirname, 'dist' ),
filename: filename ( '.js' )
},
resolve: {
extensions: [ '.js', '.jsx', '.json' ],
alias: {
'@src': path.resolve ( __dirname, 'src' ),
'@components': path.resolve ( __dirname, 'src/components' ),
'@pages': path.resolve ( __dirname, 'src/pages' ),
'@assets': path.resolve ( __dirname, 'src/assets' ),
'@media': path.resolve(__dirname, 'src/utils/media'),
'@utils': path.resolve ( __dirname, 'src/utils' ),
'@commonStyles' : path.resolve(__dirname, 'src/styles/commonStyles'),
'@swiper' : path.resolve(__dirname, 'src')
}
},
optimization: optimization (),
devtool: isDev ? 'inline-source-map' : 'source-map',
plugins: plugins (),
module: {
rules: [
{
test: /\.css$/,
use: cssLoaders ()
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
},
},
],
},
{
test: /\.(ttf|woff|woff2|eot)$/,
use: [ 'file-loader' ]
},
{
test: /\.svg$/,
loader: 'svg-inline-loader'
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: {
loader: 'babel-loader',
options: babelOptions ()
}
},
{
test: /\.jsx$/,
exclude: /node_modules/,
loader: {
loader: 'babel-loader',
options: babelOptions ( '@babel/preset-react' )
}
}
]
},
devServer: {
contentBase: 'dist/',
hot: true,
inline: false,
proxy: [
{
context: [ '/api' ],
target: 'http://localhost:8000',
pathRewrite: {
'^/api/': '/',
},
},
],
}
};
Если без div { ...children } то работает. Webpack собирал сам. Проблема в сборке?
import React from 'react';
import SwiperId from '../../core/swiper';
const SliderSmall = () => {
return (
<SwiperId>
<h1>Hello</h1>
</SwiperId>
);
};
export default SliderSmall;
import React, { memo } from 'react';
const SwiperId = ( { children, params } ) => {
return (
<div>
{ children }
</div>
);
};
export default SwiperId;
Ответы (1 шт):
Приведенный код - рабочий, ошибок нет. Если поместить его в сниппет - отрендерится заветная надпись Hello! в тэге h1, который в свою очередь будет обернут div-ом. Рабочий фрагмент кода в сниппете прилагаю:
const SliderSmall = () => {
return (
<SwiperId>
<h1>Hello!</h1>
</SwiperId>
);
};
const SwiperId = ( { children, params } ) => {
return (
<div>
{ children }
</div>
);
};
ReactDOM.render(
<SliderSmall />,
document.getElementById('app')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<!-- The content rendered into this tag should match the content below. -->
<div id="app"></div>
Некоторые компоненты не знают своих потомков заранее. Это особенно характерно для таких компонентов, которые представляют из себя как бы «коробку», в которую можно что-то положить.
Для таких компонентов рекомендуется использовать специальный проп children, который передаст дочерние элементы сразу на вывод:
const SwiperId = ( { children } ) => {
return (
<div>
{ children }
</div>
);
};
Это позволит передать компоненту произвольные дочерние элементы, вложив их в JSX:
const SliderSmall = () => {
return (
<SwiperId>
<h1>Hello</h1>
</SwiperId>
);
};
Всё, что находится внутри JSX-тега <SwiperId>, передаётся в компонент SwiperId через проп children. Поскольку SwiperId рендерит {props.children} внутри <div>, все переданные элементы (в данном случае один тэг h1) отображаются в конечном выводе.
Ссылка на источник: ReactJS Композиция против наследования
P.S.: чтобы отрендерить проп children, достаточно просто написать { children } в JSX разметке, как показано в примере выше. Не нужно писать вот так: { ...children }, используя деструктурирующее присваивание.
В дополнение, полезные ссылки по babel-loader (также удостоверьтесь, что код компонент написан в файлах с расширением .jsx, вероятнее всего проблема в конфигурировании сборки webpack):
Ставим пару пакетов:
npm install babel-loader babel-preset-react
После этого конфигурируем webpack (module -> loaders):
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['react']
}
}
],
}
И не забываем про пресеты в .babelrc файле:
presets:['es2015','react']
Более подробную информацию можно посмотреть в прикрепленных ссылках или в туториалах на подобии: «How to set up React, webpack, and Babel»