React: kompozycja
Opublikowano sob 29 sierpnia 2020 w reactjs • 2 min read
props.children
pozwala nam na tworzenie komponentów otwartych na uzupełniania nowym kodem, wystarczy wykorzystać {props.children} w ramach komponentu aby wskazać, w którym miejscu istnieje możliwość uzupełnienia/wstawienia kodu
Komponent otwarty na ew. rozszerzenia o nową treść
function TestComposition(props) {
let {children} = props;
return (<div>
<h1>Test Kompozycji</h1>
{children}
<h2>Konice testu kompozycji</h2>
</div>
)
}
function App() {
return (
<TestComposition>
<h3>Element będący zagnieżdżoną treścią</h3>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Culpa, eum!</p>
</TestComposition>
)
}
ReactDOM.render(
<App/>,
document.getElementById("app")
);
W efekcie tego powstanie
<div>
<h1>Test Kompozycji</h1>
<h3>Element będący zagnieżdżoną treścią</h3>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Culpa, eum!</p>
<h2>Konice testu kompozycji</h2>
</div>
props.children
może wyrenderować inny komponent przyjęty w propsie.
Powyższy przykład, może wyglądać również w poniższy sposób
function TestComposition(props) {
let {children} = props;
return (<div>
<h1>Test Kompozycji</h1>
{children}
<h2>Konice testu kompozycji</h2>
</div>
)
}
function ChildComponent() {
return (
<h3>Element będący zagnieżdżonym dzieckiem</h3>
)
}
function App() {
return (
<TestComposition children={<ChildComponent/>}/>
)
}
ReactDOM.render(
<App/>,
document.getElementById("app")
);
A co jeśli zależy nam na tym aby dany komponent był w stanie przyjąć wiele innych komponentów lub inaczej rzecz ujmując mieć możliwość wypełnienia wielu luk. W tym przypadku należy zastosować odrębne nazewnictwo dla każdego fragmentu/luki, który ma być uzupełniony a następnie przekazać go w odpowiedni sposób w props.
function TestComposition(props) {
let {child1, child2} = props;
return (<div>
<h1>Test Kompozycji</h1>
{child1}
{child2}
<h2>Konice testu kompozycji</h2>
</div>
)
}
function ChildComponent({text}) {
return (
<h3>Element będący zagnieżdżonym {text}</h3>
)
}
function App() {
return (
<TestComposition child1={<ChildComponent text='dzieckiem-1'/>} child2={<ChildComponent text='dzieckiem-2'/>}/>
)
}
ReactDOM.render(
<App/>,
document.getElementById("app")
);
W efekcie tego powstanie
<div>
<h1>Test Kompozycji</h1>
<h3>Element będący zagnieżdżonym dzieckiem-1</h3>
<h3>Element będący zagnieżdżonym dzieckiem-2</h3>
<h2>Konice testu kompozycji</h2>
</div>
Ominięcie prop-drilling wykorzystując kompozycję oraz props.children
Przekazywanie propsów do elementu liściowego z pominięciem pośredników (lub tzw. prop-drilling -> gdzie dane w postaci propsów są przekazywane przez komponenty które, z nich faktycznie nie korzystają) może odbyć się poprzez wykorzystanie props.children. Wymaga to jednak otwartości poprzednich komponentów na możliwość (włączenia) wywołania w nich dzeci.
function TestComposition({children,i}) {
return (
<div className='testComposition' key={i}>
<h2>Beginning o parent component</h2>
{children}
<h2>End of parent component</h2>
<p>--------------------</p>
</div>
)
}
function ChildComponent({children}) {
return (
<div className='childComponent'>
<h3>Beginning o child component</h3>
{children}
<h3>End of child component</h3>
</div>
)
}
function GrandChild({text}) {
return (
<h3 className='grandChild'>{text}</h3>
)
}
function App({grandChildren}) {
return (
grandChildren.map((elem,i)=>
<TestComposition id={i}>
<ChildComponent>
<GrandChild text={elem}/>
</ChildComponent>
</TestComposition>
)
)
}
ReactDOM.render(
<App grandChildren = {['Grand Child 1', 'Grand Child 2', 'Grand Child 3']}/>,
document.getElementById("app")
);
W wyniku tego powstanie:
<div id="app">
<div id="app"><div class="testComposition">
<h2>Beginning o parent component</h2>
<div class="childComponent">
<h3>Beginning o child component</h3>
<h3 class="grandChild">Grand Child 1</h3>
<h3>End of child component</h3>
</div>
<h2>End of parent component</h2>
<p>--------------------</p>
</div>
<div class="testComposition">
<h2>Beginning o parent component</h2>
<div class="childComponent">
<h3>Beginning o child component</h3>
<h3 class="grandChild">Grand Child 2</h3>
<h3>End of child component</h3>
</div>
<h2>End of parent component</h2>
<p>--------------------</p>
</div>
<div class="testComposition">
<h2>Beginning o parent component</h2>
<div class="childComponent">
<h3>Beginning o child component</h3>
<h3 class="grandChild">Grand Child 3</h3>
<h3>End of child component</h3>
</div>
<h2>End of parent component</h2>
<p>--------------------</p>
</div>
</div>
Źródła:
Kompozycja vs dziedziczenie - Wzorce w React #3
Thinking in React: Component Composition
How To Avoid Prop Drilling in React Using Component Composition