Πώς να μετατρέψετε τοRouter σε ένα React Hook

Ένα από τα μεγαλύτερα πλεονεκτήματα του React Hooks στο νέο v16.7 είναι η αφαίρεση της εξάρτησης από εξαρτήματα υψηλότερης τάξης. Ενώ βρισκόμουν στη διαδικασία της μετεγκατάστασης των τάξεων κράτησής μου σε λειτουργικά άγκιστρα, ήμουν giddy στην ευκαιρία να μεταφέρει το συστατικό μου με το router σε υψηλότερο επίπεδο σε ένα άγκιστρο επίσης. Έχω χρησιμοποιήσει αυτήν την προσαρμοσμένη εφαρμογή για να αναδημιουργήσω τα στοιχεία μου στην αλλαγή της διαδρομής. ο ενσωματωμένος αντιδραστήρας-router με το Router HOC δεν αναπαράγει τα εξαρτήματα στην αλλαγή της διαδρομής και είναι δύσκολο να αντιμετωπιστεί.

Αυτό το άρθρο θα πρέπει να χρησιμεύσει ως οδηγός για την εφαρμογή ενός γάντζου React με λειτουργία pub-sub. Το Pub-sub, το οποίο είναι σύντομο για το "publish-subscribe", είναι μια μεθοδολογία προγραμματισμού όπου ένα σύνολο διαδικασιών συνδρομής γίνεται γνωστό όταν δημοσιεύεται μια ενημερωμένη έκδοση. Εν ολίγοις, όταν αλλάζει η τοποθεσία (το δημοσιευμένο συμβάν), θέλω να αναδημιουργήσω το συστατικό μου (την συνδρομή του ακροατή).

Το τελικό προϊόν απαιτεί React Router v4.4 ή μεγαλύτερο, καθώς οι προηγούμενες εκδόσεις του Router React δεν εκθέτουν το περιβάλλον του δρομολογητή, το οποίο χρησιμοποιούμε για να ακούσουμε τις αλλαγές τοποθεσίας. Αν η τελευταία έκδοση του Router React δεν είναι προσβάσιμη από εσάς, μπορείτε να ακούσετε την κατάσταση του ιστορικού των παραθύρων ως εναλλακτική λύση. Επέλεξα να χρησιμοποιήσω την ίδια "ενιαία πηγή αλήθειας" που χρησιμοποιεί ο αντιδραστήρας-δρομολογητής, εξασφαλίζοντας ότι οι καταστάσεις μου είναι πάντα συγχρονισμένες.

Μπορείτε να χρησιμοποιήσετε μόνοι σας αυτή τη συσκευασία μέσω του router use-react-router στο NPM ή να συμβάλλετε στο πύργο GitHub ανοιχτού κώδικα.

Η εμπειρία χρήστη

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

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

Θα ήθελα να εισαγάγω ένα γάντζο από προεπιλεγμένη εξαγωγή πακέτου.

Θέλω να το καλέσω και να τελειώσω με αυτό.

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

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

Η εφαρμογή

Οι εξαρτήσεις

Πρώτον, τις εξαρτήσεις μας.

Θα χρειαστούμε το περιβάλλον δρομολογητή από το πακέτο αντιδραστήρα-δρομολογητή, καθώς περιέχει τα δεδομένα που θέλουμε να έχουμε πρόσβαση στην συνιστώσα μας και θα χρειαστούμε το άγκιστρο useContext από το πακέτο αντιδράσεων να "γαντζώσει" στο περιβάλλον δρομολογητή. Εφόσον εφαρμόζουμε την λειτουργία pub-sub, χρειαζόμαστε επίσης το άγκιστρο useEffect που είναι ενσωματωμένο στο React. Αυτό θα μας επιτρέψει να εγγραφείτε και να καταργήσετε την εγγραφή σας από τις αλλαγές τοποθεσίας.

Τέλος, πρόκειται να εισαγάγω useForceUpdate από το πακέτο NPM ενημέρωσης χρήσης-δύναμης. Είναι απλώς μια συντομογραφία για να καλέσουμε το usestate χέρι για να αναγκάσουμε μια re-rendering, κάτι που θα κάνουμε όταν αλλάξει η θέση.

Το γάντζο

Με τις εξαρτήσεις που εισάγουμε, μπορούμε να αρχίσουμε να γράφουμε το άγκιστρο

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

