React: Cross-cutting concerns (šķērsojošā koda problēmas) skaidrojums

 

Cross-cutting concerns ir funkcionalitāte vai uzvedība, kas ietver vairākas komponentes lietojumprogrammā. Piemēri cross-cutting concerns ietver:

  • autentifikāciju,
  • žurnālēšanu,
  • kļūdu apstrādi un
  • datu iegūšanu.

Cross-cutting concerns apstrāde React var būt nedaudz izaicinoša, jo šīs problēmas bieži vien ietver vairākas komponentes, padarot kodu pārvaldību modulārā un uzturamā veidā apgrūtinošu.

Viena no pieejām cross-cutting concerns apstrādei React ir izmantot augstākās kārtas komponentus (*HOC). Augstākās kārtas komponents ir funkcija, kas ņem komponentu kā argumentu un atgriež jaunu komponentu ar papildu funkcionalitāti.

Cita pieeja cross-cutting concerns apstrādei React ir izmantot kontekstu. Konteksts nodrošina veidu, kā dalīties ar datiem starp komponentiem, neizmantojot propus manuāli caur katru komponentu koka līmeni. Tas var būt noderīgi cross-cutting concerns kā autentifikācija, tēma un lokalizācija.

Tas var ietekmēt React programmēšanas pieredzi, jo tas var prasīt papildu plānošanu un kodēšanu, lai pareizi apstrādātu šīs problēmas.

Piemērs:

Lūk, piemērs, kā varētu izskatīties React aplikācija, kas izmanto augstākās kārtas komponentu (HOC), lai apstrādātu autentifikācijas cross-cutting concern:

import React, { useState, useEffect } from 'react';

const withAuth = WrappedComponent => {
  return props => {
    const [isAuthenticated, setIsAuthenticated] = useState(false);

    useEffect(() => {
      const checkAuth = async () => {
        const response = await fetch('/api/check-auth');
        if (response.ok) {
          setIsAuthenticated(true);
        }
      };
      checkAuth();
    }, []);

    if (!isAuthenticated) {
      return <div>Lūdzu, piesakieties, lai skatītu šo lapu.</div>;
    }

    return <WrappedComponent {...props} />;
  };
};

function MyComponent(props) {
  return <div>Laipni lūdzam Manā komponentē</div>;
}

const AuthComponent = withAuth(MyComponent);

function App() {
  return <AuthComponent />;
}

export default App;

Šajā piemērā withAuth ir HOC, kas ņem MyComponent kā argumentu un atgriež jaunu komponentu. Ja lietotājs nav autentificēts, tiek parādīts ziņojums, lūdzot lietotājam pieslēgties. Ja lietotājs ir autentificēts, tiek parādīts oriģinālais komponents.

Šis piemērs parāda vienu no veidiem, kā var apstrādāt cross-cutting concerns React.

 

Iedziļināsimies, lai ilustrētu dažas no paraugprakses un brīdinājumiem saistībā ar HOC.

Tie ietver komponenta mutāciju nekad HOC iekšienē, nesaistītu rekvizītu nodošanu iesaiņotajam komponentam un komponējamības palielināšanu, izmantojot komponentu => komponenta parakstu, jeb Component => Component signature.

 

Nepārveidojiet oriģinālo komponentu, jeb neveiciet oriģinālā komponenta mutācijas!

Viens no iespējamiem kārdinājumiem ir modificēt komponentu, kas tiek sniegts kā arguments, vai, citiem vārdiem sakot, mutēt to. Tas ir tāpēc, ka JavaScript ļauj veikt šādas darbības, un dažos gadījumos tas šķiet visvienkāršākais un ātrākais ceļš. Atcerieties, ka React veicina nemainīgumu visos scenārijos. Tā vietā izmantojiet kompozīciju un pārvērtiet HOC par tīru funkciju, kas nemaina saņemto argumentu, vienmēr atgriežot jaunu komponentu.

const HOC = (IepakotsKomponents) => {
  // ŠĀDI NEDARIET un neveidojiet mutācijas!
  IepakotsKomponents = () => {
   
  }; 
 …
}

Nododiet nesaistītus rekvizītus iesaiņotajam komponentam

HOC pievieno komponentam funkcijas. Citiem vārdiem sakot, tas to uzlabo. Tāpēc viņiem nevajadzētu krasi mainīt savu sākotnējo līgumu. Tā vietā sagaidāms, ka komponentam, kas atgriezts no HOC, būs līdzīga saskarne ar iesaiņoto komponentu.

HOC ir jāizplatās un jāiziet cauri visiem piederumiem, kas nav saistīti ar to īpašajām problēmām, palīdzot nodrošināt, ka HOC ir pēc iespējas elastīgāki un atkārtoti lietojami, kā parādīts tālāk esošajā piemērā.

 

