Kompozíció és öröklődés
A React egy erőteljes kompozíciós modellel rendelkezik, és ajánljuk is a kompozíció használatát öröklődés helyett, a kód komponensek közötti újrafelhasználásának érdekében.
Ebben a fejezetben szemügyre veszünk néhány problémát ahol a még új React fejlesztők előszeretettel nyúlnak az örökléshez, és megmutatjuk hogyan lehet ezeket kompozícióval megoldani.
Elszigetelés
Néhány komponens nem ismeri a saját gyermekeit idő előtt. Ez igen gyakori olyan komponensek esetében mint a Sidebar
vagy a Dialog
, amik általános “dobozokat” képviselnek.
Azt ajánljuk, hogy ilyen komponensek esetében használd a speciális children
(gyermekek) prop-ot, hogy ezen komponensek kimenetébe közvetlenül le tudd küldeni a gyermek elemeket:
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children} </div>
);
}
Ez lehetővé teszi más komponenseknek tetszőleges számú gyermeket küldeni ezen komponenseknek, JSX-be való beágyazással:
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title"> Üdvözöljük </h1> <p className="Dialog-message"> Köszönjük, hogy meglátogatta űrhajónkat! </p> </FancyBorder>
);
}
Bármi ami a <FancyBorder>
JSX címkéi között van, children
prop-ként lesz leküldve a FancyBorder
komponensnek. Mivel a FancyBorder
egy <div>
-ben rendereli a {props.children}
-t, a legküldött elem meg fog jelenni a végső kimenetben.
Ha nem is gyakran, de néha szükséged lehet több “lyukra” is egy komponensben. Ilyen esetekben előrukkolhatsz egy saját megoldással a children
helyett:
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left} </div>
<div className="SplitPane-right">
{props.right} </div>
</div>
);
}
function App() {
return (
<SplitPane
left={
<Contacts /> }
right={
<Chat /> } />
);
}
A React elemek mint a <Contacts />
és a <Chat />
csak objektumok, szóval le tudod őket küldeni prop-ként, mint bármilyen más adatot. Ez a megközelítés ismerős lehet számodra más könyvtárakból “slot” (rés)-ként, de a React esetében nincs semmilyen megkötés, hogy mit küldesz le prop-ként.
Specializáció
Némely esetben úgy tekintünk komponensekre, mint más komponensek “speciális esetére”. Például mondhatjuk, hogy a WelcomeDialog
a Dialog
egy speciális esete.
A React-ben ez is kompozícióval érhető el, ahol egy “specifikusabb” komponens egy “általánosabb” komponenst renderel, amiket prop-okkal konfigurál:
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title} </h1>
<p className="Dialog-message">
{props.message} </p>
</FancyBorder>
);
}
function WelcomeDialog() {
return (
<Dialog title="Üdvözöljük" message="Köszönjük, hogy meglátogatta űrhajónkat!" /> );
}
A kompozíció ugyanolyan jól működik osztályként definiált komponensek esetében is:
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
{props.children} </FancyBorder>
);
}
class SignUpDialog extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSignUp = this.handleSignUp.bind(this);
this.state = {login: ''};
}
render() {
return (
<Dialog title="Mars Kutató Program"
message="Hogy hívjunk?">
<input value={this.state.login} onChange={this.handleChange} /> <button onClick={this.handleSignUp}> Írj fel engem! </button> </Dialog>
);
}
handleChange(e) {
this.setState({login: e.target.value});
}
handleSignUp() {
alert(`Üdv a fedélzeten, ${this.state.login}!`);
}
}
És mi a helyzet az örökléssel?
A Facebook-nál a React-et több ezernyi komponensben használjuk, és egyetlen esetet sem találtunk, ahol komponens öröklő hierarchia készítését ajánlanánk.
A prop-ok és a kompozíció minden szabadságot megadnak ahhoz, hogy egy biztonságos és határozott módon tudd kifejezni a komponensed kinézetét és viselkedését. Emlékezz, hogy a komponensek tetszőleges számú prop-ot fogadhatnak, beleértve primitív értékeket, React elemeket és függvényeket.
Ha újra szeretnél használni egy nem felhasználói felület specifikus tulajdonságot komponensek között, akkor ajánljuk hogy azt szeparáld ki egy saját JavaScript modulba. A komponensek ezt importálni és használni tudják bármi féle öröklő kiterjesztés nélkül, legyen az függvény, objektum, vagy egy osztály.