“Ce naiba sunt cârligele?”

M-am trezit întrebând la fel cum am crezut că am acoperit toate bazele React. Așa este viața unui dezvoltator frontend, jocul se schimbă mereu. Introduceți Hooks.

Este întotdeauna frumos să înveți ceva nou nu? Desigur! Dar uneori trebuie să ne întrebăm „De ce? Ce rost are acest lucru nou? Trebuie să-l învăț”?

Cu cârlige, răspunsul este „nu imediat”. Dacă ați învățat React și ați folosit până acum componente bazate pe clasă, nu vă grăbiți să vă deplasați la cârlige. Cârligele sunt opționale și pot funcționa în tandem cu componentele dvs. existente. Nu-l urăști atunci când trebuie să-ți rescrii întreaga bază de cod pentru a pune la cale un lucru nou?

Oricum, iată câteva motive pentru care cârligele au fost introduse în primul rând și de ce recomand începătorilor să le învețe.

Utilizarea stării în componentele funcționale

Înainte de cârlige, nu am putut folosi starea în componentele funcționale. Asta înseamnă că, dacă aveți o componentă funcțională bine elaborată și testată, care trebuie brusc să stocheze starea, sunteți blocat cu sarcina dureroasă de a refactura componenta funcțională într-o componentă de clasă.

Ura! Permiterea stării în cadrul componentelor funcționale înseamnă că nu trebuie să ne refactorizăm componentele de prezentare Consultați acest articol pentru mai multe.

Componentele clasei sunt greoaie

Să recunoaștem, componentele clasei vin cu o mulțime de cazane. Constructori, obligatorii, folosind „asta” peste tot. Utilizarea componentelor funcționale elimină mult din acest lucru, astfel încât codul nostru devine mai ușor de urmărit și de întreținut.

Puteți citi mai multe despre acest lucru pe documentele React:

Cod mai lizibil

Deoarece cârligele ne permit să folosim componente funcționale, înseamnă că există mai puțin cod în comparație cu componentele clasei. Acest lucru face ca codul nostru să fie mai ușor de citit. Ei bine, asta este ideea oricum.

Nu trebuie să ne facem griji cu privire la legarea funcțiilor noastre sau să ne amintim ce legătură are și „asta” și așa mai departe. Ne putem face griji dacă ne scriem codul.

Dacă abia începi cu React, am o grămadă de postări de început pe blogul meu care te-ar putea ajuta! Verifică-l aici:

React State Hook

Ah, stat. O piatră de temelie a ecosistemului React. Să ne umezim picioarele cu Hooks prin introducerea celui mai comun cârlig cu care veți lucra – useState().

Să aruncăm o privire la o componentă de clasă care are stare.


import React, { Component } from 'react';
import './styles.css';

class Counter extends Component {
	state = {
		count: this.props.initialValue,
	};

	setCount = () => {
		this.setState({ count: this.state.count + 1 });
	};

	render() {
		return (
			<div>
				<h2>This is a counter using a class</h2>
				<h1>{this.state.count}</h1>

				<button onClick={this.setCount}>Click to Increment</button>
			</div>
		);
	}
}

export default Counter;

Cu React Hooks, putem rescrie această componentă și putem elimina o mulțime de lucruri, facilitând înțelegerea:


import React, { useState } from 'react';

function CounterWithHooks(props) {
	const [count, setCount] = useState(props.initialValue);

	return (
		<div>
			<h2>This is a counter using hooks</h2>
			<h1>{count}</h1>
			<button onClick={() => setCount(count + 1)}>Click to Increment</button>
		</div>
	);
}

export default CounterWithHooks;

În față, există mai puțin cod, dar ce se întâmplă?

Sintaxa de reacție a stării

Așa că am văzut primul nostru cârlig! Ura!

 const [count, setCount] = useState();

Practic, aceasta folosește atribuirea de destructurare pentru tablouri. useState() funcția ne oferă 2 lucruri:

  • o variabilă pentru a păstra valoarea de stare, în acest caz, se numește counto funcție pentru a schimba valoarea, în acest caz, se numește setCount.

Puteți să le numiți oricum doriți:


const [myCount, setCount] = useState(0);

Și le puteți utiliza în tot codul, ca variabile / funcții normale:


function CounterWithHooks() {
	const [count, setCount] = useState();

	return (
		<div>
			<h2>This is a counter using hooks</h2>
			<h1>{count}</h1>
			<button onClick={() => setCount(count + 1)}>Click to Increment</button>
		</div>
	);
}

