Σύνθεση έναντι Κληρονομικότητας
Το React έχει ένα ισχυρό μοντέλο σύνθεσης και σας συνιστούμε να χρησιμοποιήσετε τη σύνθεση αντί της κληρονομικότητας για να επαναχρησιμοποιήσετε τον κώδικα μεταξύ των components.
Σε αυτή την ενότητα θα εξετάσουμε μερικά προβλήματα στα οποία οι developers νέοι στο React συχνά φτάνουν για κληρονομίκότητα και θα δείξουμε πώς μπορούμε να τα λύσουμε με τη σύνθεση.
Περιορισμός
Μερικά components δεν γνωρίζουν από πριν τα children τους. Αυτό είναι ιδιαίτερα κοινό για τα components όπως Sidebar
ή Dialog
που αντιπροσωπεύουν γενικά “κουτιά”.
Συνιστούμε τα components αυτά να χρησιμοποιούν το ειδικό children
prop για να μεταφέρουν τα children elements απευθείας στην έξοδο τους:
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children} </div>
);
}
Αυτό επιτρέπει σε άλλα components να περάσουν αυθαίρετα children σε αυτά, εμφωλιάζοντας το JSX:
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title"> Welcome </h1> <p className="Dialog-message"> Thank you for visiting our spacecraft! </p> </FancyBorder>
);
}
Οτιδήποτε μέσα στο <FancyBorder>
JSX tag περνάει στο FancyBorder
component ως children
prop. Επειδή το FancyBorder
κάνει render το {props.children}
μέσα σε ένα <div>
, τα περασμένα elements εμφανίζονται στην τελική έξοδο.
Ενώ αυτό είναι λιγότερο κοινό, μερικές φορές μπορεί να χρειαστείτε πολλαπλές “τρύπες” σε ένα component. Σε τέτοιες περιπτώσεις μπορείτε να καταλήξετε στη δική σας σύμβαση αντί να χρησιμοποιήσετε το children
:
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 /> } />
);
}
Τα React elements όπως τα <Contacts/>
και <Chat />
είναι απλά objects, επομένως μπορείτε να τα περάσετε ως props όπως οποιαδήποτε άλλα δεδομένα. Αυτή η προσέγγιση μπορεί να σας υπενθυμίσει τα “slots” σε άλλες βιβλιοθήκες, αλλά δεν υπάρχουν περιορισμοί σε αυτό που μπορείτε να περάσετε ως props στο React.
Ειδίκευση
Μερικές φορές σκεφτόμαστε τα components ως “ειδικές περιπτώσεις” άλλων components. Για παράδειγμα, θα μπορούσαμε να πούμε ότι ένα WelcomeDialog
είναι μια ειδική περίπτωση του Dialog
.
Στο React, αυτό επιτυγχάνεται επίσης με τη σύνθεση, όπου ένα πιο “ειδικό” component κάνει render ένα πιο “γενικό” και το διαμορφώνει με props:
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="Welcome" message="Thank you for visiting our spacecraft!" /> );
}
Η σύνθεση λειτουργεί εξίσου καλά για τα components που ορίζονται ως κλάσεις:
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 Exploration Program"
message="How should we refer to you?">
<input value={this.state.login} onChange={this.handleChange} /> <button onClick={this.handleSignUp}> Sign Me Up! </button> </Dialog>
);
}
handleChange(e) {
this.setState({login: e.target.value});
}
handleSignUp() {
alert(`Welcome aboard, ${this.state.login}!`);
}
}
Τι Γίνεται Με Την Κληρονομικότητα?
Στο Facebook, χρησιμοποιούμε το React σε χιλιάδες components και δεν βρήκαμε καμιά περίπτωση χρήσης όπου θα συνιστούσαμε τη δημιουργία ιεραρχιών κληρονομικότητας component.
Τα props και η σύνθεση σας δίνουν όλη την ευελιξία που χρειάζεστε για να προσαρμόσετε την εμφάνιση και τη συμπεριφορά ενός component με έναν σαφή και ασφαλή τρόπο. Θυμηθείτε ότι τα components ενδέχεται να δέχονται αυθαίρετα props, συμπεριλαμβανομένων των primitive values, React elements ή συναρτήσεις.
Εάν θέλετε να επαναχρησιμοποιήσετε κάποια λειτουργία εκτός του UI μεταξύ των components, σας συνιστούμε να την εξαγάγετε σε ένα ξεχωριστό JavaScript module. Τα components μπορούν να το κάνουν import και να χρησιμοποιούν αυτή τη συνάρτηση, object ή κλάση, χωρίς να το επεκτείνουν.