Wprowadzenie React #4 (2020) – stan komponentu i przepływ danych

W poprzednim wpisie przyjrzeliśmy się jak obsługiwać zdarzenia z poziomu React, a w tym wykorzystamy tę wiedzę, by rozszerzyć funkcjonalność naszej strony i dowiemy się czym jest bardzo ważna rzecz – stan komponentu.

Czytaj dalej Wprowadzenie React #4 (2020) – stan komponentu i przepływ danych

Wprowadzenie React #3 (2020) – obsługa zdarzeń

W poprzednim wpisie dowiedzieliśmy się czym są propsy i jak dzięki nim możemy reużywać komponenty. W tym zajmniemy się obsługa zdarzeń, czyli jak w React obsłużyć np. kliknięcie na obszarze danego komponentu.

Obsługa zdarzeń w React

Wykonanie kawałka kodu w React po np. kliknięciu komponentu wygląda bardzo podobnie jak w tradycyjnym JavaScript. Po pierwsze w JSX znajdujemy element, który ma nasłuchiwać na zdarzenia i przy pomocy znanego on*, czyli np. onClick, onMouseLeave etc. powiedzieć, na jakie zdarzenie chcemy czekać.

export const Image = ({ url }) => {
  return (
    <img
      src={url}
      height="175"
      width="200"
      onClick=...
    ></img>
  );
};

W powyższym przykladzie dodaliśmy w tagach img właściwość onClick, bo chcemy wykonać kawałek logiki, gdy użytkownik kliknie obrazek.

Ten kawałek logiki umieszczamy w nawiasach klamrowych po onClick=. Musi być to funkcja, która może przyjmować jeden argument – będzie to obiekt event z danymi zdarzenia jakie zostało wywołane.

<img
      src={url}
      height="175"
      width="200"
      onClick={event => console.log(url)}
></img>

Czyli po kliknięciu elementu img w komponencie Image na konsoli zostanie wypisany adres url danego obrazu.

Wszystko pięknie, tylko nie zawsze logika, którą chcemy wykonać zmieści się w kilku tylko znakach. Wówczas warto przenieść funkcję obsługującą dane zdarzenie do osobnej zmiennej.

export const Image = ({ url }) => {
  const handleOnClick = event => {
    console.log(url);
  };

  return (
    <img 
       src={url} 
       height="175" 
       width="200" 
       onClick={handleOnClick}>
    </img>
  );
};

Czyli całość obsługi zdarzenia przypisujemy do zmiennej, a potem podajemy ją jako wartość dla onClick.

Tyle, jeśli chodzi o podstawy, są natomiast dwie sprawy, na które należy zwrócić uwagę pracując z event handlerami.

Gubienie kontekstu, czyli this to nie ten this

Problem ten dotyczy w głównej mierze komponentów klasowych, od których obecnie można w dużej mierze odejść, bo od czasu hooks komponenty funkcyjne mogą mieć własny stan i obsługę zdarzeń cyklu życia, ale to tym w następnym w wpsie.

Nie zmienia to jednak faktu, że warto wiedzieć o problemie z ‘this’ przy event handlerach.

Deklarując funkcję obsługującą zdarzenie użyłem arrow function, zamiast klasycznego function(event). Poniżej wersja function vs arrow function.

const hoc = function(event) {
    console.log(url);
}
  
const handleOnClick = event => {
    console.log(url);
};

W naszym przykładzie nie ma to znaczenia, ma natomiast gdybyśmy pracowali z klasami, to przy użyciu function do zdefiniowania funkcji obsługującej event handling zgubilibyśmy kontekst (this).

Arrow function automatycznie łączy daną funkcję z kontekstem, w którym została zdefiniowana.

Dlatego, przeskakując do konkluzji, deklarując funkcję obsługujące zdarzenia warto zawsze używać arrow function zamiast klasycznego podejścia.

Blokowanie domyślnego zachowania

Ważne jest również, by pamiętać o dwóch funkcjach, które powinny być wołane na początku obsługi wydarzenia, mianowicie event.preventDefault() oraz event.stopPropagation().

Do czego one służą?

Część elementów w HTML ma domyślne zachowanie przy pewnych wydarzeniach. Podstawowym przykładem jest kliknięcie elementu button w formularzu. Spowoduje ono przesłanie formularza, a w praktyce przeładowanie strony. Co przy używaniu React jest bardzo niepożądanym zachowaniem. Dlatego na początku funkcji obsługującej zdarzenie warto dodać event.preventDefault() by wyłączyć domyślne zachowanie.

Gdy zmienimy nieco definicję naszego głównego komponentu poprzez dodanie <div> z nasłuchiwaniem na kliknięcie.

export const App = () => {
  return (
    <div onClick={event => console.log("Event from div")}>
      <Image url="https://images.unsplash.com/photo-1508138221679-760a23a2285b" />
      <Image url="https://images.unsplash.com/photo-1474487548417-781cb71495f3" />
      <Image url="https://images.unsplash.com/photo-1580109672851-b85640868813" />
      <Image url="https://images.unsplash.com/photo-1580046939256-c377c5b099f1" />
      <Image url="https://images.unsplash.com/photo-1576801488695-2e4d7a14b8b5" />
    </div>
  );
};

