de Andrei Cacio

Cum să detectați un clic exterior cu React și Hooks

Cum sa detectati un clic exterior cu React si Hooks
Fotografie de Alex Block pe Unsplash

Ce înseamnă „clic extern”?

Vă puteți gândi la asta ca la „anti-buton”. Un clic extern este o modalitate de a ști dacă utilizatorul dă clic pe totul DAR pe o anumită componentă. Este posibil să fi văzut acest comportament atunci când deschideți un meniu drop-down sau o listă drop-down și faceți clic în afara acestuia pentru a-l închide.

Există tot felul de alte cazuri de utilizare pentru o astfel de caracteristică:

  • la închiderea listelor derulante
  • la închiderea ferestrelor modale
  • când treceți în și din modul de editare pentru elemente editabile
  • închidere
  • si multe altele…

Acum să vedem cum putem scrie o componentă React generică și reutilizabilă care va încorpora acest comportament.

Cum va arăta

Un flux fericit ar trebui să arate astfel:

Structura componentelor

Pentru ca această componentă să funcționeze, va trebui să atașăm un document de gestionare a evenimentelor de clic pe documentul însuși. Acest lucru ne va ajuta să detectăm când facem clic oriunde pe pagină. Apoi, va trebui să verificăm dacă ținta noastră făcută clic diferă de elementul nostru înfășurat. Deci, o structură de bază va arăta astfel:

Pentru primul exemplu, vom începe codificarea utilizând stilul React Class și apoi refactorizăm-o cu noua API Hooks.

Am implementat două funcții ale ciclului de viață:

  • componentDidMount (): va atașa ascultătorul de evenimente
  • componentWillUnmount (): va curăța gestionarul de clicuri înainte ca componenta să fie distrusă

și apoi redăm tot ceea ce înfășoară componentele. Pentru primul nostru exemplu de mai sus va reda .

Condiția „ClickOutside”

Acum trebuie să verificăm dacă utilizatorul dă clic în afara copilului înfășurat. unu naiv soluția este să comparăm elementul țintă (elementul pe care facem clic) cu nodul copilului nostru. Dar acest lucru va funcționa numai dacă avem un nod simplu (cu un singur nivel) în copilărie. Dacă copilul nostru înfășurat are mai multe subnoduri, atunci această soluție va eșua.

Din fericire există o metodă numită .contains () care ne spune dacă un nod este un copil al unui anumit nod. Următorul pas va fi accesul la nodul copilului nostru. Pentru a realiza acest lucru vom folosi React Refs.

Ref-urile sunt modalitatea React de a ne oferi acces la obiectul nod brut. De asemenea, vom utiliza API-ul Reacts pentru manipularea this.props.children componente. Avem nevoie de acest API, deoarece vom injecta referința creată copilului nostru împachetat. Având în vedere acest lucru, componenta noastră va arăta astfel:

Perfect, acest lucru ar trebui să funcționeze conform așteptărilor. Cel puțin pentru fluxul nostru fericit (un copil înfășurat). Dacă intenționăm să înfășurăm mai multe noduri, trebuie să facem câteva ajustări:

  • trebuie să avem o serie de referințe (la fel de mulți ca și copiii noștri înfășurați)
  • trebuie să folosim React.Children.map pentru a clona fiecare copil și a injecta ref-ul asociat din gama noastră privată de ref

Acest lucru ar trebui să fie bine. Acum, să refacem acest lucru folosind Hooks!

Cârlige

React 16.8 a introdus un nou API numit Cârlige. Cu Hooks putem scrie mai puțin cod și putem obține o amprentă mai mică pe baza noastră de cod. De asemenea, Hooks profită de funcții care sunt cetățeni de primă clasă în JavaScript. Dacă sunteți familiarizați cu componente funcționale fără stat în React ești la jumătatea drumului. Refactorul nostru inițial va arăta astfel:

Până în prezent, folosim în continuare „vechea” API React pentru a declara o componentă funcțională simplă fără stat. Cu toate acestea, avem încă nevoie de acele funcții ale ciclului de viață pentru a ne atașa handlerul la document nodul.

Iată unde Cârlig de efect cârligul Efect va înlocui „componentDidMount” și “componentWillUnmount”Metode. Cârligul de efecte va fi apelat imediat după redarea componentelor, astfel că ne va ajuta să atașăm la timp handlerul dorit. De asemenea, pentru partea de curățare, dacă cârligul de efecte returnează o funcție, această funcție va fi apelată chiar înainte ca componenta să fie demontată. Deci, este momentul potrivit pentru a face o curățare. În următorul refactor, lucrurile vor deveni puțin mai clare.

Aceasta este forma finală a componentei noastre funcționale folosind Cârligul de efecte. Dacă doriți să vedeți ambele exemple în acțiune, le puteți rula mai jos. (Puteți exporta implicit fie componenta Class, fie componenta funcțională, iar aplicația se va comporta la fel.)

Concluzie

Chiar dacă comportamentul clicului în exterior este o caracteristică utilizată pe scară largă, este posibil să nu fie atât de simplu de implementat în React. Cu acest exemplu, mi-am luat libertatea de a experimenta puțin cu React Hooks și de a construi soluția în două moduri de a compara cele două abordări. Sunt un mare fan al componentelor funcționale și acum, cu ajutorul Hooks, le putem duce la nivelul următor.