Observați useState cârlig în partea de sus. Declarăm / destructurăm 2 lucruri:

  • counter: o valoare care va deține valoarea noastră de stat
  • setCounter: o funcție care ne va schimba counter variabil

Pe măsură ce vom continua prin cod, veți vedea această linie:


<h1>{count}</h1>

Acesta este un exemplu al modului în care putem folosi o variabilă de cârlig de stare. În cadrul JSX-ului nostru, le plasăm pe count variabilă în {} să-l execute ca JavaScript și, la rândul său, count valoarea este redată pe pagină.

Comparând acest lucru cu vechiul mod „bazat pe clase” de utilizare a unei variabile de stare:


<h1>{this.state.count}</h1>

Veți observa că nu mai trebuie să ne facem griji cu privire la utilizare this, ceea ce ne face viața mult mai ușoară – de exemplu, editorul VS Code ne va da un avertisment dacă {count} nu este definit, permițându-ne să prindem erorile mai devreme. În timp ce nu va ști dacă {this.state.count} este nedefinit până când rulează codul.

Trecem la următoarea linie!


 <button onClick={() => setCount(count + 1)}>Click to Increment</button>

Aici, folosim setCount funcție (amintiți-vă că am destructurat / declarat acest lucru din useState() cârlig) pentru a schimba count variabil.

Când se face clic pe buton, actualizăm fișierul count variabilă după 1. Deoarece aceasta este o schimbare de stare, aceasta declanșează o redare și React actualizează vizualizarea cu noua count valoare pentru noi. Dulce!

Cum pot seta starea inițială?

Puteți seta starea inițială trecând un argument la useState() sintaxă. Aceasta poate fi o valoare codificată:


 const [count, setCount] = useState(0);

Sau poate fi luat din recuzită:


 const [count, setCount] = useState(props.initialValue);

Acest lucru ar stabili count valoare pentru orice props.initialValue este.

Asta rezumă useState(). Frumusețea este că puteți utiliza variabile de stare / funcții ca orice altă variabilă / funcție pe care ați scrie-o singur.

Cum pot gestiona mai multe variabile de stare?

Acesta este un alt lucru interesant despre cârlige. Putem avea câte ne place într-o componentă:


 const [count, setCount] = useState(props.initialValue);
 const [title, setTitle] = useState("This is my title");
 const [age, setAge] = useState(25);

După cum puteți vedea, avem 3 obiecte de stare separate. Dacă dorim să actualizăm vârsta, de exemplu, numim doar setAge () funcţie. La fel cu numara și titlu. Nu mai suntem legați de vechea cale componentă a clasei obraznice în care avem un obiect de stat masiv stocat folosind setState ():


this.setState({ count: props.initialValue, title: "This is my title", age: 25 })

Deci, ce zici de actualizarea lucrurilor atunci când recuzita sau starea se schimbă?

Când folosim cârlige și componente funcționale, nu mai avem acces la metode React de ciclul de viață, cum ar fi componentDidMount, componentDidUpdate, si asa mai departe. Aoleu! Nu vă panicați, prietenul meu, React ne-a dat un alt cârlig pe care îl putem folosi:

  • Tambur *

Introduceți useEffect!

Cârligul de efecte (useEffect ()) este locul în care punem „efecte secundare”.

Eh, efecte secundare? Ce? Să ieșim din circuit pentru un minut și să discutăm ce este efectul secundar. Acest lucru ne va ajuta să înțelegem ce useEffect() și de ce este util.

O explicație plictisitoare pentru computer ar fi.

„În programare, un efect secundar este atunci când o procedură schimbă o variabilă din afara domeniului său de aplicare”

În termenii React-y, acest lucru înseamnă „când variabilele sau starea unei componente se modifică pe baza unui lucru extern”. De exemplu, aceasta ar putea fi:

  • Când o componentă primește recuzită nouă care își schimbă starea
  • Când o componentă efectuează un apel API și face ceva cu răspunsul (de exemplu, schimbă starea)

Deci, de ce se numește efect secundar? Bine, nu putem fi siguri care va fi rezultatul acțiunii. Nu putem fi niciodată 100% siguri ce recuzită vom primi sau care ar fi răspunsul unui apel API. Și, nu putem fi siguri cum va afecta acest lucru componenta noastră.

Sigur că putem scrie cod pentru a valida și gestiona erorile și așa mai departe, dar în cele din urmă nu putem fi siguri care sunt efectele secundare ale acestor lucruri.

De exemplu, atunci când schimbăm starea, pe baza unora lucru exterior acest lucru este cunoscut ca un efect secundar.