To po kliknięciu obrazu zostanie wywołany event listener zarówno z danego kompnentu Image (czyli wypisze URL na konsolę) ORAZ zostanie wywołany event z div’a, czyli na konsoleęzostanie wypisany też tekst “Event from div”. To zachowanie jest spowodowane tak zwanym ‘event propagation’ – zdarzenie wędruję w górę drzewa DOM uruchamiając każdy nasłuchujący na nie event listener.

event.stopPropagation() przerywa propagację. Tak zdefiniowany event listener w Image spowoduję, że pojawi się tylko URL obrazu, a onClick z div’a nie zostanie już uruchomiony.

export const Image = ({ url }) => {
  
  const handleOnClick = event => {
    event.preventDefault();
    event.stopPropagation();
    console.log(url);
  };

  return <img src={url} height="175" width="200" onClick={handleOnClick}></img>;
};

Tyle w temacie obsługi zdarzeń. Nie zrobiliśmy nic w temacie wyglądu czy funkcjonalności strony, ale to się zmieni w przyszłości.

Kod przykładu dostępny jest na Github.

Tradycyjnie zapraszam do dołączenia do newslettera, gdzie materiały odnośnie React również mają swoje miejsce.

Wprowadzenie React #2 (2020) – komponenty i props

W poprzednim wpisie utworzyliśmy nasz projekt oraz pierwszy komponent, w tym będziemy dalej bawić się komponentami oraz dowiemy się czym są w React props.

Drzewo komponentów

Nasza galeria zdjęć z jednym tylko zdjęciem nie do końca zasługuje na to miano. Przydałoby się więc dodać jeszcze kilka obrazów. Możemy to zrobić powielając komponent <Image>… jednak jak ma się to przedstawiać w funkcji ReactDOM.render?

W ReactJS jeśli chcemy stworzyć kilka równorzędnych komponentów wówczas musimy je opakować w jakiś komponent nadrzędny. Możemy zrobić na przykład tak:

export const Image = () => (
  <img
    src="https://images.unsplash.com/photo-1508138221679-760a23a2285b"
    height="175"
    width="200"
  ></img>
);

export const App = () => {
  return (
    <div>
      <Image />
      <Image />
      <Image />
      <Image />
      <Image />
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));

Stworzyliśmy dodatkowy, główny, komponent App, który ma w sobie jeden węzeł nadrzędny – ‘div‘ oraz pięć komponentów Image. Przy okazji ustawiliśmy na sztywno wysokość i szerokość obrazu w komponencie Image by nie był tak gigantyczny.

Natomiast dodawanie ‘sztucznego’ diva o ile przy tworzeniu nowych aplikacji zdaje się relatywnie bezbolesne to w momencie, kiedy np. migrujemy istniejącą aplikację na React, a nasze testy bazują na X-Path… wtedy taki niegroźny div, jest źródłem wielu zmian w kodzie.

Dlatego jakiś czas temu do Reacta dodano React.Fragment, który zbiera w węzeł nadrzędny komponenty (jak div w przykładzie) na potrzeby Reacta. Nie ma on jednak przełożenia na ostateczny wygląd HTML, czyli po prostu go nie widać.

export const App = () => {
  return (
    <React.Fragment>
      <Image />
      <Image />
      <Image />
      <Image />
      <Image />
    </React.Fragment>
  );
};

Możemy ten kod jeszcze odrobinę skrócić i zamiast React.Fragment możemy napisać po prostu <>.

export const App = () => {
  return (
    <>
      <Image />
      <Image />
      <Image />
      <Image />
      <Image />
    </>
  );
};

React props

Wszystko fajnie tylko po co nam 5 takich samych obrazków? Jeśli chcemy mieć inny URL dla zdjęcia musimy tworzyć nowy komponent? Na szczęście nie. Tu pojawiają się propsy, dzięki, którym komponent Image będzie mógł wyświetlać różne obrazy.

Tak jak standardowe tagi HTML mogą mieć pewne właściwości (jak height i width w tagu img), tak komponenty Reactowe również mogą mieć zdefiniowane przez nas właściwości.

Konkretnie do komponentu Image możemy dodać property “url”, który będzie wskazywać na adres obrazu.

export const App = () => {
  return (
    <>
      <Image url="https://images.unsplash.com/photo-1508138221679-760a23a2285b" />
      <Image url="https://images.unsplash.com/photo-1474487548417-781cb71495f3" />
      <Image url="https://images.unsplash.com/photo-1580109672851-b85640868813" />
      <Image url="https://images.unsplash.com/photo-1580046939256-c377c5b099f1" />
      <Image url="https://images.unsplash.com/photo-1576801488695-2e4d7a14b8b5" />
    </>
  );
};

By dobrać się do tego pola, z poziomu komponentu Image, musimy nieco go rozbudować.

