Δημιουργήστε μια εφαρμογή React από την αρχή (Μέρος 7): Ρύθμιση του React και Best Practices

Αυτή η ανάρτηση αποτελεί μέρος μιας σειράς θέσεων για αρχάριους που προορίζονται για άτομα που χρησιμοποιούν
έτοιμα εργαλεία, πρότυπα ή πινακίδες για το React, αλλά επιθυμούν να μάθουν και να κατανοήσουν πώς να χτίσουν μια εφαρμογή React από την αρχή.

Όλες οι δημοσιεύσεις αυτής της σειράς:
Μέρος 1: Εισαγωγή
Μέρος 2: Αρχικοποίηση και το πρώτο αρχείο
Μέρος 3: Χρήση της σύνταξης ES2015
Μέρος 4: Εφαρμογή ενός οδηγού στυλ
Μέρος 5: Εγκατάσταση ενός διακομιστή Express
Μέρος 6: Χρήση ενός πακέτου μονάδων
Μέρος 7: Ρύθμιση του React και των Βέλτιστων Πρακτικών
Μέρος 8: Ρύθμιση του Redux
Μέρος 9: Ρύθμιση του δρομολογητή αντίδρασης
Μέρος 10: TDD και ρύθμιση του Jest

Ρύθμιση του React

Σε αυτήν την ανάρτηση, θα ρυθμίσουμε το React και θα δημιουργήσουμε ένα πολύ απλό συστατικό και στη συνέχεια θα ακολουθήσουμε μερικές από τις βέλτιστες πρακτικές που θα πρέπει να έχετε κατά νου όταν αναπτύσσετε συστατικά React. Εδώ ξεκινάει το κομμάτι διασκέδασης, οπότε ας σκάψουμε δεξιά!

Εγκαταστήστε πακέτα React και React Dom ως εξαρτήσεις:

$ npm install - να αντιδράσει αντίδραση-dom

Στη συνέχεια, ανοίξτε το index.js και δημιουργήστε ένα πολύ απλό στοιχείο React που αντιπροσωπεύει την εφαρμογή μας. Έχουμε ήδη ένα στοιχείο με εφαρμογή id στο αρχείο temp template index.pug, οπότε ας το χρησιμοποιήσουμε για να τοποθετήσουμε την εφαρμογή.

/ **
 * index.js
 * /
εισαγωγή Αντιδρά από "αντιδρά";
εισαγωγή {render} από το "react-dom".
const MainApp = () => (
  

Hello React! ) ·

// αποδώστε την εφαρμογή
rendering (, document.getElementById ('app'));

Αυτός ο απλός κώδικας δημιουργεί μια βασική λειτουργική συνιστώσα MainApp και το τοποθετεί σε ένα στοιχείο DOM που έχει εφαρμογή id. Αυτός ο κώδικας δε θα λειτουργούσε αμέσως και θα λάβατε λάθος εάν προσπαθήσετε να δημιουργήσετε τη δέσμη ή να ξεκινήσετε το διακομιστή.

Ο λόγος για αυτό το σφάλμα είναι ότι έχουμε σύνταξη JSX στο αρχείο index.js που η Babel δεν κατανοεί ακόμα. Για να μπορέσει η Babel να ερμηνεύσει αυτή τη σύνταξη σε κανονικό JavaScript, πρόκειται να χρησιμοποιήσουμε την προεπιλογή React για Babel.

Εγκαταστήστε τη συσκευασία ως εξάρτηση:

$ npm install - αποθήκευση babel-preset-react

Στη συνέχεια, προσθέστε την προεπιλογή στη λίστα των προεπιλογών σε αρχείο .babelrc:

{
  "προεπιλογές": [
    "es2015",
    "στάδιο-0",
    "αντιδρώ"
  ],
  "plugins": ["μεταβλητές-inline-περιβάλλον-μεταβλητές"]
}}

Θα πρέπει επίσης να υπάρχει ένα λάθος χνούδι που θα σας εμποδίσει να χτίσετε τη δέσμη. Το linter διαμαρτύρεται επειδή το index.js είναι ένα αρχείο JavaScript που περιέχει σύνταξη JSX αλλά χρησιμοποιεί την επέκταση js αντί για το jsx.

Μπορείτε να διαβάσετε εδώ την περιγραφή αυτού του κανόνα. Η ενότητα "Όταν δεν το χρησιμοποιείτε" λέει ότι δεν πρέπει να χρησιμοποιήσετε αυτόν τον κανόνα εάν δεν σας ενδιαφέρει να περιορίσετε την επέκταση των αρχείων που περιέχουν σύνταξη JSX.