Αν δεν θέλετε τη λειτουργία ανακατανομής, μπορείτε να σταματήσετε εδώ. Μπορείτε να καταργήσετε τη μεταβλητή forceUpdate, την εφαρμογή useEffect και την εξάρτηση από την εφαρμογή-force-update. Θα ήθελα να συστήσω τη χρήση μιας εξωτερικής χρήσηςReactRouter γάντζου πάνω από το call useContext μέσα στο συστατικό σας μόνο εξαιτίας του ονόματος __RouterContext και του @next semvar που απαιτείται σήμερα για πρόσβαση στο Router React v4.4. Η πρόσβαση σε αυτό το πλαίσιο ενδέχεται να υπόκειται σε αλλαγές και η προσαρμογή στο ενιαίο πακέτο είναι σημαντικά μικρότερη από αυτή της προσαρμογής σε κάθε στοιχείο που εξαρτάται από το δρομολογητή που χρησιμοποιείτε στο έργο σας. Επίσης, είναι πάντα πιο διασκεδαστικό για τους προγραμματιστές να χρησιμοποιούνReactRouter από το useContext (__ RouterContext) - η πρόσθετη εισαγωγή περιβάλλοντος είναι περιττή και αμετάβλητη.

Το Pub-Sub

Για να εφαρμόσουμε συμπεριφορά pub-sub, θα θέλουμε να χρησιμοποιήσουμεEffect. Αυτό θα μας επιτρέψει να εγγραφείτε στην εγκατάσταση και να καταργήσετε την εγγραφή σας στην αποσύνδεση εξαρτημάτων. Θεωρητικά, θα καταργήσει την εγγραφή από ένα παλιό πλαίσιο και θα γίνει εκ νέου εγγραφή σε νέο, εάν το περιβάλλον του δρομολογητή αλλάξει (μια επιθυμητή συμπεριφορά αν αυτό συνέβαινε), αλλά δεν υπάρχει λόγος να υποθέσουμε ότι θα συμβεί ποτέ.

Αντικαταστήστε το / * TODO * / με τα εξής:

useEffect παίρνει μια λειτουργία που θα εκτελέσει κάθε mount και ενημέρωση. Εάν αυτή η συνάρτηση επιστρέφει μια συνάρτηση, αυτή η δεύτερη λειτουργία θα εκτελείται κάθε αποσύνδεση και προεγκατάσταση.

Όπου το αποτέλεσμα1 είναι η εξωτερική συνάρτηση και το αποτέλεσμα2 είναι η εσωτερική συνάρτηση, ο κύκλος ζωής του εξαρτήματος εκτελείται ως εξής:

mount> effect1 ... effect2> update> effect1 ... effect2> unmount

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

Στόχος μας είναι να εγγραφείτε σε αλλαγές τοποθεσίας μόλις συνδεθεί το στοιχείο μας και να διαγραφείτε από τις αλλαγές τοποθεσίας λίγο πριν την αποσύνδεση του στοιχείου.

Η συστοιχία απομνημόνευσης του useEffect λέει ότι "δεν εκτελούν αυτές τις λειτουργίες εφέ στην ενημερωμένη έκδοση εκτός αν αυτή η σειρά παραμέτρων έχει αλλάξει". Μπορούμε να χρησιμοποιήσουμε αυτό για να μην εγγραφούμε συνεχώς και να καταργούμε την εγγραφή στις αλλαγές τοποθεσίας, μόνο και μόνο επειδή το στοιχείο αναδιπλώνεται. Όσο το περιβάλλον του δρομολογητή είναι το ίδιο, δεν χρειάζεται να αλλάξουμε τη συνδρομή μας. Επομένως, η συστοιχία memoization μπορεί να περιέχει ένα μόνο στοιχείο: [routerContext].

Πώς μπορείτε να εγγραφείτε σε αλλαγές τοποθεσίας; Μεταβιβάζοντας μια συνάρτηση στο routerContext.history.listen, αυτή η λειτουργία θα εκτελεστεί κάθε φορά που αλλάζει το ιστορικό του δρομολογητή. Σε αυτήν την περίπτωση, η λειτουργία που θέλουμε να εκτελέσουμε είναι απλά forceUpdate.

Και πώς καταργείτε την εγγραφή σας από αλλαγές τοποθεσίας; Δεν μπορούμε απλώς να αφήσουμε αυτή τη συνδρομή μετά την αποσύνδεση της συνιστώσας - η forceUpdate θα κληθεί, αλλά δεν θα υπάρχει ένα στοιχείο για ενημέρωση!

routerContext.history.listen επιστρέφει μια συνάρτηση κατάργησης εγγραφής που, όταν καλείται, καταργεί τον ακροατή συνδρομής (forceUpdate) από το συμβάν.

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

Και ακόμη μικρότερη:

Πού να πάτε από εδώ;

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

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

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

Συμπέρασμα

Εάν θέλετε να συνεισφέρετε σε αυτό το πακέτο ανοιχτού κώδικα ή να το δείτε στο TypeScript, μπορείτε να το αστερίσετε, να το ανοίξετε, να ανοίξετε προβλήματα ή διαφορετικά να το ελέγξετε στο GitHub. Μπορείτε να χρησιμοποιήσετε μόνοι σας αυτό το πακέτο μέσω του router use-react-router στο NPM.

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

Για να διαβάσετε περισσότερες από τις στήλες μου, μπορείτε να ακολουθήσετε με το LinkedIn και το Twitter ή να ελέγξετε το χαρτοφυλάκιό μου στο CharlesStover.com.