export const Image = props => {
  console.log(props.url);
  return <img src={props.url} height="175" width="200"></img>;
};

Po pierwsze teraz nasza funkcja tworząca komponent bierze jeden argument – props. Jest to obiekt, który ma zestaw pól odpowiadającym właściwością, jakie zostały przesłane do naszego komponentu. W naszym wypadku obiekt props ma pole url, bo zrobiliśmy tak <Image url=”https://images.unsplash.com/photo-1576801488695-2e4d7a14b8b5″ />. Nie ma natomiast propsa ala czy kot bo żaden taki klucz nie został przesłany.

Teraz by odnieść się do wartości przesłanej z poziomu kodu JavaScript używamy standardowo props.url, natomiast jeśli chcemy użyć tej wartości w elemencie zwracanym, czyli w JSX, musimy opakować ją w nawiasy klamrowe {props.url}.

Często w komponentach, zamiast ciągle pisać props. dokonuję się destrukturyzacji parametru funkcji. Wygląda to wówczas tak:

export const Image = ({ url }) => {
  console.log(url);
  return <img src={url} height="175" width="200"></img>;
};

Zapis {url} oznacza “weź pole url z obiektu, który zostanie przesłany jako parametr tej funkcji i przypisz je do zmiennej url, wyrzuć wszystko inne”. Gdybyśmy mieli więcej interesujących nas pól destrukturyzacja wyglądałaby tak: {url, otherField, anotherField }.

I to by było na tyle jeśli chodzi o podstawy pracy z props. W następnej części zajmiemy się nasłuchiwaniem na zdarzenia i reagowaniem na nie.

Kod przykładu dostępny jest na Github.

Tradycyjnie zapraszam do dołączenia do newslettera, gdzie materiały odnośnie React również mają swoje miejsce.

Praktyczne wprowadzenie do ReactJS 2020 | #1

React jest jedną z najpopularniejszych bibliotek języka Javascript, służącą do tworzenia interfejsów użytkownika, a konkretniej tych webowych, czyli stron internetowych. Został on stworzony  w podziemiach tajnej fabryki Facebooka ;), inne duże korporacje, jakie z niego korzystają to PayPal czy Netflix. Na chwilę obecną można śmiało powiedzieć, ze React stał się dominującą biblioteką w ekosystemie JS. Wprowadzenie React JS utworzymy, krok po kroku, pierwszą, pełnoprawną aplikację internetową. Czytaj dalej Praktyczne wprowadzenie do ReactJS 2020 | #1

Video Chat z WebRTC i TypeScript #1 – początek projektu

WebRTC jest otwartą technologią webową stworzoną przez Google. Pozwala ona na przesyłanie mediów i danych w czasie rzeczywistym pomiędzy przeglądarkami i urządzeniami mobilnymi bez dedykowanego serwera do przesyłu danych.

Więcej o technologii można dowiedzieć się z tej prezentacji. My przejdziemy od razu do praktyki. W pierwszej części utworzymy projekt oraz dowiemy się jak przesłać video z kamery na lokalną stronę www.

Czytaj dalej Video Chat z WebRTC i TypeScript #1 – początek projektu

Omówienie Technology Radar v. 21 w kontekście ekosystemu JavaScript

Technology Radar jest kwartalnym, wysokopoziomowym rzutem oka na technologie z każdego programistycznego i dev-opsowego ekosystemu. Tworzony jest przez specjalistów z różnych dziedzin z firmy Thoughtworks. Przyglądają się oni platformom, językom programowania, frameworkom i narzędziom, i podpowiadają nam, na co warto zwrócić uwagę, albo wręcz przeciwnie – z jakiej technologii warto się przenieść na coś lepszego.

Czytaj dalej Omówienie Technology Radar v. 21 w kontekście ekosystemu JavaScript

TypeScript w praktyce. Na niepraktycznym przykładzie.

W ostatniej części cyklu wprowadzającego do Typescript weźmiemy trochę rzeczy, o których traktowały poprzednie wpisy i zaimplementujemy prostą aplikację internetową.

I to właśnie sformułowanie “prostą aplikację internetową” czyni ten przykład… niepraktycznym. Mianowicie im projekt większy, tym więcej daje nam TypeScript z jego silnym typowaniem, generykami, interfejsami. Większość z tych rzeczy jest nadmiarowa przy prostych aplikacjach webowych, które spokojnie można tworzyć w JavaScript bez obawy jakiś drastycznych pomyłek czy zamotaną architekturę.

Czytaj dalej TypeScript w praktyce. Na niepraktycznym przykładzie.

NestJS – REST API – pierwszy tutorial dla uczestników newsettera

Właśnie opublikowałem pierwszy mini-kurs na mojej platformie :). Dotyczy on tworzenia REST API w NestJS. Czym jest NestJS można przeczytać na stronie tego obiecującego frameworka.

Jeśli chcesz uzyskać dostęp do 1.5h materiału gdzie krok po kroku tworzę REST API zapraszam na kursy.clockworkjava.pl