Μπορείτε να συνεχίσετε να χρησιμοποιείτε αυτόν τον κανόνα, αλλά προτιμώ να χρησιμοποιήσω την επέκταση js για όλα τα αρχεία, επομένως πρόκειται να απενεργοποιήσω αυτόν τον κανόνα:

{
  "επεκτείνει": "airbnb",
  "env": {
    "es6": true,
    "browser": true,
    "κόμβος": αληθής
  },
  "κανόνες": {
    "react / jsx-filename-extension": 0
  }}
}}

Ενεργοποίηση της HMR

Η ενεργοποίηση της αντικατάστασης θερμής μονάδας είναι τόσο απλή όσο η προσθήκη ενός μπλοκ κώδικα:

/ **
 * index.js
 * /
εισαγωγή Αντιδρά από "αντιδρά";
εισαγωγή {render} από το "react-dom".
αν (module.hot) {
  module.hot.accept ();
}}
const MainApp = () => (
  

Hello React! ) ·

// αποδώστε την εφαρμογή
rendering (, document.getElementById ('app'));

Συμβουλές και βέλτιστες πρακτικές

Πριν συνεχίσουμε με το σεμινάριο, θα περάσουμε από μια συγκεντρωτική λίστα συμβουλών και βέλτιστων πρακτικών που έχω μάθει από την εμπειρία μου που συνεργάζομαι με το React καθώς και από την ανάγνωση και την αναζήτηση στον ιστό. Κρατήστε αυτά κατά νου όταν δημιουργείτε τα στοιχεία React.

Εισαγωγές εξαρτήσεων έναντι τοπικών εισαγωγών

Διαχωρίστε τις εισαγωγές εξάρτησης από τις τοπικές εισαγωγές με μια νέα γραμμή. Οι εισαγωγές εξαρτήσεων πρέπει να είναι πρώτες.

εισαγάγετε React, {Component} από το 'react';
να εισαγάγετε χρήσιμο Module από το 'useful-module'.
εισαγάγετε το myLocalModule από './my-local-module'.

Άτατα Λειτουργικά Συστατικά

Εάν το στοιχείο είναι συστατικό μόνο για την απόδοση ή δεν χρειάζεται να χρησιμοποιήσετε ένα κρατικό αντικείμενο, χρησιμοποιήστε μια απλή λειτουργία JavaScript αντί για μια κλάση. Αυτό ονομάζεται λειτουργικό στοιχείο χωρίς καθεστώς.

Έτσι, αντί να το κάνετε αυτό:

εισαγάγετε React, {Component} από το 'react';
class MyComponent επεκτείνει το στοιχείο {
  render () {
    ΕΠΙΣΤΡΟΦΗ (
      
Γεια σας!     ) ·   }} }}
προεπιλογή εξαγωγής MyComponent;

Κάνε αυτό:

εισαγωγή Αντιδρά από "αντιδρά";
const MyComponent = () => 
Γεια σας! ;
προεπιλογή εξαγωγής MyComponent;

Δείτε πόσα ακαταστασία έχει αφαιρεθεί; Θα μπορούσατε επίσης να το κάνετε απλούστερο εξάγοντας την ίδια τη λειτουργία:

εισαγωγή Αντιδρά από "αντιδρά";
εξαγωγή προεπιλογή () => 
Γεια σας! ;

Ωστόσο, δεν προτιμώ να το κάνω αυτό επειδή κάνει πιο δύσκολο το σβήσιμο. Αν ελέγξετε τα εργαλεία React Dev, θα δείτε ότι το όνομα του στοιχείου είναι "Άγνωστο", επειδή η λειτουργία είναι ανώνυμη.

Ανώνυμο λειτουργικό στοιχείο

Μια καλύτερη προσέγγιση θα ήταν να χρησιμοποιήσετε μια κανονική ονομαστική λειτουργία αντί για μια ανώνυμη λειτουργία:

εισαγωγή Αντιδρά από "αντιδρά";
προεπιλεγμένη συνάρτηση εξαγωγής MyComponent () {
  επιστρέψτε 
Γεια σας! ; }}
Ονομασμένο λειτουργικό στοιχείο

Ξεκινήστε με τα Presentational Components

Τα πακέτα παρουσιάσεων είναι απλούστερα στον καθορισμό, είναι ευκολότερα κατανοητά και μπορούν να επαναχρησιμοποιηθούν ξανά και ξανά επειδή είναι ανεξάρτητα από την υπόλοιπη εφαρμογή.

