Создать html-элемент, описание которого пришло из props, React
Есть компонент, который принимает проп elem, и а сам компонент должен обернуть в него свой вывод или во фрагмент, если проп не пришёл. Подобный механизм есть в Material-UI.
<Show elem="div" />
Должно вывывести:
<div>/* Some Stuff Here */</div>
а это:
<Show />
Вернёт фрагмент:
/* Some Stuff Here */
Ещё пример:
<Show elem="ol">
<li>One</li>
<li>Two</li>
</Show>
Вывод:
<ol>
<li>One</li>
<li>Two</li>
</ol>
Ответы (4 шт):
Если я вас правильно понял, то вы хотите из родительского компонента передать пропс для отрисовки чего либо, если он приходит. Вы можете просто воспользоваться проверкой пропса на этапе рендера:
const Parent = () => {
return (
<Show content="Something text" />
)
}
const Show = ({content}) => {
return content ? (<div>{content}</div>) : null
}
Альтернативный пример рендера на основе пропса:
const Show = (htmlElement) => {
const renderElement = (ChildComponent) => {
if (htmlElement === "ol") { // проверяем пришедший пропс
return <ol><ChildComponent /></ol> // возвращаем собранный компонент (если вариантов тегов будет 3 и больше, рекомендую использовать switch case)
}
}
return (
renderElement(<li />) // вызываем функцию renderElement и передаем ей дочерний компонент, который хотим положить внутрь пропсового элемента
)
}
Может быть я вас не правильно понял, однако предположу, что вы хотите создавать парные теги, обёртку вокруг контента:
import React, {Fragment} from 'react'
export function Show({ title = '/* Some Stuff Here */', tag }) {
return (
<>
{tag ?
React.createElement(tag, '', title) :
<Fragment>{title}</Fragment>}
</>
)
}
Получается, что вы можете полностью управлять внешними данными компонента, его тегами, пропсами, атрибутами и так далее:
React.createElement(component, props, ...children)
Переданный пропс можно использовать в jsx. При этом переменная должна начинаться с большой буквы, чтобы была разобрана как реакт компонент.
const {createRoot} = ReactDOM;
const {useState, Fragment} = React;
// Пример функционального компонента
const Wrapper = ({tag=Fragment, children})=>{
const Component = tag;
return <div>
Wrapper
<Component>{children}</Component>
</div>
}
// Пример классового компонента
class App extends React.Component {
render() {
return (
<React.Fragment>
<Wrapper tag="div">
Content 1
</Wrapper>
<Wrapper>
Content 2
</Wrapper>
</React.Fragment>
);
}
}
// Рендеринг
const rootContainer = document.querySelector('#react');
const root = createRoot(rootContainer);
root.render(<App />);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.production.min.js"></script>
Если кому-то пригодиться, сам я уже не помню, зачем мне это было нужно =):
const { createRoot } = ReactDOM;
const { createElement, Fragment } = React;
const Show = ({
el,
children,
...restProps
}) => {
if (!el) {
return <Fragment>{children}</Fragment>;
}
return createElement(el, restProps, children);
};
const HighlightComponent = ({
bg = "#000000",
fg = "#ffffff",
children,
}) => {
return <div style={{ color: fg, backgroundColor: bg }}>{children}</div>;
};
function App() {
return (
<Show el="div" className="App">
<Show el="h1">Hello World!</Show>
<Show el={HighlightComponent} bg="#aaaa00" fg="#000000">Test custom component</Show>
<Show>Test fragment</Show>
</Show>
);
}
const rootContainer = document.querySelector('#react');
const root = createRoot(rootContainer);
root.render(<App />);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.production.min.js"></script>