Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pw:laboratoare:08 [2020/04/06 09:43]
valeriu.stanciu [2. Ce este JSX ?]
pw:laboratoare:08 [2021/04/25 22:35] (current)
alexandru.hogea [Exercitii]
Line 1: Line 1:
-===== Laboratorul 08: Intoducere in ReactJS ​=====+===== Laboratorul 08: React Hooks =====
  
-==== 1. Ce este Single Page Application (SPA)? ​==== +===== 1. React Hooks ===== 
-Un SPA sau aplicatie cu o singura paginaeste aplicatie (sau un website) care interactioneaza cu browserul web prin rescrierea dinamica, a DOM-ului current, cu date noi generate fie din client, fie din serverIn acest caz, browserul nu este nevoit sa incarce o pagina noua.+**[[https://​reactjs.org/​docs/​hooks-overview.html|Hooks]]** sunt noua adaugare in **React 16.8**. Va permit sa utilizati functiile de stare si alte functii Reactfara a scrie clasaAvantajul ​este mai putin cod scris pentru a obtine aceeasi functionalitate.
  
-==== 2Ce este JSX ? ==== +=== 1.1 useState() ​=== 
-Considerati urmatoarea linie +[[https://reactjs.org/​docs/​hooks-state.html|useState]] este un hook de React care va permite sa interactionati cu starea unei componente. Acesta va intoarce un vector format din 2 elemente: 
-{{ :pw:​laboratoare:​screenshot_1.png?​nolink ​|}}+  * Variabila de stare 
 +  * Functia care va modifica variabila de stare
  
-Aceasta sintaxa se numeste JSX, iar denumirea ​pornit de la Syntax Extension to JavaScript. Aceasta sintaxa este folosita in React pentru a descrie cum va arata o componenta. JSX se poate sa va duca cu gandul la HTML, diferenta este ca JSX vine si cu toate functionalitatile JavaScript.  +Functia **useState** primeste ca parametru valoarea initiala ​starii 
-In exemplul de mai jos, declaram o variabila nameiar ulterior o folosim in interiorul JSX fiind pusa intre paranteze acolade. +<code javascript>​ 
-{{ :​pw:​laboratoare:​screenshot_2.png?​nolink |}}+const [myStatemyFunctionToChangeState] = useState(initialValue);​ 
 +</​code>​
  
-De asemeneaputeti ​sa puneti orice cod JavaScript valid in interiorul parantezelor acolate in JSX. +<note tip>​Atentievaloarea initiala trebuie ​sa reflecte tipul de stare pe care vreti sa il retineti (string, numar, obiect, etc...)</​note>​ 
-{{ :​pw:​laboratoare:​screenshot_3.png?nolink |}}+<note tip>O componenta poate apela **useState** de mai multe ori, pentru a retine stari diferite</​note>​
  
-JSX poate sa fie folosit si in contextul unor expresii, precum +{{:​pw:​laboratoare:​mai_multe_stari.png?800|}}
-{{ :​pw:​laboratoare:​screenshot_4.png?nolink ​|}}+
  
-Tag-urile JSX pot contine si mai multi copii. +Acest exemplu reda un contorCand faceti clic pe buton, creste valoarea:
-{{ :pw:​laboratoare:​screenshot_5.png?​nolink |}}+
  
-De asemenea, putem folosi JSX pentru a ne proteja si de eventuale atacuri. +{{ :​pw:​laboratoare:​usestate_1.png?nolink |}}
-{{ :​pw:​laboratoare:​screenshot_6.png?nolink |}}+
  
-**JSX reprezinta obiecte.** +<note tip>​Observati cum valoarea initiala a starii este 0</​note>​
-Babel se ocupa de compilarea JSX in apeluri React.createElement() +
-{{ :​pw:​laboratoare:​screenshot_7.png?​nolink |}}+
  
-==== 3Ce este React ? ===+=== 1.2 useEffect() ​===
-React este o biblioteca JavaScript pentru construirea de interfete utilizator. Este creat si intretinut de Facebook si de o comunitate de dezvoltatori ( open source ) si desigur si de alte companii individuale.+
  
-==== 4. Crearea unei aplicatii React ==== +[[https://reactjs.org/docs/hooks-effect.html|useEffect]] este al doilea hook important din React si va permite propagarea **efectelor colaterale** din React - sau pe scurt, **efecte** - (de exemplu, modificarea DOM-ului, afisarea unor alerte, preluarea unor date, etc...).
-Pentru a putea folosi tool-ul oferit de Facebook, avem nevoie sa indeplinim urmatoarele conditii: ​[[https://nodejs.org/en| Node >= 8.10 si npm >= 5.6]].+
  
-Pentru a genera un proiect trebuie sa rulati urmatoarele:​ +Orice actiune care nu se poate efectua in timpul randarii (render), pentru ca poate modifica structura componentei,​ este considerat efect
-{{ :​pw:​laboratoare:​screenshot_8.png?nolink |}}+
  
-Dupa rularea script-ului //npm start// puteti accesa aplicatia accesand link-ul din consola +Pe vremuri, cand componentele functionale nu erau atat de folosite si inca se foloseau foarte mult componentele clasa, aceste efecte erau tratate in **ciclurile de viata** ale componentelor. Aceste cicluri de viata nu sunt nimic mai mult decat metode ale claselor de React. Amintim cateva: 
-<​code>​ +  * **componentDidMount** ​metoda care se executa dupa redarea initiala a componentei 
-http://​localhost:​3000 +  * **componentDidUpdate** ​metoda care se executa dupa ce state sau props au fost modificate 
-</​code>​ +  * **componentWillUnmount** - metoda care se executa inainte de stergerea componentei - adica este scoasa ​din DOM
-{{ :​pw:​laboratoare:​screenshot_9.png?​nolink |}}+
  
-==== 5. Componente ==== +{{ :​pw:​laboratoare:​react_events.png?​nolink&​700 |}}
-Componentele va permit sa va impartiti interfata utilizator in "​piese"​ reutilizabile,​ iar in acelasi timp va puteti gandi la fiecare piesa ca fiind izolata.+
  
-Conceptualcomponentele sunt asemanatoare cu functiile JavaScript. Acestea accepta intrari (denumite "​props"​) ​si returneaza elemente Reactcare descriu ceea ce ar trebui sa apara in interfata.+In principal**efectele** declarate folosind **useEffect** se realizeaza, prin analogie, in **componentDidMount**,​ **componentDidUpdate** ​si, daca este declarat un comportament specific si in **componentWillUnmount**.
  
-=== 5.1. Functional Components === +Mai jos aveti un exemplu ​de efect care schimba titlul paginii:
-Cea mai simpla cale de a defini o componenta este aceea de a scrie o functie JavaScript +
-{{ :​pw:​laboratoare:screenshot_10.png?​nolink |}}+
  
-Aceasta functie este o componenta valida React deoarece accepta un singur obiect "​props"​ (proprietati) cu date si returneaza un element React. Aceste componente poarta denumirea de **function components** deoarece ele reprezinta niste functii JavaScript.+{{ :​pw:​laboratoare:​useeffect_1.png?nolink |}}
  
-=== 5.2. Class Components === +Prin analogieasa s-ar fi scris folosind clase:
-De asemeneaputeti folosi si o [[https://​developer.mozilla.org/​en-US/​docs/​Web/​JavaScript/​Reference/​Classes | clasa ES6]] pentru a defini o componenta:​ +
-{{ :​pw:​laboratoare:screenshot_11.png?​nolink |}}+
  
-Cele doua componente definite mai sus, sunt echivalente din punct de vedere React.+{{:​pw:​laboratoare:​react_hook_clasa.png|}}
  
-=== 5.3 Adaugarea unei componente ​in DOM (Rendering a Component) === +<note tip> Observati cum logica este duplicata ​in **componentDidMount** si **componentDidUpdate**useEffect elimina aceasta duplicare</​note>​
-Pana acum, am intampinat elemente React care reprezentau tag-uri DOM, precum: +
-{{ :​pw:​laboratoare:​screenshot_12.png?nolink |}}+
  
-De asemenea, elementele pot reprezenta si componente definite ​de utilizator:​ +Exista cazuri cand doriti sa anulati un efect in momentul in care nu mai aveti nevoie ​de componenta sau cand proprietatile componentei se schimba. Acest proces se numeste **curatare**. In Reactul clasic, acest lucru era scris in metoda **componentWillUnmount**,​ sau in metoda **componentDidUpdate**. Pentru a face acest lucru in useEffect, este nevoie sa **returnati o functie**
-{{ :​pw:​laboratoare:​screenshot_13.png?nolink |}}+
  
-Cand React descopera un element care reprezinta o componenta definita de utilizatoracesta trimite atributele JSX si copiii catre aceasta ​componenta ​folosind un singur obiect. Acest obiect poarta numele ​de "​props"​.+Asadarce se intampla in corpul functiei useEffect se intampla **de fiecare data** cand componenta se randeaza (render) ​si ce se returneaza se executa **de fiecare data** cand componenta ​a terminat ​de executat render.
  
-In exemplul urmatorcodul "​randeaza"​in paginamesajul //Hello, Sara//. +De exemplusa presupunem ca avem un API de Chat care are doua metode: subscribe si unsubscribe. Aceste doua metode au doi parametriun id si o functie de callback care seteaza statusul pe online sau offline. Ne dorim sa dam subscribe la inceputul componentei si sa dam unsubscribeatunci cand parasim componenenta.
-{{ :​pw:​laboratoare:​screenshot_14.png?nolink |}}+
  
-Componentele create pot fi reutilizate de cate ori dorim. Spre exempluputem crea o componenta //App// care afiseaza //Welcome// de mai multe ori, folosind alt nume. +Folosind useEffectacest lucru se poate realiza foarte usor:
-{{ :​pw:​laboratoare:screenshot_15.png?​nolink |}}+
  
-=== 5.4 Stare ( State ) === +{{ :pw:​laboratoare:​useeffect_2.png?​nolink ​|}}
-[[https://reactjs.org/​docs/​state-and-lifecycle.html ​State]] reprezinta un obiect JavaScript care pastreaza informatia care influenteaza aspectul sau starea componentei compilate si randate. Diferenta fata de **props** este aceea ca starea este mentinuta in contextul componentei - similar cu definirea unei variabile in interioriul unei functii.+
  
 +Pe de alta parte, folosind clasa, codul ar fi aratat astfel:
  
-== 5.4.1 Functional Components == +{{:​pw:​laboratoare:​react_hook_clasa_2.png|}}
-{{ :​pw:​laboratoare:​state_functional.png?​nolink&​700 ​|}}+
  
-== 5.4.2 Class Components == +<note tip>​Observati cum ce este returnat in **useEffect** este scris in **componentWillUnmount** si ce este scris in corpul **useEffect** este scris in **componentDidMount**,​ asa cum am explicat anterior.</​note>​
-{{ :​pw:​laboratoare:​state_class.png?​nolink&​700 |}}+
  
-Cele doua componente prezentate mai sus sunt echivalente,​ insa exista o mica diferenta:+<note important>​Codul din ultima coza este un cod ce are bug. Ganditi-va la urmatorul cazcand **props** este modificat (adica atunci cand parintele ii trimite alta valoare pentru props), componenta **NU** va efectua unsubscribe,​ chiar daca id-ul s-a modificat. Acest lucru trebuie tratat tot in **componentDidMount**. useEffect elimina aceasta problema, executand codul la fiecare render.</​note>​
  
-Class Components fac referire la state sau props folosind ​**this**. +Asa ar fi trebuit sa arate codul corect, ​folosind ​clase:
-<​code>​ +
-Class components+
  
-this.state +{{:​pw:​laboratoare:​react_hook_clasa_3.png|}}
-this.props +
-</​code>​+
  
-<​code>​ +=== 1.3 useReducer() ===
-Functional Components+
  
-state +[[https://​reactjs.org/​docs/​hooks-reference.html#​usereducer |useReducer]],​ este o alternativa pentru useState(). Accepta un reducer de tip <​code>​(state, action) => newState</​code> ​si returneaza state-ul curent si functia dispatch. Dispatch, care primeste o actiune ca argument, declanseaza actualizarea state-ului in functie de actiunea folosita.
-props +
-</​code>​+
  
-=== 5.5 Event Handling === +Un reducer ​este o functie care primeste state-ul curent ​si o actiune si returneaza state-ul modificatactiunea fiind modalitatea prin care se precizeaza cum se va modifica state-ul. O actiune este un obiect care trebuie obligatoriu sa aiba un tip (**type**).
-Gestionarea evenimentelor cu elemente React este foarte asemanatoare cu gestionarea evenimentelor pe elemente DOM. Exista de asemenea ​si cateva diferente de sintaxaprecum:+
  
-HTML +Este recomandat sa fie folosit daca logica state-ului este mai complexa.
-{{ :​pw:​laboratoare:​screenshot_16.png?nolink |}}+
  
 +{{ :​pw:​laboratoare:​screenshot_2021-04-25_at_21.39.15.png?​nolink&​700 |}} 
  
-React 
-{{ :​pw:​laboratoare:​screenshot_17.png?​nolink |}} 
  
-HTML 
-{{ :​pw:​laboratoare:​screenshot_19.png?​nolink |}} 
  
-React +==== Exercitii ====
-{{ :​pw:​laboratoare:​screenshot_18.png?​nolink |}}+
  
-=== 5.6 Conditional Render === +Vom extinde aplicatia creata la laboratorul precedent.
-Randarea bazata pe conditii, in React, functioneaza in acelasi mod precum conditionarea in JavaScript. Folositi operatori JavaScript precum [[https://​developer.mozilla.org/​en-US/​docs/​Web/​JavaScript/​Reference/​Statements/​if...else |if]] sau [[https://​developer.mozilla.org/​en-US/​docs/​Web/​JavaScript/​Reference/​Operators/​Conditional_Operator |conditional operator]] pentru a crea elemente reprezentand starea curenta.+
  
-Considerati urmatoarele doua componente: +1. Folosind componentele App si Count, trimiteti valoarea counter-ului si functiile (incrementare,​ decrementare,​ reset) folosind props. Cand counter-ul ajunge 0, afisati o alerta. 
-{{ :​pw:​laboratoare:​screenshot_20.png?nolink |}}+<note important>​Componenta **Count** si **App** trebuie sa fie componente functionale. Pentru afisarea alertei va trebui sa folositi **useEffect()**. Valoarea lui count va fi definita drept state in App, la fel si functiile de incrementare,​ decrementare si reset.</​note>​
  
-Vom implementa o componenta //​Greeting//​ care afiseaza una dintre aceste componente, daca un utilizator este autentificat sau nu. +2. Modificati fisierele de css din extensia **.css** in **.scss**, daca nu ati folosit Sass in laboratorul trecut
-{{ :​pw:​laboratoare:​screenshot_21.png?nolink |}}+<note important>​ 
 +De asemenea, React permite modularizarea fisierelor SCSS prin denumirea acestora in **numeFisier.module.scss**. 
 +In acest caz, importarea si referentierea claselor css, se face in felul urmator:
  
-=== 5.7 Liste si chei (key) === 
-In primul rand, sa ne amintim cum transformam listele in JavaScript. 
-{{ :​pw:​laboratoare:​screenshot_22.png?​nolink |}} 
- 
-Acest cod afiseaza urmatorul rezultate in consola 
 <​code>​ <​code>​
-[2, 4, 6, 8, 10] +numeFisier.module.scss
-</​code>​+
  
-== Afisarea mai multor componente == +.container { 
-<​code>​ +  ​display:​ flex; 
-const numbers = [1, 2, 3, 4, 5]+  ​justify-content:​ space-between
-const listItems = numbers.map((number) => +  ​align-items:​ center; 
-  ​<​li>​{number}</​li>​ +  ​flex-direction:​ row; 
-)+  ​padding:​ 1rem 0
-</​code>​+  ​font-size:​ 1em; 
 +  font-weight:​ 700; 
 +  [...] 
 +}
  
-{{ :​pw:​laboratoare:​screenshot_23.png?nolink |}}+import styles from './​numeFisier.module.scss';​
  
-Cand rulam acest cod, in consola va fi afisat un mesaj de atentionare spunandu-ne ca pentru fiecare //li// (list item) trebuie sa furnizam o cheie unica. +<div className={styles.container}
-{{ :​pw:​laboratoare:​screenshot_24.png?nolink |}}+[...] 
 +</​div>​ 
 +</​code>​
  
-Pentru a rezolva aceasta problematrebuie sa introducem urmatoarea modificare:​ +In cazul in care doriti import-ul standardfara module, acesta va arata in felul urmator:
-{{ :​pw:​laboratoare:screenshot_25.png?​nolink |}}+
  
-Aceste **key**s (chei) ajuta React-ul la identificarea elementelor care s-au schimbat, adaugat si eliminat. Putem privi aceste chei precum identitatea unui element.+numeFisier.scss
  
-=== 5.8 Compozitie === +<​code>​ 
-React are un model puternic de compozitie si va recomandam sa folositi compozitia in loc de mostenire pentru a reutiliza codul intre componente+.container { 
 +  display: flex; 
 +  justify-content:​ space-between;​ 
 +  align-items:​ center; 
 +  flex-direction:​ row; 
 +  padding: 1rem 0; 
 +  font-size: 1em; 
 +  font-weight:​ 700; 
 +  [...] 
 +}
  
-Unele componente nu stiu din timp ce copii vor avea. Aceste componente sunt de obicei folosite cand ne definimi **Layout**-ul aplicatiei sau orice element care reprezinta o 'cutie' pentru elementele noastre.+import ​'./​numeFisier.scss';​
  
-Fiecare componenta React, are o proprietare rezervata in obiectul **props** numita **children**Aceasta proprietate poate fi accesata in felul urmator:+<div className="​container">​ 
 +[...] 
 +</​div>​ 
 +</​code>​
  
-<code> +</note>
-Class components+
  
-this.props.children +3Modificati counter-ul astfel incat sa nu mai afiseze un numar, ci sa afiseze o imagine de **counter** ori. Stilizarea interfetei poate urma design-ul de mai jos, folosind culorile alese si fontul, dar tematica poate fi schimbata dupa propriile idei (Puteti sa faceti o tema inspirata dintr-un film sau natura).
-</​code>​+
  
-<​code>​ +{{ :​pw:​laboratoare:​screenshot_2021-04-25_at_22.34.34.png?​nolink&​700 |}}
-Functional components+
  
-props.children 
-</​code>​ 
  
-{{ :​pw:​laboratoare:​screenshot_26.png?nolink |}} +{{ :​pw:​laboratoare:​screenshot_2021-04-25_at_22.29.40.png?nolink&​700 ​|}}
-{{ :​pw:​laboratoare:​screenshot_27.png?nolink |}}+
  
----- +4. Componenta ​Layout ​va trebui ​sa alcatuiasca toata interfata utilizator, folosind **Header**, **props.children** si **Footer**. 
- +        
-==== Exercitii ==== +
-  - Generati o aplicatie React folosind **create-react-app**. +
-  - Creati o componenta **Counter** care sa afiseze un numar si 3 butoane **Increment**,​ **Decrement** si **Reset**. +
-  - Adaugati functionalitatea necesara pentru a incrementa, decrementa si reseta starea componentei **Counter**. +
-  - Creati ​componente (Class sau Functional) **Header**, **Nav**, **Footer** si **Layout**. +
-  - Creati o sectiune in componenta **Layout** care sa reprezinte continutul afisat pe paginaiar in iteriorul acestui continut sa putem adauga copii folosind ​compozitia. +
-  - Adaugati ​**Header**, **Nav** si **Footer** ​in Layout pentru a defini structura paginii+
-  - Afisati componenta **Counter** in **Layout**ul pe care l-ati creat anterior.+
pw/laboratoare/08.1586155401.txt.gz · Last modified: 2020/04/06 09:43 by valeriu.stanciu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0