Αν σπάσετε την αίτησή σας σε ένα σύνολο παρουσιάσιμων στοιχείων, μπορείτε να τα βάλετε σε μια σελίδα και να τροποποιήσετε το σχεδιασμό και τις παραλλαγές τους, για να επιτύχετε μια ενιαία εμφάνιση και αίσθηση σε ολόκληρη την εφαρμογή.

Δημιουργήστε το συστατικό σας ως παρουσιάσιμο στοιχείο και προσθέστε μόνο την κατάσταση όταν χρειάζεται, η οποία μας φέρνει στην επόμενη συμβουλή.

Ελαχιστοποίηση της χρήσης του κράτους

Χρησιμοποιήστε την κατάσταση με φειδώ στα συστατικά σας και σιγουρευτείτε ότι χρησιμοποιούν την κατάσταση για το UI και όχι τα δεδομένα, με άλλα λόγια, αν δεν το χρησιμοποιείτε στην απόδοση (), τότε δεν πρέπει να είναι στην κατάσταση. Θυμηθείτε ότι θα πρέπει να χρησιμοποιείτε μόνο το setState, εάν θέλετε να κάνετε ξανά τη συνιστώσα σας.

Ας πούμε ότι έχουμε ένα στοιχείο που αποτελείται από ένα μόνο κουμπί. Αυτό το κουμπί μπορεί να κάνει κλικ μόνο μία φορά και όταν γίνει κλικ, θα καταγραφεί ένα μήνυμα στην κονσόλα:

εισαγάγετε React, {Component} από το 'react';

class MyComponent επεκτείνει το στοιχείο {
  state =
    clickedOnce: false,
  },
  handleClick = () => {
    αν (! thisstatestate.clickedOnce) {
      console.log ('κλικ');
    }}
    this.setState ({
      clickedOnce: true,
    });
  }}
  componentDidUpdate () {
    console.log ('Ενημερώθηκε!');
  }}
  render () {
    ΕΠΙΣΤΡΟΦΗ (
      
        <κουμπί onClick = {this.handleClick}> Κάντε κλικ στο κουμπί            ) ·   }} }}
προεπιλογή εξαγωγής MyComponent;

Αυτό είναι ένα παράδειγμα κακής εφαρμογής, χρησιμοποιώντας την κατάσταση για να ορίσετε μια σημαία clickedOnce η οποία καθορίζει αν μπορεί να γίνει ξανά κλικ στο κουμπί. Κάθε φορά που κάνετε κλικ στο κουμπί, το στοιχείο θα επανεκδοθεί ακόμα κι αν δεν χρειάζεται.

Η εφαρμογή εκ νέου γίνεται με το πάτημα του κουμπιού

Αυτό θα ήταν καλύτερο:

εισαγάγετε React, {Component} από το 'react';

class MyComponent επεκτείνει το στοιχείο {
  clickedOnce = false;
  
  handleClick = () => {
    αν (! this.clickedOnce) {
      console.log ('κλικ');
    }}
    this.clickedOnce = true;
  }}
  componentDidUpdate () {
    console.log ('Ενημερώθηκε!');
  }}
  render () {
    ΕΠΙΣΤΡΟΦΗ (
      
        <κουμπί onClick = {this.handleClick}> Κάντε κλικ στο κουμπί            ) ·   }} }}
προεπιλογή εξαγωγής MyComponent;

Αυτή η υλοποίηση χρησιμοποιεί μια ιδιότητα κλάσης αντί για ένα κρατικό κλειδί επειδή η σημαία clickedOnce δεν αντιπροσωπεύει κατάσταση περιβάλλοντος χρήστη και επομένως δεν πρέπει να ζει μέσα στην κατάσταση συνιστωσών. Με αυτή τη νέα εφαρμογή, κάνοντας κλικ στο κουμπί περισσότερες από μία φορές, δεν ενεργοποιείται πλέον μια ενημέρωση.

Πάντα να ορίζετε πρότυπα και defaultProps

Όλα τα συστατικά θα πρέπει να έχουν τα πρότυπα και τα defaultProps που ορίζονται όσο το δυνατόν υψηλότερα μέσα στο στοιχείο. Χρησιμεύουν ως τεκμηρίωση στοιχείων και πρέπει να είναι άμεσα ορατά σε άλλους προγραμματιστές που διαβάζουν το αρχείο.

Από το React v15.5, το React.PropTypes μετακινήθηκε σε διαφορετικό πακέτο, οπότε ας εγκαταστήσουμε το πακέτο ως εξάρτηση:

$ npm install --save prop-types

Για λειτουργικά στοιχεία χωρίς καθεστώς:

Οι λειτουργίες ανυψώνονται στο JavaScript, πράγμα που σημαίνει ότι μπορείτε να χρησιμοποιήσετε μια λειτουργία πριν από τη δήλωση:

εισαγωγή Αντιδρά από "αντιδρά";
την εισαγωγή προτύπων από «προ-τύπους».
MyComponent.propTypes = {
  τίτλος: PropTypes.string,
},
MyComponent.defaultProps = {
  τίτλος: «Ένας απλός μετρητής»,
},
λειτουργία προεπιλογής εξαγωγής MyComponent (υποστηρίξεις) {
  επιστροφή 

{props.title} . }}

Το ESLint θα διαμαρτυρόταν για τη χρήση της λειτουργίας πριν από τον ορισμό της, αλλά για λόγους καλύτερης τεκμηρίωσης στοιχείων, ας απενεργοποιήσουμε αυτόν τον κανόνα για τη λειτουργία των λειτουργιών τροποποιώντας το αρχείο .eslintrc:

{
  ...
  "κανόνες": {
    "react / jsx-filename-extension": 0,
    "no-use-before-define": [
      "λάθος",
      {
        "λειτουργίες": ψευδές
      }}
    ]
  }}
}}

Για συστατικά με βάση την κλάση:

Αντίθετα από τις λειτουργίες, οι κλάσεις στο JavaScript δεν ανυψώνονται, οπότε δεν μπορούμε απλά να κάνουμε MyComponent.propTypes = ... πριν καθορίσουμε την ίδια την κλάση, αλλά μπορούμε να ορίσουμε propTypes και defaultProps ως ιδιότητες static class:

εισαγάγετε React, {Component} από το 'react';
την εισαγωγή προτύπων από «προ-τύπους».
class MyComponent επεκτείνει το στοιχείο {
  static propTypes = {
    τίτλος: PropTypes.string,
  },
  static defaultProps = {
    τίτλος: «Ένας απλός μετρητής»,
  },
  render () {
    επιστροφή 

{this.props.title} ;   }} }}

προεπιλογή εξαγωγής MyComponent;

Αρχικοποίηση του κράτους

Η κατάσταση μπορεί να αρχικοποιηθεί εντός του κατασκευαστή κατασκευαστικού στοιχείου:

class MyComponent επεκτείνει το στοιχείο {
  κατασκευαστής (στηρίγματα) {
    σούπερ (στηρίγματα);
    this.state = {
      Αριθμός: 0,
    },
  }}
}}

Ένας καλύτερος τρόπος είναι να αρχικοποιήσετε την κατάσταση ως ιδιότητα κατηγορίας:

class MyComponent επεκτείνει το στοιχείο {
  κατασκευαστής (στηρίγματα) {
    σούπερ (στηρίγματα);
  }}
  state =
    Αριθμός: 0,
  },
}}

Αυτό φαίνεται πολύ καλύτερα, καθαρότερο, πιο ευανάγνωστο και συμβάλλει επίσης στην τεκμηρίωση των στοιχείων. Το αντικείμενο πολιτείας πρέπει να αρχικοποιηθεί μετά από propTypes και defaultProps:

εισαγάγετε React, {Component} από το 'react';
την εισαγωγή προτύπων από «προ-τύπους».
class MyComponent επεκτείνει το στοιχείο {
  // propTypes έρχεται πρώτα
  static propTypes = {
    τίτλος: PropTypes.string,
  },
  // defaultProps έρχεται δεύτερη
  static defaultProps = {
    τίτλος: «Ένας απλός μετρητής»,
  },
  // Ο κατασκευαστής έρχεται εδώ
  κατασκευαστής () {
    ...
  }}
  // τότε έρχεται η κατάσταση
  state =
    Αριθμός: 0,
  },
}}

Περάστε μια λειτουργία στο setState

Το React Documentation αποθαρρύνει την εξάρτηση από αυτό το state.state και this.props τιμές για τον υπολογισμό της επόμενης κατάστασης επειδή το React τις ενημερώνει ασύγχρονα. Αυτό σημαίνει ότι η κατάσταση δεν μπορεί να αλλάξει αμέσως μετά την κλήση του setState ().

class MyComponent επεκτείνει το στοιχείο {
  state =
    Αριθμός: 10,
  }}
  onClick = () => {
    console.log (αυτό το κράτος.κάντα); // 10
    
    // count δεν θα αλλάξει αμέσως
    this.setState ({count: this.state.count + this.props.step}).
    
    console.log (αυτό το κράτος.κάντα); // ακόμα 10
  }}
}}

