Differences

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

Link to this comparison view

pw:laboratoare:07 [2021/04/18 14:17]
alexandru.hogea [6.2 Variabile, functii, nesting]
pw:laboratoare:07 [2022/05/13 21:01] (current)
alexandru.hogea [Formulare]
Line 1: Line 1:
-====== Laboratorul 07: Introducere in ReactJS ​======+====== Laboratorul 07: Integrare Frontend-Backend ​======
  
-===== 1. Ce este Single Page Application (SPA)? ​===== +===== Scopul laboratorului ​===== 
-Un SPA sau o aplicatie ​cu o singura pagina, este o aplicatie ​(sau un website) care interactioneaza cu browserul web prin rescrierea dinamicaa DOM-ului current, cu date noi generate fie din client, fie din server. In acest caz, browserul nu este nevoit sa incarce o pagina noua.+Acest laborator reprezinta integrarea frontend-ului ​cu backend-ul creat pentru aceasta ​aplicatie. Vom introduce ​un pachet important, cel pentru axios[[https://​axios-http.com/​docs/​intro|Axios]], cu care vom putea face aceasta integrare.
  
-===== 2. Ce este JSX ? ===== +===== Ce veti invata la acest laborator? ===== 
-Considerati urmatoarea linie +Cum sa interactionati cu un server, cum sa folositi Axios pentru a face cereri si cum sa manipulam raspunsul.
-{{ :​pw:​laboratoare:​screenshot_1.png?nolink |}}+
  
-Aceasta sintaxa se numeste JSX, iar denumirea a 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.  +===== Inainte ​de integrarea frontend-backend ===== 
-In exemplul de mai jos, declaram o variabila name, iar ulterior o folosim in interiorul JSX fiind pusa intre paranteze acolade. +==== Actualizarea formularelor ==== 
-{{ :pw:​laboratoare:​screenshot_2.png?​nolink ​|}}+<note important>​Au fost actualizate formularele astfel incat sa foloseasca biblioteca[[https://​react-hook-form.com/|react-hook-form]]. Aceasta biblioteca ne scuteste de gestionarea fiecarui input din cadrul formularelor.</​note>​
  
-De asemenea, ​puteti ​sa puneti orice cod JavaScript valid in interiorul parantezelor acolade in JSX. +Mai jos puteti ​vedea un exemplu din documentatia celor de la react-hook-formCel mai important feature este **register** care paseaza urmatoarele proprietati fiecarui input: 
-{{ :pw:​laboratoare:​screenshot_3.png?​nolink |}}+  * onChange 
 +  * name 
 +  * onBlur 
 +  * ref
  
-JSX poate sa fie folosit si in contextul unor expresiiprecum +Prin aceste proprietatise vor actualiza campurile, valorile finale fiind returnate de **getValues()**. 
-{{ :​pw:​laboratoare:​screenshot_4.png?​nolink |}}+<​code>​ 
 +import React from "​react";​ 
 +import ​useForm ​from "​react-hook-form";​
  
-Tag-urile JSX pot contine si mai multi copii. +export default function App() { 
-{{ :​pw:​laboratoare:​screenshot_5.png?​nolink |}}+  ​const ​register, handleSubmit,​ watch, formState: ​errors ​} } = useForm();​ 
 +  const onSubmit = data => console.log(data);​
  
-De asemenea, putem folosi JSX pentru a ne proteja si de eventuale atacuri. +  console.log(watch("​example"​));​ // watch input value by passing the name of it
-{{ :​pw:​laboratoare:​screenshot_6.png?​nolink |}}+
  
-**JSX reprezinta obiecte.** +  return ( 
-Babel se ocupa de compilarea JSX in apeluri React.createElement() +    /"​handleSubmit"​ will validate your inputs before invoking "​onSubmit" ​*/ 
-{{ :​pw:​laboratoare:​screenshot_7.png?​nolink |}+    <​form onSubmit={handleSubmit(onSubmit)}> 
- +      {/* register your input into the hook by invoking the "​register"​ function */
-===== 3Ce este React ? ===== +      <​input defaultValue="​test"​ {...register("​example"​)} /> 
-React este o biblioteca JavaScript pentru construirea de interfete utilizatorEste creat si intretinut de Facebook si de o comunitate de dezvoltatori ​open source ​si desigur si de alte companii individuale. +       
- +      {/* include validation with required or other standard HTML validation rules */
-===== 4. Crearea unei aplicatii React ===== +      <input {...register("​exampleRequired",​ { requiredtrue })} /> 
-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]]. +      {/* errors will return when field validation fails  */} 
- +      ​{errors.exampleRequired && <​span>​This field is required</​span>​
-Pentru a genera un proiect trebuie sa rulati urmatoarele+       
-{{ :​pw:​laboratoare:​screenshot_8.png?nolink |}+      <​input type="​submit" ​/> 
- +    </form
-Dupa rularea script-ului ​//npm start// puteti accesa aplicatia accesand link-ul din consola +  ); 
-<code+}
-http://​localhost:​3000+
 </​code>​ </​code>​
-{{ :​pw:​laboratoare:​screenshot_9.png?​nolink |}} 
  
-===== 5. Componente ===== +<​note>​Desi pentru aceasta aplicatie nu am pus mesajele de eroare, ​va recomandam ​sa aveti intotdeauna un raspuns pe care sa il dati utilizatorilor care nu completeaza corect. Greselile facute de oameni ​in interactiunea cu un program nu sunt 'human error'sunt bad design.</​note>​
-Componentele ​va permit ​sa va impartiti interfata utilizator ​in "​piese"​ reutilizabileiar in acelasi timp va puteti gandi la fiecare piesa ca fiind izolata.+
  
-Conceptual, componentele sunt asemanatoare cu functiile JavaScriptAcestea accepta intrari (denumite "​props"​) si returneaza elemente React, care descriu ceea ce ar trebui sa apara in interfata.+===== Ce este Axios? ===== 
 +Axios este un client HTTP pentru node.js sau pentru browserCu ajutorul acestuia putem sa: 
 +  * interceptam cererea sau raspunsul 
 +  * transformam datele cererii sau al raspunsului 
 +  * anulam cereri 
 +  * transformam automat raspunsul pentru format JSON
  
-==== 5.1. Functional Components ==== 
-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. +===== Configurarile necesare ​===== 
- +==== 1. Instalare Axios ====
-==== 5.2. Class Components ​==== +
-De asemenea, puteti 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. +
- +
-==== 5.3 Adaugarea unei componente in DOM (Rendering a Component) ​==== +
-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:​ +
-{{ :​pw:​laboratoare:​screenshot_13.png?​nolink |}} +
- +
-Cand React descopera un element care reprezinta o componenta definita de utilizator, acesta trimite atributele JSX si copiii catre aceasta componenta folosind un singur obiect. Acest obiect poarta numele de "​props"​. +
- +
-In exemplul urmator, codul "​randeaza",​ in pagina, mesajul //Hello, Sara//. +
-{{ :​pw:​laboratoare:​screenshot_14.png?​nolink |}} +
- +
-Componentele create pot fi reutilizate de cate ori dorim. Spre exemplu, putem crea o componenta //App// care afiseaza //Welcome// de mai multe ori, folosind alt nume. +
-{{ :​pw:​laboratoare:​screenshot_15.png?​nolink |}} +
- +
-==== 5.4 Stare ( State ) ==== +
-[[https://​reactjs.org/​docs/​state-and-lifecycle.html | State]] reprezinta un obiect JavaScript care pastreaza informatia influentand 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. +
- +
- +
-=== 5.4.Functional Components === +
-In cazul componentelor functionale,​ o variabila de stare este declarata cu ajutorul useState ([[https://​reactjs.org/​docs/​hooks-state.html |React Hooks]]). O variabila de stare poate lua mai multe forme: string, numar sau obiect. Functia useState primeste ca paramentru valoarea initiala pe care vrem sa o atribuim variabilei si returneaza variabila de stare impreuna cu functia de actualizare,​ similara cu this.setState din componentele de tip clasa. +
- +
-{{ :​pw:​laboratoare:​state_functional.png?​nolink&​700 |}} +
- +
-=== 5.4.2 Class Components ​=== +
-{{ :​pw:​laboratoare:​state_class.png?​nolink&​700 |}} +
- +
-Cele doua componente prezentate mai sus sunt echivalente,​ insa exista o mica diferenta:​ +
- +
-Class Components fac referire la state sau props folosind **this**.+
 <​code>​ <​code>​
-Class components +npm install axios
- +
-this.state +
-this.props+
 </​code>​ </​code>​
 +==== 2. Fisier de configurare rute ====
 +Pentru a avea toate informatiile intr-un loc, vom crea un fisier in care sa tinem toate rutele.
  
 +<​note>​Daca am avea undeva hostat serverul, pur si simplu am inlocui base in acest fisier, in loc sa inlocuim oriunde folosim axios.</​note>​
 +<​note>​Am grupat rutele in functie de functionalitati,​ va recomandam sa tineti informatiile statice sub o forma cat mai ordonata.</​note>​
 <​code>​ <​code>​
-Functional Components+const base = "​https://​localhost:​7002/​api/​v1/";​ 
 +const routes = { 
 +    books: { 
 +        addBook: "​Books/​addBook",​ 
 +        getAll: "​Books/​viewAllBooks",​ 
 +        getBook: (id) => `Books/​viewStatusAboutBook/​${id}`,​ 
 +        deleteBook: (id) => `Books/​deleteBook/​${id}`,​ 
 +    }, 
 +    metrics: { 
 +        getBook: (id) => `Metrics/​metricsAboutBook/​${id}`,​ 
 +    }, 
 +    rentals: { 
 +        rentBook: "​Rentals/​rentBook",​ 
 +        myRentals: "​Rentals/​viewMyRentals",​ 
 +        returnBook: (id) => `Rentals/​returnBook/​${id}`,​ 
 +    }, 
 +    profile: { 
 +        setupProfile:​ "​Profiles/​registerProfile",​ 
 +        getProfile: "​Profiles/​viewProfile",​ 
 +    }, 
 +};
  
-state +export { base, routes };
-props+
 </​code>​ </​code>​
- +==== 3Configurare instanta Axios ==== 
-==== 5.5 Event Handling ​==== +De ce o [[https://axios-http.com/docs/instance|instanta]] de Axios? Pentru ca in diferite cazuri avem nevoie de o configurare mai specifica pentru interactiunea cu backend-ul. De asemenea, aceasta instanta ne ajuta pentru a folosi ​[[https://axios-http.com/docs/interceptors|interceptori]].  
-Gestionarea evenimentelor cu elemente React este foarte asemanatoare cu gestionarea evenimentelor pe elemente DOM. Totusi, exista cateva ​ diferente de sintaxa: +<note tip> 
-  * evenimentele din React sunt camelCase +Interceptorii ne pot ajuta in 2 moduri
-  * pentru gestionarea evenimentelor in React sunt folosite functii, nu string-uri +  - Daca vrem sa modificam orice cerere inainte sa o trimitem (exsa atasam un header in plus) 
- +  - Daca vrem sa gestionam datele primite de la server 
-HTML +</note> 
-{{ :​pw:​laboratoare:​screenshot_16.png?​nolink |}} +In cazul nostrunu a trebuit ​sa folosim interceptori.
- +
- +
-React +
-{{ :​pw:​laboratoare:​screenshot_17.png?​nolink |}} +
- +
-HTML +
-{{ :​pw:​laboratoare:​screenshot_19.png?​nolink |}} +
- +
-React +
-{{ :​pw:​laboratoare:​screenshot_18.png?​nolink |}} +
- +
-==== 5.6 Conditional Render ==== +
-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+
-{{ :pw:​laboratoare:​screenshot_20.png?​nolink |}} +
- +
-Vom implementa o componenta ​//Greeting// care afiseaza una dintre aceste componente, daca un utilizator este autentificat sau nu. +
-{{ :​pw:​laboratoare:​screenshot_21.png?​nolink |}} +
- +
-==== 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 rezultat in consola+
 <​code>​ <​code>​
-[2, 4, 6, 8, 10] +import axios from "​axios";​ 
-</code>+import { base } from "./Api";
  
-=== Afisarea mai multor componente === +const axiosInstance ​axios.create({ 
-<​code>​ +    ​baseURL:​ base, 
-const numbers = [12, 3, 4, 5]; +    ​timeout:​ 1000
-const listItems = numbers.map((number) => +});
-  <​li>​{number}</​li>​ +
-); +
-</​code>​+
  
-{{ :​pw:​laboratoare:​screenshot_23.png?​nolink |}} +export default axiosInstance;​
- +
-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. +
-{{ :​pw:​laboratoare:​screenshot_24.png?​nolink |}} +
- +
-Pentru a rezolva aceasta problema, trebuie sa introducem urmatoarea modificare:​ +
-{{ :​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. +
- +
-==== 5.8 Compozitie ==== +
-React are un model puternic de compozitie si va recomandam sa folositi compozitia in loc de mostenire pentru a reutiliza codul intre componente +
- +
-Unele componente nu stiu din timp ce copii vor avea. Aceste componente sunt de obicei folosite cand ne definini **Layout**-ul aplicatiei sau orice element care reprezinta o '​cutie'​ pentru elementele noastre. +
- +
-Fiecare componenta React, are o proprietare rezervata in obiectul **props** numita **children**. Aceasta proprietate poate fi accesata in felul urmator: +
- +
-<​code>​ +
-Class components +
- +
-this.props.children+
 </​code>​ </​code>​
 +==== 4. Folosirea instantei pentru a face cereri ====
 +<​note>​Cele mai folosite tipuri de cereri folosite sunt: GET, POST, PUT si DELETE. GET este folosit pentru a cere resurse, POST pentru crearea unei resurse, PUT pentru actualizarea unei resurse deja existente, iar DELETE, precum ii zice si numele, va sterge o resursa.</​note>​
 +Mai jos puteti gasi doua exemple de functii care fac doua cereri: una de tip GET - pentru a cere toate cartile si una de tip POST - pentru a adauga o carte. Primul pas in ambele este de a prelua **access token-ul** provenit de la auth0. Aceasta actiune o facem folosind functia getAccessTokenSilently() pe care auth0 ne-o ofera. Al doilea pas este sa folosim instanta noastra de axios pentru a cere datele respective sau pentru a adauga resursa. In final, pentru a citi raspunsul cererii, vom folosi **then** pentru a actualiza lista de carti.
  
 +<note tip>​Pentru '​prinderea'​ erorilor puteti folosi **catch**. </​note>​
 <​code>​ <​code>​
-Functional components+  const getAllBooks = useCallback(async () => { 
 +    const accessToken = await getAccessTokenSilently();​ 
 +    axiosInstance 
 +      .get(routes.books.getAll,​ { 
 +        headers: { 
 +          Authorization:​ `Bearer ${accessToken}`,​ 
 +        }, 
 +      }) 
 +      .then(({ data }) => setBooks(data));​ 
 +  }, [getAccessTokenSilently]);​
  
-props.children+  const handleAddBook = (form) => { 
 +    (async () => { 
 +      const accessToken = await getAccessTokenSilently();​ 
 +      axiosInstance 
 +        ​.post(routes.books.addBook,​ form, { 
 +          headers: { 
 +            Authorization:​ `Bearer ${accessToken}`,​ 
 +          }, 
 +        }) 
 +        .then(() => getAllBooks());​ 
 +    })(); 
 +  };
 </​code>​ </​code>​
  
-{{ :​pw:​laboratoare:​screenshot_26.png?​nolink |}} +<note tip>Daca vrem sa primim toate cartile ​de fiecare data cand componenta noastra Books se va randaatunci vom folosi ​**useEffect**.</​note>​
-{{ :​pw:​laboratoare:​screenshot_27.png?​nolink |}} +
- +
- +
-===== 6. Sass (Syntactically Awesome Style Sheets) ===== +
- +
-==== 6.1 Ce este Sass si de ce este util? ==== +
- +
-Stilizarea unei pagini web poate sa devina obositoare scriind aceleasi linii de cod (culori, layout, font, pozitie), mai ales cand vrem sa schimbam tema.[[https://​sass-lang.com/​guide|Sass]]pre-procesor CSS, vine in ajutorul nostru, oferindu-ne posibilitatea folosirii de variabile, mixins sau nesting. +
- +
-==== 6.2 Variabile, mixins, nesting ==== +
-**Exemplu folosire variabile** +
 <​code>​ <​code>​
-$font-stack: ​   Helvetica, sans-serif;​ +  useEffect(() => 
-$primary-color:​ #333; +    ​getAllBooks()
- +  ​}, [getAllBooks]);
-body +
-  font: 100% $font-stack+
-  ​color: $primary-color; +
-}+
 </​code>​ </​code>​
  
-**Exemplu folosire nesting** +Un exemplu de cerere de tip DELETE o avem pentru stergerea unei resurse (carti):
 <​code>​ <​code>​
-nav { +  const handleDelete = () => 
-  ul +    ​**confirmare stergere resursa** 
-    ​margin: 0; +    ​axiosInstance 
-    ​padding: 0; +      ​.delete(routes.books.deleteBook(id)) 
-    ​list-style:​ none+      .then(() => navigate("/​books"​))
-  } +  };
- +
-  li { display: inline-block+
- +
-  a { +
-    display: block; +
-    padding: 6px 12px; +
-    text-decoration:​ none; +
-  } +
-}+
 </​code>​ </​code>​
  
-**Exemplu folosire mixins** +<note tip>Inainte de stergerea resursei, utilizatorul ar trebui cumva anuntat de actiunea acestuia, in caz ca a apasat din greseala. Acest lucru se poate face printr-un pop-up in care sa confirme stergerea.</note
- +Putem observa ca functia este asemanatoare,​ avem instanta ​de axios care va face o cerere ​de tip **delete** ​si daca cererea a fost efectuata cu successe va naviga pe pagina cu toate cartile.
-<code> +
-@mixin transform($property) { +
-  ​-webkit-transform: $property;​ +
-  -ms-transform:​ $property;​ +
-  transform: $property;​ +
-+
-.box {  +
-  @include transform(rotate(30deg));​  +
-+
-</code+
- +
----- +
- +
-===== Exercitii ===== +
-{{ :​pw:​laboratoare:​lab_2_-_counter_-_width.png?​nolink&​750 |}} +
-{{ :​pw:​laboratoare:​lab2_-_brief.png?​nolink&​750 |}} +
- +
-Realizati urmatoarele exercitii astfel incat sa respecte design-ul ​de mai sus. Informatiile legate ​de font si culori le puteti gasi sub design. Pentru fontputeti folosi [[https://​fonts.google.com|Google Fonts]], iar pentru partea de layout folositi [[https://​flexboxfroggy.com|Flexbox]].+
  
-  - 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 3 componente (Class sau Functional) **Header**, **Footer** si **Layout**. 
-  - Creati o sectiune in componenta **Layout** care sa reprezinte continutul afisat pe pagina, iar in interiorul acestui continut sa putem adauga copii folosind compozitia. 
-  - Adaugati **Header** si **Footer** in Layout pentru a defini structura paginii. 
-  - Afisati componenta **Counter** in **Layout**ul pe care l-ati creat anterior. 
pw/laboratoare/07.1618744645.txt.gz · Last modified: 2021/04/18 14:17 by alexandru.hogea
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