A magasabb rendű alkatrészek (HOC) egyfajta React komponensek, amelyek segítenek a logika újrafelhasználásában az alkalmazásban. A terminológia összetettnek tűnhet, de a HOC-kat könnyű kezelni, és egyszerűbbé teheti a kódbázis fenntartását.
A Magasabb rendű alkatrész a gyermek alkatrészeit mindig további funkciókkal csomagolja be. A HOC olyan funkcióként definiálható, amely egy komponenst paraméterként fogad el. Ezután visszatér a új komponens, amely általában a bemeneti komponenst extra kellékekkel csomagolja.
Egyszerű példa
A legjobb módja annak, hogy megbecsüljük a HOC-k értelmét, ha látjuk őket működésben. Vegyünk egy egyszerű fizetési rendszert, ahol a felhasználó kosarának állapotát központilag tároljuk az alkalmazáson belül. Példáink szerint a Redux mint állami üzlet, de ez csak szemléltető célokra szolgál.
Tegyük fel, hogy ez az objektum képviseli alkalmazásunk állapotát:
{ checkout: { items: [ { label: "Product 1", price: 150.00, quantity: 2 }, { label: "Product 2", price: 75.00, quantity: 1 } ] } }
Van egy egyszerű tömbünk, amely a felhasználó kosarában található elemeket ábrázolja. Pénztári összetevőink ebből az állapotból további értékeket fognak származtatni, például a teljes rendelési értéket és az alkalmazandó adókat.
A fizetési rendszerünknek valószínűleg meg kell mutatnia a teljes értéket több független összetevőn belül. Lehet, hogy van egy oldalsáv widget, amely megmutatja a kosarat, a pénztár utáni felülvizsgálati képernyőt és a szállítási költség kalkulátort. Egy naiv rendszer, amely egyszerűen átadta a pénztár tételeit kellékként, megkockáztathatja a logika megkettőzését – minden egyes alkatrésznek ki kell dolgoznia a teljes rendelési értéket.
A HOC bemutatása
Nézzük meg, hogyan segíthet a HOC:
import React from "react"; import {connect} from "react-redux"; const withCheckout = ComponentToWrap => { const ComponentWithCheckout = class extends React.Component { render() { return ( <ComponentToWrap checkoutItems={this.props.checkout.items} checkoutTotal={this.total} {...this.props} /> ); } get total() { const prices = this.props.checkout.items.map(i => (i.quantity * i.price)); return prices.reduce((a, b) => (a + b), 0); } } return connect(({checkout}) => ({checkout}))(ComponentWithCheckout); } export default withCheckout;
A fájl egyetlen függvényt exportál, withCheckout
, amely a React komponenst veszi egyetlen paraméternek (ComponentToWrap
). A függvényen belül létrehozunk egy új névtelen osztályt, amely maga is React komponens.
Ez az új komponens render
metódus létrehozza a ComponentToWrap
átmentünk a függvénybe. Most lehetőségünk van meghatározni a példány kellékeit. A pénztár tételek tömböt továbbítjuk checkoutItems
és az előre kiszámított teljes értéket elérhetővé teszi checkoutTotal
.
A HOC-nak továbbított támaszokat továbbítják a belső alkatrészhez, biztosítva, hogy az az összes szükséges adatot megkapja. A függvény az újonnan létrehozott névtelen osztályt adja vissza, amely készen áll az egész alkalmazás megjelenítésére.
Használjuk a connect
a metódusa react-redux
így a checkout
a HOC-on belüli prop megkapja a checkout
kulcs a Redux üzletünk állapotában. Ez a megvalósítás részletei – a HOC fenntarthatja a saját állapotát, vagy elérhet más szolgáltatásokat az alkalmazáson belül.
A HOC használata
Itt az ideje, hogy használatba vegyük a HOC-t.
import React from "react"; import withCheckout from "./withCheckout.js"; class CheckoutReviewScreen extends React.Component { render() { return ( <h1>Checkout</h1> <h2>{this.props.checkoutTotal}</h2> ); } } export default withCheckout(CheckoutReviewScreen);
Feltételezzük, hogy withCheckout
A HOC mappába menti withCheckout.js
ugyanabban a könyvtárban, mint az új fizetési ellenőrző képernyő komponensünk. Azáltal, hogy becsomagoljuk az alkatrészt a miénkkel withCheckout
HOC, elérhetjük és megjeleníthetjük a teljes rendelési értéket. Nem kell magunknak kiszámítanunk, vagy az alkalmazás állapotában tárolnunk. Ha valaha is frissíteni akartuk a teljes összeg kiszámításának módját (például rögzített kezelési költség hozzáadásával), akkor csak egy helyen kell változtatnunk – a HOC-on belül.
Most már renderelhet <CheckoutReviewScreen />
bárhol az alkalmazásodban. A becsomagolt példánkat nem kell átadni semmilyen kelléknek, mivel az adatokat a Redux üzletünkből szerzi be. Mert be van csomagolva withCheckout
, maga burkolva a Redux-ékkel connect
, az ellenőrző képernyő automatikusan megkapja a checkoutTotal
prop, amely összegzi az összes elem árát az alkalmazás állapotában.
Most érdemes megemlíteni, hogyan neveztük el a HOC-t: withCheckout
. Megállapodás szerint a HOC neveknek általában a with
előtag, mert hozzáadnak valamit az általuk becsomagolt alkatrészekhez. Esetünkben a HOC kényelmes hozzáférést biztosít pénztárunk kosarához, amelyet egyébként minden egyes alkatrészen belül végrehajtanunk kellene.
A HOC előnyei
A HOC használatával elvonatkoztathatja az összetevőkből a gyakori viselkedéseket, minimalizálva a kódduplikációt és növelve a fenntarthatóságot. A HOC-k lehetővé teszik a függőség-injektálás egy formáját. Segítenek az összetevők egyszerűbb megőrzésében, mivel lehetővé teszik, hogy többet továbbítsanak a külvilágtól.
A HOC-k gyakoriak a React ökoszisztémán belül. Valójában láttunk egyet ebben a cikkben – connect()
, része react-redux
, amely feliratkozik a komponenseire a Redux állapotváltozásokra.
A HOC-k azért népszerűek, mert olyan kód-újrafelhasználási módszert kínálnak, amely nem rontja meg az összetevők önzárását. A minta kihasználja a React összetételét, hogy extra funkciókat csatolhasson mellékhatások veszélye nélkül.
Az alkalmazás bármelyik összetevőjét átadhatja withCheckout
anélkül, hogy bármit is eltörne – a HOC csak néhány extra támaszt rögzít. Ezért olyan fontos, hogy a HOC-k továbblépjenek összes az általuk kapott kellékek ({...this.props}
példánkban). Nem tehetnek semmit, ami zavarhatja a burkolt alkatrész normál működését.
Úgy érezheti, hogy az alkatrészei most függenek a HOC-tól. Ez nem így van. Exportálhatja az összetevő egy második verzióját, amely nincs becsomagolva, így a fogyasztók választhatnak, hogy melyiket használják.
Az Ön alkatrésze csak bizonyos ragaszkodásokhoz ragaszkodik – checkoutTotal
a mi esetünkben. Ezt megadhatja a HOC, vagy átadhat egy értéket, bárhol is jelenítjük meg az alkatrészt. A HOC egyszerűbbé teszi a fejlesztést, de alapvetően nem változtatta meg renderelt komponenseink jellegét.