Ενώ αυτό λειτουργεί για απλά σενάρια και το κράτος θα εξακολουθεί να ενημερώνεται σωστά, μπορεί να οδηγήσει σε απροσδόκητη συμπεριφορά σε πιο σύνθετα σενάρια.

Σκεφτείτε αυτό το σενάριο, έχετε ένα στοιχείο που κάνει ένα μόνο κουμπί. Κάνοντας κλικ σε αυτό το κουμπί, ονομάζεται μέθοδος handleClick:

class MyComponent επεκτείνει το στοιχείο {
  static defaultProps = {
    βήμα: 5,
  }}
  static propTypes = {
    βήμα: PropTypes.number,
  }}
  
  state =
    Αριθμός: 10,
  }}
  
  handleClick = () => {
    this.doSomething ();
    this.doSomethingElse ();
  }}
  doSomething = () => {
    this.setState ({count: this.state.count + this.props.step}).
  }}
  doSomethingElse = () => {
    this.setState ({count: this.state.count - 1}).
  }}
  render () {
    ΕΠΙΣΤΡΟΦΗ (
      
        

Η τρέχουσα μέτρηση είναι: {this.state.count}         <κουμπί onClick = {this.handleClick}> Κάντε κλικ στο κουμπί            ) ·   }} }}

Το κουμπί καλεί το handleClick () όταν κάνει κλικ, το οποίο με τη σειρά του καλεί doSomething () και στη συνέχεια doSomethingElse (). Και οι δύο λειτουργίες θα τροποποιήσουν την τιμή μέτρησης μέσα στην κατάσταση.

Λογικά, το 10 + 5 είναι 15 και στη συνέχεια αφαιρείται 1 και το αποτέλεσμα πρέπει να είναι 14, σωστά; Λοιπόν, σε αυτή την περίπτωση δεν είναι - η τιμή του count μετά το πρώτο κλικ είναι 9, όχι το 14. Αυτό συμβαίνει επειδή η αξία αυτού του state.state.count είναι ακόμα 10 όταν ονομάζεται doSomethingElse (), όχι 15.

Για να διορθώσετε αυτό, μπορείτε να χρησιμοποιήσετε μια δεύτερη μορφή του setState () που δέχεται μια λειτουργία και όχι ένα αντικείμενο. Αυτή η συνάρτηση θα λάβει την προηγούμενη κατάσταση ως πρώτο όρισμα και τα στηρίγματα τη στιγμή που θα εφαρμοστεί η επικαιροποίηση ως το δεύτερο όρισμα:

this.setState ((prevState, props) => ({
  count: prevState.count + props.step
}))

Μπορούμε να χρησιμοποιήσουμε αυτή τη φόρμα για να καθορίσουμε το παράδειγμά μας:

class MyComponent επεκτείνει το στοιχείο {
  ...
  handleClick = () => {
    this.doSomething ();
    this.doSomethingElse ();
  }}
  doSomething = () => {
    this.setState ((prevState, props) => ({
      count: prevState.count + props.step
    }}).
  }}
  doSomethingElse = () => {
    this.setState (prevState => ({
      count: prevState.count - 1
    }}).
  }}
  ...
}}

Με αυτήν την εφαρμογή, ο αριθμός ενημερώνεται σωστά από 10 έως 14 έως 18 και ούτω καθεξής. Τα απλά μαθηματικά έχουν και πάλι νόημα!

Χρησιμοποιήστε τις λειτουργίες βέλους ως ιδιότητες κλάσης

Αυτή η λέξη-κλειδί ήταν πάντα σύγχυση για τους προγραμματιστές JavaScript και η συμπεριφορά της δεν είναι λιγότερο σύγχυση στα στοιχεία React. Γνωρίζετε πώς αλλάζει αυτή η λέξη-κλειδί σε ένα στοιχείο React; Εξετάστε το ακόλουθο παράδειγμα:

εισαγάγετε React, {Component} από το 'react';
class MyComponent επεκτείνει το στοιχείο {
  state =
    Αριθμός: 0,
  },
  στο κλικ() {
    console.log (αυτό το κράτος);
  }}
  render () {
    ΕΠΙΣΤΡΟΦΗ (
      
        

Η αρίθμηση είναι: {this.state.count}         <κουμπί onClick = {this.onΚάντε κλικ}> Κάντε κλικ στο κουμπί            ) ·   }} }}

προεπιλογή εξαγωγής MyComponent;

Κάνοντας κλικ στο κουμπί θα προκληθεί σφάλμα:

Uncaught TypeError: Δεν είναι δυνατή η ανάγνωση της ιδιότητας 'state' του undefined