const arPelesPozīciju = (IepakotsKomponents) => {
    const injicētsProp = {pelesPozīcija: {x: 10, y: 10}};
 
    return (oriģinālsProps) => {
      return <IepakotsKomponents injicētsProp={injicētsProp} {...oriģinālsProps} />;
    };
  };

Maksimāli palieliniet kompozīciju

Līdz šim esat uzzinājis, ka HOC primārais paraksts ir funkcija, kas pieņem React komponentu un atgriež jaunu komponentu.

Dažreiz HOC var pieņemt papildu argumentus, kas darbojas kā papildu konfigurācija, kas nosaka komponenta saņemtā uzlabojuma veidu.

const PaplašinātsKomponents = HOC(IepakotsKomponents, config)

Visizplatītākais HOC paraksts izmanto funkcionālu programmēšanas modeli, ko sauc par “currying” , lai maksimāli palielinātu funkciju sastāvu. Šis paraksts tiek plaši izmantots React bibliotēkās, piemēram, React Redux, kas ir populāra bibliotēka statusa pārvaldīšanai React lietojumprogrammās.

const PaplašinātsKomponents = connect(selector, actions)(IepakotsKomponents);

Sākotnēji šī sintakse var šķist dīvaina, taču, ja notiekošo sadalītu atsevišķi, to būtu vieglāk saprast.

const HOC = connect(selector, actions);
const PaplašinātsKomponents = HOC(IepakotsKomponents);

connect ir funkcija, kas atgriež augstākas kārtas komponentu, sniedzot vērtīgu īpašību vairāku HOC sastādīšanai kopā.

Viena argumenta HOC, piemēram, tiem, kurus esat izpētījis līdz šim, vai tam, ko atgriezusi connect funkcija, ir kā paraksts  Komponents => Komponents “Component => Component”. Izrādās, ka funkcijas, kuru izvades veids ir tāds pats kā ievades veids, ir patiešām viegli salikt kopā.

const paplašināt = compose(
    // Šie abi ir vientuļie HOCs komponenti
    arPelesPozīciju,
    arURLLokāciju,
    connect(selector)
  );
 
  // Paplašināts HOC
  const PaplasinātsKomponents = enhance(IepakotsKomponents);

Daudzas trešo pušu bibliotēkas jau nodrošina rakstīšanas utilīta ieviešanu, piemēram, lodash, Redux un Ramda. Tās paraksts ir šāds:

compose(f, g, h) ir tāds pats kā (...args) => f(g(h(...args)))

Brīdinājumi

Augstākas kārtas komponentiem ir daži brīdinājumi, kas nav uzreiz pamanāmi.

Neizmantojiet HOC citos komponentos: vienmēr izveidojiet savus uzlabotos komponentus ārpus jebkura komponenta darbības jomas. Pretējā gadījumā, ja to darāt citu komponentu pamattekstā un notiek atkārtota renderēšana, uzlabotais komponents būs atšķirīgs. Tas liek React to atkārtoti uzstādīt, nevis vienkārši atjaunināt. Rezultātā komponents un tā bērni zaudētu savu iepriekšējo stāvokli.

const Component = (props) => {
    // Šis ir nepareizi, nekad tā nedariet
    const PaplašinātsKomponents = HOC(IepakotsKomponents);
    return <PaplašinātsKomponents />;
  };
 
  // Šis ir pareizais veids
  const PaplašinātsKomponents = HOC(IepakotsKomponents);
  const Component = (props) => {
    return <PaplašinātsKomponents />;
  };

Atsauces netiek nodotas: tā kā React atsauces nav rekvizīti, React tos īpaši apstrādā. Ja pievienojat atsauci elementam, kura komponents ir HOC rezultāts, atsauce attiecas uz visattālākā konteinera komponenta gadījumu, nevis uz iesaiņoto komponentu. Lai to atrisinātu, varat izmantot React.forwardRef API. Vairāk par šo API un tās lietošanas gadījumiem varat uzzināt Higher Order Components from the official React docs. 

Secinājums

Rezumējot, jūs esat detalizētāk izskatījis augstākas pakāpes komponentus. Galvenais, ko var izmantot, nekad nav mutācijas HOC iekšpusē un nesaistītu rekvizītu nodošana jūsu iesaiņotajam komponentam.

Jūs arī uzzinājāt, kā palielināt kompozīciju, izmantojot komponentu => komponenta parakstu, un pievērsāt uzmanību dažiem brīdinājumiem par HOC.

* HOC ir saīsinājums no “Higher-Order Component” jeb “Augstākās kārtas komponents” latviski. Tas ir funkcija, kas ņem komponentu kā argumentu un atgriež jaunu komponentu ar papildu funkcionalitāti. HOC var palīdzēt apstrādāt cross-cutting concerns React, jo tas ļauj izveidot modulāru un uzturamu kodu .

Loading

Noderīgs raksts? Dalies ar citiem: