Laboratorul 03: Introducere in ReactJS

1. Ce este Single Page Application (SPA)?

Un SPA sau o aplicatie cu o singura pagina, este o 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 server. In acest caz, browserul nu este nevoit sa incarce o pagina noua.

2. Ce este JSX ?

Considerati urmatoarea linie

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. In exemplul de mai jos, declaram o variabila name, iar ulterior o folosim in interiorul JSX fiind pusa intre paranteze acolade.

De asemenea, puteti sa puneti orice cod JavaScript valid in interiorul parantezelor acolade in JSX.

JSX poate sa fie folosit si in contextul unor expresii, precum

Tag-urile JSX pot contine si mai multi copii.

De asemenea, putem folosi JSX pentru a ne proteja si de eventuale atacuri.

JSX reprezinta obiecte. Babel se ocupa de compilarea JSX in apeluri React.createElement()

3. Ce este React ?

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

Pentru a putea folosi tool-ul oferit de Facebook, avem nevoie sa indeplinim urmatoarele conditii: Node >= 8.10 si npm >= 5.6.

Pentru a genera un proiect trebuie sa rulati urmatoarele:

Dupa rularea script-ului npm start puteti accesa aplicatia accesand link-ul din consola

http://localhost:3000

5. Componente

Componentele va permit sa va impartiti interfata utilizator in “piese” reutilizabile, iar in acelasi timp va puteti gandi la fiecare piesa ca fiind izolata.

Conceptual, componentele sunt asemanatoare cu functiile JavaScript. Acestea accepta intrari (denumite “props”) si returneaza elemente React, care descriu ceea ce ar trebui sa apara in interfata.

5.1. Functional Components

Cea mai simpla cale de a defini o componenta este aceea de a scrie o functie JavaScript

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.

5.2. Class Components

De asemenea, puteti folosi si o clasa ES6 pentru a defini o componenta:

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:

De asemenea, elementele pot reprezenta si componente definite de utilizator:

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.

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.

5.4 Stare ( State )

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.1 Functional Components

In cazul componentelor functionale, o variabila de stare este declarata cu ajutorul useState (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.

5.4.2 Class Components

Cele doua componente prezentate mai sus sunt echivalente, insa exista o mica diferenta:

Class Components fac referire la state sau props folosind this.

Class components

this.state
this.props
Functional Components

state
props

5.5 React Hooks

5.5.1 useState

Un Hook este o functie speciala care va permite sa va „conectati” la functionalitatile oferite de React. De exemplu, useState este un Hook care va permite sa adaugati stare pentru componentele functionale.

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

Ce face apelarea useState? Declara o variabila de stare. Variabila noastră se numește count, dar am putea-o numi orice altceva. React isi va aminti valoarea actuala intre randari si va furniza cea mai recenta valoare pentru variabila noastra. Daca vrem sa actualizam numarul curent, putem apela setCount.

5.5.2 useEffect

Folosind useEffect Hook, ii spui Reactului ca componenta ta trebuie sa faca ceva dupa randare / la actualizarea unei variabile. React isi va aminti functia pe care ai transmis-o (ne vom referi la ea ca „efectul nostru”) si o va apela dupa efectuarea actualizarilor din DOM.

Structura acestui Hook este urmatoarea: o functie care se va executa si o lista de dependente, cu care poti forma 3 cazuri de utilizare:

  1. Daca vrei ca actiunea sa se desfasoare la randarea componentei, atunci vei lasa lista goala
    useEffect(() => {
        console.log(`I am alive`);
      });
  2. Daca vrei ca actiunea sa se efectueze in momentul in care o variabla se actualizeaza, de exemplu, daca vrei sa afisam in consola de fiecare data cand variabila noastra count se modifica, vom avea urmatorul useEffect:
    useEffect(() => {
      document.title = `You clicked ${count} times`;
    }, [count]);

    Unde putem observa ca in lista noastra de dependente avem count, deci de fiecare daca cand count va fi modificat se va afisa in consola mesajul respectiv.

  3. Daca vrei ca actiunea sa se petreaca in momentul in care componenta este distrusa, atunci vei folosi un return in useEffect
      useEffect(() => {
        return function cleanup() {
          console.log('I am cleaning');
        };
      });

5.6 Event Handling

Gestionarea evenimentelor cu elemente React este foarte asemanatoare cu gestionarea evenimentelor pe elemente DOM. Totusi, exista cateva diferente de sintaxa:

  • evenimentele din React sunt camelCase
  • pentru gestionarea evenimentelor in React sunt folosite functii, nu string-uri

HTML

React

HTML

React

5.7 Conditional Rendering

Randarea bazata pe conditii, in React, functioneaza in acelasi mod precum conditionarea in JavaScript. Folositi operatori JavaScript precum if sau conditional operator pentru a crea elemente reprezentand starea curenta.

Considerati urmatoarele doua componente:

Vom implementa o componenta Greeting care afiseaza una dintre aceste componente, daca un utilizator este autentificat sau nu.

5.8 Liste si chei (key)

In primul rand, sa ne amintim cum transformam listele in JavaScript.

Acest cod afiseaza urmatorul rezultat in consola

[2, 4, 6, 8, 10]

Afisarea mai multor componente

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li>{number}</li>
);

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.

Pentru a rezolva aceasta problema, trebuie sa introducem urmatoarea modificare:

Aceste keys (chei) ajuta React-ul la identificarea elementelor care s-au schimbat, adaugat si eliminat. Putem privi aceste chei precum identitatea unui element.

5.9 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:

Class components

this.props.children
Functional components

props.children

6. Ce este Tailwind CSS si de ce este util?

Tailwind CSS este un framework de CSS care ne ajuta sa construim un design mult mai rapid si usor fata de metodele clasice (SASS, CSS simplu, styled-components, Bootstrap, etc).

Printre feature-urile pe care le ofera putem mentiona:

  • design accesibil si customizabil usor pentru orice tip de ecran (desktop, tableta, telefon)
  • ofera stilizarea starilor prin care pot trece componentele de baza (butoane, inputuri, etc)
  • ofera tema intunecata (dark mode)
  • dimensiune mica a pachetului astfel incat sa nu influenteze performanta
  • se pot modifica cu usurinta toate valorile default

7. Construirea design-ului din laboratorul 2 folosind ReactJS

Codul pentru acest laborator se afla pe acest repository.

Pentru ca nu este un proiect mic, vom sparge in doua laboratoare construirea design-ului.

Versiunea cu Vue o sa apara saptamana viitoare.

7.1 Crearea unui proiect nou

npx create-react-app lab-03

7.2 Modificarea structurii

Ne dorim sa ramanem organizati astfel incat proiectul nostru sa fie urmarit cu usurinta si de alti oameni. Pentru a face asta am separat paginile de componentele care vor intra in structura paginilor in diferite foldere: pages (paginile care sunt legate de anumite rute si le-am spart in Admin si User), styling (pentru fisierele noastre de styling), utils (pentru componente de tip layout, routing), components ( modals - unde avem fomularele pentru adaugare, editare de entitati si componentele noastre custom - input, buton, tabel, etc).

7.3 Crearea unui sistem de navigatie in cadrul aplicatiilor de Admin/User

Vom folosi biblioteca react-router-dom cu documentatia aceasta.

import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Analytics from "../pages/Admin/Analytics";
import Book from "../pages/Admin/Book";
import UserBooks from "../pages/User/Books";
import Books from "../pages/Admin/Books";
import Account from "../pages/User/Account";
 
const Router = () => (
  <BrowserRouter>
    <Routes>
      <Route exact path="/" element={<UserBooks />} />
      <Route exact path="/profile" element={<Account />} />
      <Route exact path="books" element={<Books />} />
      <Route exact path="books/:id" element={<Book />} />
      <Route exact path="analytics" element={<Analytics />} />
    </Routes>
  </BrowserRouter>
);
 
export default Router;

7.4 Crearea componentelor custom

Precum am facut in laboratorul trecut, construind sistemul de design, asa ne vom ocupa prima data de componentele custom pe care le contine aplicatia: input, butoane, formulare, tabel, link-uri si text. Asta inseamna ca le vom face atat structura folosind JSX, cat si stilizarea folosind Tailwind.

7.4.1 Input
import React from "react";
 
const Input = (props) => {
  const { label, icon, ...rest } = props;
  return (
    <label>
      {label && <span>{label}</span>}
      {icon}
      <input {...rest} className={`input`} />
    </label>
  );
};
 
export default Input;
7.4.2 Buton
import React from "react";
 
const Button = ({ children, className, ...rest }) => {
  return (
    <button className={`button ${className}`} {...rest}>
      {children}
    </button>
  );
};
 
export default Button;

Restul componentelor le veti gasi in repository-ul aflat pe gitlab.

7.5 Crearea paginilor

7.5.1 Layout-ul paginilor

Pentru ca avem doua tipuri de utilizatori cu layout-uri destul de diferite (unul este vertical, unul orizontal) vom face doua fisiere, fiecare cu cate un layout.

De exemplu, layout-ul pentru utilizatorul de tip administrator poate fi spart o data in doua parti pe orizontala: meniul din stanga cu link-urile catre paginile de Books/Analytics si partea de continut care este formata din header (informatiile despre utilizator) si informatiile corespunzatoare paginii curente (tabelul cu toate cartile sau grafice).

import React from "react";
import AdminHeader from "./AdminHeader";
import AdminMenu from "./AdminMenu";
 
const AdminLayout = ({ children }) => {
  return (
    <div className="layout">
      <AdminMenu />
      <div className="content">
        <AdminHeader />
        {children}
      </div>
    </div>
  );
};
 
export default AdminLayout;
import React from "react";
import { Link } from "react-router-dom";
import Avatar from "react-avatar";
 
const AdminHeader = ({ children }) => {
  const name = "Jake Markel";
  return (
    <div className="header">
      <div className="profile-container">
        <div className="profile-info">
          <p>{name}</p>
          <Link to="/">Signout</Link>
        </div>
        <Avatar name={name} round="100px" size="50px" />
      </div>
    </div>
  );
};
 
export default AdminHeader;
7.5.2 Continutul din fiecare pagina

Pagina de Books privita din perspectiva Administratorului contine in principal un tabel care este construit cu React Table si va fi populat cu date de la server.

import React, { useMemo, useState } from "react";
import Button from "../../components/Button";
import Table from "../../components/Table";
import AdminLayout from "../../utils/AdminLayout";
import { MdAdd } from "react-icons/md";
import BookModal from "../../components/modals/BookModal";
 
const Books = () => {
  const data = useMemo(date_server,
    []
  );
 
  const [openedModal, setOpenedModal] = useState(false);
  return (
    <AdminLayout>
      <BookModal
        modalIsOpen={openedModal}
        closeModal={() => {
          setOpenedModal(false);
        }}
      />
      <div className="row-between">
        <h2>{data.length} Books</h2>
        <Button onClick={() => setOpenedModal(true)}>
          <MdAdd /> Add Book
        </Button>
      </div>
      <Table data={data} />
    </AdminLayout>
  );
};
 
export default Books;

Cursuri utile

pw/laboratoare/03.txt · Last modified: 2022/04/08 12:36 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