Αυτό συμβαίνει επειδή το onClick, ως μέθοδος κλάσης, δεν δεσμεύεται από προεπιλογή. Υπάρχουν μερικοί τρόποι για να διορθωθεί αυτό. (λογοπαίγνιο προορίζεται, να το πάρει;)

Ένας τρόπος είναι να δεσμεύσετε τη συνάρτηση στο σωστό πλαίσιο καθώς την περνάτε μέσα στη λειτουργία rendering ():

<κουμπί onClick = {this.onClick.bind (αυτό)}> Κάντε κλικ στο κουμπί 

Ή μπορείτε να αποφύγετε την αλλαγή του πλαισίου χρησιμοποιώντας μια λειτουργία βέλους στην απόδοση ():

<κουμπί onClick = {e => this.onΚάντε κλικ (ε)}> Κάντε κλικ στο κουμπί 

Ωστόσο, αυτές οι δύο μέθοδοι έχουν ένα μικρό κόστος απόδοσης επειδή η λειτουργία θα ανακατανεμηθεί σε κάθε απόδοση. Για να αποφύγετε αυτό το μικρό κόστος απόδοσης, μπορείτε να δεσμεύσετε τη λειτουργία μέσα στον κατασκευαστή:

εισαγάγετε React, {Component} από το 'react';
class MyComponent επεκτείνει το στοιχείο {
  κατασκευαστής (στηρίγματα) {
    σούπερ (στηρίγματα);
    this.onClick = this.onClick.bind (αυτό).
  }}
  ...
  render () {
    ...
    <κουμπί onClick = {this.onΚάντε κλικ}> Κάντε κλικ στο κουμπί 
    ...
  }}
}}
προεπιλογή εξαγωγής MyComponent;

Αυτή η τεχνική είναι καλύτερη, αλλά θα μπορούσε εύκολα να παρασυρθεί και να καταλήξει σε κάτι που μοιάζει με αυτό:

κατασκευαστής (στηρίγματα) {
  // αυτό είναι κακό, πραγματικά κακό
  this.onClick = this.onClick.bind (αυτό).
  this.onChange = this.onChange.bind (αυτό);
  this.onSubmit = this.onSubmit.bind (αυτό);
  this.increaseCount = this.increaseCount.bind (αυτό).
  this.decreaseCount = this.decreaseCount.bind (αυτό).
  this.resetCount = this.resetCount.bind (αυτό).
  ...
}}

Εφόσον χρησιμοποιούμε τη Babel και υποστηρίζουμε τις ιδιότητες της κλάσης, ο καλύτερος τρόπος θα ήταν να χρησιμοποιούμε τις λειτουργίες βέλους κατά τον ορισμό των μεθόδων της κλάσης:

class MyComponent επεκτείνει το στοιχείο {
  ...
  onClick = () => {
    // 'αυτό διατηρείται
    console.log (αυτό το κράτος);
  }}
  render () {
    ΕΠΙΣΤΡΟΦΗ (
      
        

{this.state.count}         <κουμπί onClick = {this.onΚάντε κλικ}> Κάντε κλικ στο κουμπί            ) ·   }} }}

Καταστρέψτε το αντικείμενο Props

Όταν ένα στοιχείο έχει πολλά στηρίγματα, καταστρέψτε το αντικείμενο στηρίγματος τοποθετώντας κάθε ιδιότητα στη δική του γραμμή.

Για λειτουργικά στοιχεία χωρίς καθεστώς:

προεπιλεγμένη συνάρτηση εξαγωγής MyComponent ({
  όνομα,
  Επίθετο,
  διεύθυνση ηλεκτρονικού ταχυδρομείου,
  περιγραφή,
  onChange,
  onSubmit,
}) {
  ΕΠΙΣΤΡΟΦΗ (
    
      

{firstName}       ...        ) · }}

Τα προκαθορισμένα επιχειρήματα δεν αποτελούν δικαιολογία για την αποχώρηση των defaultProps. Όπως αναφέρθηκε προηγουμένως, θα πρέπει πάντα να ορίζετε propTypes και defaultProps.

Για συστατικά με βάση την κλάση:

class MyComponent επεκτείνει το στοιχείο {
  ...
  render () {
    const {
      όνομα,
      Επίθετο,
      διεύθυνση ηλεκτρονικού ταχυδρομείου,
      περιγραφή,
      onChange,
      onSubmit,
    } = this.props;
    ΕΠΙΣΤΡΟΦΗ (
      
        

{firstName}         ...            ) ·   }} }}