Cu asta în afara drumului, să revenim la React și la useEffect Hook!

Când folosim componente funcționale, nu mai avem acces la metode ale ciclului de viață, cum ar fi componentDidMount(), componentDidUpdate() etc. Deci, efectiv (joc de cuvinte), cârligele useEffect înlocuiesc actualele cârlige React Life Cycle.

Să comparăm o componentă bazată pe clasă cu modul în care folosim cârligul useEffect:

import React, { Component } from 'react';

class App extends Component {
	componentDidMount() {
		console.log('I have just mounted!');
	}

	render() {
		return <div>Insert JSX here</div>;
	}
}

Și acum folosind useEffect ():

function App() {
	useEffect(() => {
		console.log('I have just mounted!');
	});

	return <div>Insert JSX here</div>;
}

Înainte de a continua, este important să știm că, în mod implicit, cârligul useEffect rulează pe fiecare redare și redare. Deci, ori de câte ori starea se modifică în componenta dvs. sau componenta dvs. primește elemente noi de recuzită, aceasta va fi redată și va face ca cârligul useEffect să ruleze din nou.

Rularea unui efect o dată (componentDidMount)

Deci, dacă cârligele rulează de fiecare dată când o componentă este redată, cum ne asigurăm că cârligul rulează o singură dată când componenta se montează? De exemplu, dacă o componentă preia date dintr-un API, nu dorim ca acest lucru să se întâmple de fiecare dată când componenta se redă!

useEffect() cârligul ia un al doilea parametru, o matrice, care conține lista lucrurilor care vor face să ruleze useEffect hook. Când este schimbat, acesta va declanșa cârligul de efect. Cheia pentru a rula un efect o dată este să treci într-o matrice goală:

useEffect(() => {
	console.log('This only runs once');
}, []);

Deci, acest lucru înseamnă că cârligul useEffect va rula pe primul rand, în mod normal. Cu toate acestea, atunci când componentele dvs. renderează, useEffect va gândi „bine, am rulat deja, nu există nimic în matrice, așa că nu va trebui să mai rulez. și pur și simplu nu face nimic.

În rezumat, matrice goală = useEffect cârligul rulează o dată pe montură

Utilizarea efectelor atunci când lucrurile se schimbă (componentDidUpdate)

Am prezentat cum să ne asigurăm că un useEffect hook rulează o singură dată, dar ce rămâne cu când componenta noastră primește un nou prop? Sau vrem să rulăm un cod când starea se schimbă? Cârligele ne lasă să facem și asta!

 useEffect(() => {
	console.log("The name props has changed!")
 }, [props.name]);

Observați cum transmitem lucruri matricei useEffect de data aceasta, și anume props.name.

În acest scenariu, cârligul useEffect va rula la prima încărcare ca întotdeauna. Ori de câte ori componenta dvs. primește un nou nume prop de la părintele său, cârligul useEffect va fi declanșat și codul din acesta va rula.

Putem face același lucru cu variabilele de stare:

const [name, setName] = useState("Chris");

 useEffect(() => {
    console.log("The name state variable has changed!");
 }, [name]);

Ori de câte ori name modificări variabile, rerenderele componente și cârligul useEffect vor rula și vor emite mesajul. Deoarece aceasta este o matrice, îi putem adăuga mai multe lucruri:

const [name, setName] = useState("Chris");

 useEffect(() => {
    console.log("Something has changed!");
 }, [name, props.name]);

De data aceasta, când name modificări ale variabilei de stare sau name prop modificări, cârligul useEffect va rula și va afișa mesajul consolei.

Putem folosi componentWillUnmount ()?

Pentru a rula un cârlig pe măsură ce componenta este pe punctul de a demonta, trebuie doar să returnăm o funcție din useEffect cârlig:

useEffect(() => {
	console.log('running effect');

	return () => {
		console.log('unmounting');
	};
});

Pot folosi diferite cârlige împreună?

Da! Puteți utiliza oricâte cârlige doriți într-o componentă și puteți amesteca și potrivi după cum doriți:

function App = () => {
	const [name, setName] = useState();
	const [age, setAge] = useState();

	useEffect(()=>{
		console.log("component has changed");
	}, [name, age])

	return(
		<div>Some jsx here...<div>
	)
}

Concluzie – Ce urmează?

Iată-l. Cârligele ne permit să folosim funcții JavaScript de modă veche pentru a crea componente React mai simple și pentru a reduce o mulțime de coduri.

Acum, fugiți în lumea cârligelor Reac și încercați să construiți singuri lucruri! Vorbind singur de lucruri de construit …