Αυτό είναι καθαρότερο, διευκολύνει την αναδιάταξη των ιδιοτήτων και διευκολύνει την προσθήκη / αφαίρεση των ιδιοτήτων από / προς τη λίστα ενώ παράγει μια ευδιάκριτη διαφορά για το Git. Σκέψου τα ακόλουθα:

Η διαφορά είναι πιο ευανάγνωστη όταν κάθε ιδιοκτησία βρίσκεται σε νέα γραμμή

Στη δεξιά πλευρά, μπορείτε εύκολα να πείτε ποια ιδιότητα προστέθηκε, ωστόσο στην αριστερή πλευρά γνωρίζετε μόνο ότι κάτι έχει αλλάξει σε αυτή τη γραμμή και θα πρέπει να κοιτάξετε πολύ προσεκτικά για να καταλάβετε ποιο μέρος της γραμμής ήταν άλλαξε.

Υποχρεωτική απόδοση

Όταν χρειάζεται να κάνετε μία από τις δύο συνιστώσες ή μπλοκ του κώδικα JSX με βάση μια συνθήκη, χρησιμοποιήστε μια τριμερή έκφραση:

isLoggedIn
  ; 
Καλώς ορίσατε, {username}!   : <κουμπί onClick = {this.login}> Σύνδεση

Εάν ο κώδικας αποτελείται από περισσότερες από μία γραμμές, χρησιμοποιήστε παρενθέσεις:

isLoggedIn? (
  
    Καλώς ήλθατε, {usename}!    ): (   <κουμπί onClick = {this.login}>     Σύνδεση    )

Αν χρειάζεται να κάνετε μια συνιστώσα ή ένα μπλοκ κώδικα JSX βασισμένο σε μια συνθήκη, χρησιμοποιήστε μια αξιολόγηση βραχυκυκλώματος αντί:

isComplete && 
Έχετε τελειώσει!

Για περισσότερες από μία γραμμές, χρησιμοποιήστε παρενθέσεις:

ολοκληρώθηκε && (
  
    Τελείωσες!    )

Το χαρακτηριστικό κλειδιού

Πρόκειται για ένα κοινό πρότυπο για τη χρήση του Array.prototype.map και παρόμοιων μεθόδων συστοιχιών μέσα στη λειτουργία rendering () και είναι εύκολο να ξεχάσουμε το χαρακτηριστικό key. Η συμφιλίωση είναι αρκετά δύσκολη, μην το καταστήσετε δυσκολότερο. Να θυμάστε πάντα να τοποθετείτε το κλειδί από όπου ανήκει. (η λογοπαίγνιο προορίζεται και πάλι, πάρε το;)

render () {
  ΕΠΙΣΤΡΟΦΗ (
    
    {       {         items.map (στοιχείο => (           
  •             {όνομα προϊόντος}                    ))        }}        ) · }}

Όταν χρησιμοποιείτε το χάρτη (), το φίλτρο () ή παρόμοιες μεθόδους πίνακα, η δεύτερη παράμετρος για την επανάκληση είναι ο δείκτης του στοιχείου. Είναι γενικά κακή ιδέα να χρησιμοποιήσετε αυτόν τον δείκτη ως κλειδί. Το React χρησιμοποιεί το χαρακτηριστικό κλειδιού για να προσδιορίσει ποια στοιχεία έχουν αλλάξει, έχουν προστεθεί ή έχουν αφαιρεθεί και ότι η τιμή του κλειδιού πρέπει να είναι σταθερή και πρέπει να προσδιορίζει με μοναδικό τρόπο κάθε στοιχείο.

Σε περιπτώσεις όπου ο πίνακας ταξινομείται ή προστίθεται ένα στοιχείο στην αρχή του πίνακα, ο δείκτης θα αλλάξει ακόμα κι αν το στοιχείο που αντιπροσωπεύει αυτόν το δείκτη μπορεί να είναι το ίδιο. Αυτό οδηγεί σε περιττές αποδόσεις και σε ορισμένες περιπτώσεις έχει ως αποτέλεσμα την εμφάνιση λανθασμένων δεδομένων.

Χρησιμοποιήστε το UUID ή το ShortID για να δημιουργήσετε ένα μοναδικό αναγνωριστικό για κάθε στοιχείο κατά την πρώτη του δημιουργία και να το χρησιμοποιήσετε ως τιμή κλειδιού.

Κανονικοποιήστε την κατάσταση

Προσπαθήστε να ομαλοποιήσετε το κρατικό αντικείμενο και να το κρατήσετε όσο το δυνατόν πιο επίπεδη. Η αποθήκευση δεδομένων σε κατάσταση σημαίνει ότι απαιτείται πιο πολύπλοκη λογική για την ενημέρωσή της. Φανταστείτε πόσο άσχημο θα ήταν να ενημερώσετε ένα βαθιά ένθετο πεδίο - περιμένετε, μην το φανταστείτε, εδώ:

// το αντικείμενο του κράτους
state =
  ...
  δημοσιεύσεις: [
    ...,
    {
      meta: {
        id: 12,
        συγγραφέας: '...',
        δημόσια: ψευδή,
        ...
      },
      ...
    },
    ...
  ],
  ...
},
// για την ενημέρωση του 'public' στο 'true'
this.setState ({
  ... thisstatestate,
  δημοσιεύσεις: [
    ... this.state.posts.slice (0, ευρετήριο),
    {
      ... this.state.posts [index],
      meta: {
        ... this.state.posts [index] .meta,
        δημόσιο: αληθινό,
      }}
    },
    ... this.state.posts.slice (ευρετήριο + 1),
  ]
});

Ο κώδικας αυτός είναι όχι μόνο άσχημος, αλλά μπορεί επίσης να αναγκάσει τα μη συνδεδεμένα εξαρτήματα να αναπαράγουν ακόμη και αν τα δεδομένα που εμφανίζουν δεν έχουν αλλάξει. Αυτό συμβαίνει επειδή έχουμε ενημερώσει όλους τους προγόνους στο δέντρο καταστάσεων με νέες αναφορές αντικειμένων.

Η ενημέρωση του ίδιου πεδίου θα ήταν απλούστερη αν αναδιαρθρούσαμε το δέντρο κατάστασης:

state =
  δημοσιεύσεις: [
    10,
    11,
    12,
  ],
  meta: {
    10: {
      id: 10,
      συγγραφέας: 'συγγραφέας-α',
      δημόσια: ψευδή,
    },
    11: {
      id: 11,
      συγγραφέας: 'author-b',
      δημόσια: ψευδή,
    },
    12: {
      id: 12,
      συγγραφέας: 'author-c',
      δημόσια: ψευδή,
    },
  },
}}
this.setState ({
  meta: {
    ... this.state.meta,
    [id]: {
      ... this.state.meta [id],
      δημόσιο: αληθινό,
    }}
  }}
})

Χρησιμοποιήστε ονόματα κλασμάτων

Αν έχετε ποτέ βρεθεί σε μια κατάσταση όπου πρέπει να χρησιμοποιήσετε ένα conditionname class, ίσως έχετε γράψει κάτι που μοιάζει με αυτό:

  ...

Αυτό γίνεται πραγματικά άσχημο αν έχετε πολλαπλά κλασικά ονόματα. Αντί να χρησιμοποιήσετε ένα τριαδικό, χρησιμοποιήστε το πακέτο classnames:

Εισαγωγή κλασμάτων από 'classnames'.
const classes = ονόματα κλασμάτων ('tab', {'is-active': isActive});
  ...

Ένα συστατικό ανά αρχείο

Αυτός δεν είναι ένας σκληρός κανόνας, αλλά προτιμώ να διατηρήσω κάθε στοιχείο σε ένα μόνο αρχείο και προεπιλεγμένη εξαγωγή αυτού του στοιχείου. Δεν έχω συγκεκριμένους λόγους γι 'αυτό, αλλά το βρίσκω πιο καθαρό και οργανωμένο - υψηλό πέντε αν το κάνετε και αυτό!

συμπέρασμα

Δεν υπάρχει κανένας σωστός τρόπος για να αναπτύξετε ένα στοιχείο React. Έχουμε περάσει από μερικές από τις βέλτιστες πρακτικές και τα πρότυπα που θα σας βοηθήσουν να αναπτύξετε επαναχρησιμοποιήσιμα και συντηρητικά στοιχεία και είμαι πολύ περίεργος να μάθω τι είδους πρότυπα και πρακτικές προτιμάτε και γιατί.

Στο επόμενο μέρος αυτής της σειράς, πρόκειται να δημιουργήσουμε μια απλή εφαρμογή To-Do και να εφαρμόσουμε ορισμένες από αυτές τις βέλτιστες πρακτικές και πρότυπα.

Το άρθρο αυτό ήταν χρήσιμο; Κάντε κλικ στο κουμπί Κτύπημα παρακάτω ή ακολουθήστε με για περισσότερα.

Ευχαριστώ για την ανάγνωση! Αν έχετε κάποια σχόλια, αφήστε ένα σχόλιο παρακάτω.

Μεταβείτε στο Μέρος 7-β: Δημιουργώντας μια απλή εφαρμογή ToDo (Σύντομα)