Podział na komponenty w React.js

wp-content/uploads/2017/10/React_logo_wordmark-300x101-1-e1508612391308.png
  1. React.js: Wprowadzenie do kursu od podstaw
  2. Poznaj React.js
  3. Pierwszy komponent w React.js
  4. Props czyli atrybuty w React.js
  5. Podział na komponenty w React.js
  6. Klasy jako komponenty React.js
  7. Interakcja z komponentami React.js
  8. Stan komponentów React.js
  9. State w React.js 2
  10. Metody cyklu życia komponentu w React.js
  11. React.js w przykładach: filtrowanie statycznej listy
  12. Tworzenie aplikacji React.js dzięki create-react-app
  13. React.js na GitHub Pages dzięki create-react-app
  14. Testowanie aplikacji React.js — podstawy Enzyme
  15. Testowanie React.js w Enzyme — props, state i interakcje
  16. Poprawne bindowanie funkcji w React.js
  17. Odpowiadam na pytania: Babel, ECMAScript, destrukturyzacja, onClick, className
  18. Komunikacja pomiędzy komponentami w React.js
  19. Komunikacja z API w React.js
  20. Formularze w React.js — kontrolowane komponenty
  21. Formularze w React.js — niekontrolowane komponenty
  22. Odpowiadam na pytania: props, nawiasy klamrowe, funkcje vs klasy, import react
  23. TDD w React.js z pomocą react-testing-library
  24. Flux i Redux: globalny store i jednokierunkowy przepływ danych
  25. React + Redux — kurs: wprowadzenie i podstawy
  26. React + Redux — filtrowanie listy, proste selektory
  27. Projektowanie komponentów: Presentational & Container Components
  28. Asynchroniczność w Redux: redux-thunk
  29. Kiedy używać state, a kiedy Redux?
  30. Nowe metody cyklu życia: getDerivedStateFromProps i getSnapshotBeforeUpdate
  31. Leniwe ładowanie komponentów w React dzięki import
  32. Higher Order Reducers — Redux i powtarzanie kodu
  33. React Hooks — wprowadzenie i motywacja
  34. React Hooks: useState, czyli stan w komponentach funkcyjnych
  35. React Hooks: useState — wiele stanów, callbacki i inne niuanse
  36. React Hooks: useEffect — efekty uboczne w komponencie
  37. React Hooks a żądania do API
  38. useReducer — przenoszenie logiki poza komponent
  39. useMemo, useCallback, czyli rozwiązanie problemów ze zmieniającymi się propsami
  40. Wady React Hooks
  41. React Hooks: Piszemy własne hooki!

W tej części skupisz się na teorii i praktyce dzielenia zaprojektowanych aplikacji na poszczególne komponenty. Zaczniesz też tworzyć prostą appkę — menedżer kontaktów. W planach wyświetlanie, dodawanie i edycja kontaktów. Ale najpierw — musimy przecież zaprojektować HTML i CSS dla tej aplikacji.

Projekt

Przyjrzyj się temu co będziesz budował(a). Będzie to lista kontaktów, ale na początku spójrz tylko na pierwszy widok:

Komponenty w React.js i JSX

To dzisiaj „potniemy” i podzielimy na komponenty React.js w JSX.

Sprawdź szkolenia z React!

Zacznij od napisania kodu HTML i CSS. W przykładzie wykorzystuję framework CSS semantic-ui, ale na dobrą sprawę z łatwością napiszesz wszystko w gołym CSS. Możesz też użyć bootstrapa — do woli. Oto kod HTML:

<header class="ui fixed menu">
  <nav class="ui container">
    <a href="#" class="header item">
      <img class="logo" src="https://typeofweb.com/wp-content/uploads/2017/08/cropped-typeofweb_logo-04-white-smaller-1-e1504359870362.png" />
      Lista kontaktów
    </a>
    <div class="header item">
      <button class="ui button">Dodaj</button>
    </div>
  </nav>
</header>
<main class="ui main text container">
  <ul class="ui relaxed divided list selection">
    <li class="item">
      <img src="https://api.adorable.io/avatars/55/typeofweb1.png" class="ui mini rounded image" />
      <div class="content">
        <h4 class="header">Lena</h4>
        <div class="description">JavaScript Developer</div>
      </div>
    </li>
    <li class="item">
      <img src="https://api.adorable.io/avatars/55/typeofweb2.png" class="ui mini rounded image" />
      <div class="content">
        <h4 class="header">Brian</h4>
        <div class="description">Human Resources</div>
      </div>
    </li>
    <li class="item">
      <img src="https://api.adorable.io/avatars/55/typeofweb3.png" class="ui mini rounded image" />
      <div class="content">
        <h4 class="header">Rick</h4>
        <div class="description">QA</div>
      </div>
    </li>
  </ul>
</main>

Jest tutaj nagłówek z logo i przyciskiem dodawania kontaktów oraz lista z trzema kontaktami. Wygląda dokładnie jak na screenshocie powyżej. Ale chcesz mieć to w React, prawda? Do dzieła!

Na razie nie skupiam się na sposobach używania kodu CSS do Reacta i po prostu dodałem <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.min.css"> do mojego kodu.,

Podział na komponenty w React.js

Do tej pory tworzyliśmy jeden komponent i renderowaliśmy go przez funkcję ReactDOM.render. Napisałaś/eś wtedy pewnie coś w stylu <App />. Czy to oznacza, że własne komponenty są także elementami? Tak jakby. Możemy ich używać w JSX tak, jakby nimi były. Czy to nie jest ekstra?

Myśląc o aplikacji postaraj się ją jakoś logicznie podzielić. Na jak najmniejsze fragmenty. To będą Twoje komponenty. Co możemy natychmiast wydzielić w naszej aplikacji? Oczywiście nawigację na górze oraz listę kontaktów. Świetna myśl! Dalej w oczy rzuca się możliwość odseparowania komponentu dla poszczególnych kontaktów — tak, aby nie powielać ich kodu. Dodatkowo, można by się pokusić o stworzenie osobnego komponentu dla avatarów — z tego względu, że zawarte jest w nim nieco logiki. Na schemacie wygląda to jakoś tak:

Schemat komponentów w React.js

Wszystko zaplanowane? Czas na kod!

Komponenty w React.js

Zacznij od stworzenia jednego komponentu w React i sprawienia, aby się wyświetlał. Potem przejdź do podziału. Pierwsze co musimy zrobić to zamienić wszystkie class na className w HTML. Potem już z górki:

function App() {
  return (
    <div>
      <header className="ui fixed menu">
        …
      </header>
      ……
    </div>
  );
}

To było proste, prawda? To już znasz. Teraz pozostaje wydzielić tylko pozostałe komponenty. Tworzymy AppHeader, ContactsListContactItem i wewnątrz nich odpowiedni kod. App ostatecznie będzie wyglądał tak:

function App() {
  return (
    <div>
      <AppHeader />
      <main className="ui main text container">
        <ContactsList />
      </main>
    </div>
  );
}
ReactDOM.render(, document.getElementById("app"));

AppHeader to łatwizna, więc nawet tutaj nie wrzucam. ContactsList jest nieco ciekawszy, bo wewnątrz używa kolejnego komponentu i przekazuje do niego propsy:

function ContactsList() {
  return (
    <ul className="ui relaxed divided list selection">
      <ContactItem
        login="typeofweb1"
        name="Lena"
        department="JavaScript Developer"
      />
      <ContactItem
        login="typeofweb2"
        name="Brian"
        department="Human Resources"
      />
      <ContactItem
        login="typeofweb3"
        name="Rick"
        department="QA"
      />
    </ul>
  );
}

Mamy tutaj komponent ContactsList, który tworzy listę i wewnątrz niej 3 komponenty ContactItem. Do nich przekazywane są odpowiednie propsy: Login, name i department, które służą do sparametryzowania tego co wyświetla komponent. W związku z tym ContactItem przyjmuje 3 propsy jako argument:

function ContactItem({ login, name, department }) {
  const imgUrl = `https://api.adorable.io/avatars/55/${login}.png`;
  return (
    <li className="item">
      <img src={imgUrl} className="ui mini rounded image" />
      <div className="content">
        <h4 className="header">{name}</h4>
        <div className="description">{department}</div>
      </div>
    </li>
  );
}

Poniżej efekt końcowy wraz z kodem:

See the Pen Props czyli atrybuty w React.js by Michał Miszczyszyn (@mmiszy) on CodePen.

Co dalej?

W kolejnych wpisach dodasz interakcję (np. kliknięcia) do komponentów. Dodatkowo poznasz stan (state), który potem przyda się nam przy rozbudowie aplikacji. Bez niego praktycznie niemożliwe byłoby tworzenie jakichkolwiek aplikacji, które oprócz wyświetlania treści miałyby robić cos jeszcze 🙂

Jeśli chcesz na bieżąco śledzić kolejne części kursu React.js to koniecznie śledź mnie na Facebooku i zapisz się na newsletter.

Nie wysyłamy spamu, tylko wartościowe informacje. W każdej chwili możesz się wypisać klikając „wypisz się” w stopce maila.

Ćwiczenie

Ćwiczenie: Stwórz komponent do wyświetlania avatarów i przenieś do niego kod za to odpowiedzialny. Niech ten komponent przyjmuje jako props tylko login. Wrzuć swój kod w komentarzu!

Ćwiczenie*: Zmodyfikuj stworzony komponent z avatarem tak, aby obecne obrazki były wyświetlane gdy login nie jest mailem. Natomiast gdy jest mailem to skorzystaj z Gravatara. Zauważ, że całkowita zmiana działania tego komponentu nie wymaga wprowadzania żadnych zmian w pozostałym kodzie aplikacji!

Nawigacja po kursie:
  1. React.js: Wprowadzenie do kursu od podstaw
  2. Poznaj React.js
  3. Pierwszy komponent w React.js
  4. Props czyli atrybuty w React.js
  5. Podział na komponenty w React.js
  6. Klasy jako komponenty React.js
  7. Interakcja z komponentami React.js
  8. Stan komponentów React.js
  9. State w React.js 2
  10. Metody cyklu życia komponentu w React.js
  11. React.js w przykładach: filtrowanie statycznej listy
  12. Tworzenie aplikacji React.js dzięki create-react-app
  13. React.js na GitHub Pages dzięki create-react-app
  14. Testowanie aplikacji React.js — podstawy Enzyme
  15. Testowanie React.js w Enzyme — props, state i interakcje
  16. Poprawne bindowanie funkcji w React.js
  17. Odpowiadam na pytania: Babel, ECMAScript, destrukturyzacja, onClick, className
  18. Komunikacja pomiędzy komponentami w React.js
  19. Komunikacja z API w React.js
  20. Formularze w React.js — kontrolowane komponenty
  21. Formularze w React.js — niekontrolowane komponenty
  22. Odpowiadam na pytania: props, nawiasy klamrowe, funkcje vs klasy, import react
  23. TDD w React.js z pomocą react-testing-library
  24. Flux i Redux: globalny store i jednokierunkowy przepływ danych
  25. React + Redux — kurs: wprowadzenie i podstawy
  26. React + Redux — filtrowanie listy, proste selektory
  27. Projektowanie komponentów: Presentational & Container Components
  28. Asynchroniczność w Redux: redux-thunk
  29. Kiedy używać state, a kiedy Redux?
  30. Nowe metody cyklu życia: getDerivedStateFromProps i getSnapshotBeforeUpdate
  31. Leniwe ładowanie komponentów w React dzięki import
  32. Higher Order Reducers — Redux i powtarzanie kodu
  33. React Hooks — wprowadzenie i motywacja
  34. React Hooks: useState, czyli stan w komponentach funkcyjnych
  35. React Hooks: useState — wiele stanów, callbacki i inne niuanse
  36. React Hooks: useEffect — efekty uboczne w komponencie
  37. React Hooks a żądania do API
  38. useReducer — przenoszenie logiki poza komponent
  39. useMemo, useCallback, czyli rozwiązanie problemów ze zmieniającymi się propsami
  40. Wady React Hooks
  41. React Hooks: Piszemy własne hooki!

Nie wysyłamy spamu, tylko wartościowe informacje. W każdej chwili możesz się wypisać klikając „wypisz się” w stopce maila.

Subscribe
Powiadom o
guest
57 komentarzy
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Karol Grabowski
Karol Grabowski
2 lat temu

Hejka, bardzo fajna seria artykułów do reacta, sam aktualnie jestem w trakcie nauki i sie bardzo przydają. Mam takie pytanie, czy jak tworzymy bezstanowy komponent to lepiej korzystac z klas (tak to jest często robione w przykładach w dokumentacji reacta ) czy lepiej uzyc jednak zwyklych funkcji, ma to jakiś wpływ np na wydajność?

Tomasz Sochacki
Tomasz Sochacki
2 lat temu

Podobno funkcje są wydajniejsze, tym bardziej, że jest to rozwiązanie zalecane m.in przez Airbnb: https://github.com/airbnb/javascript/tree/master/react#class-vs-reactcreateclass-vs-stateless. Jeśli skonfigurujesz sobie pod Airbnb eslinta to domyślnie będzie chciał właśnie funkcje i to zwykłe, nie arrow function.

Bartek
Bartek
2 lat temu

Super czekam na więcej

Wiesław Turzański
Wiesław Turzański
2 lat temu

nie wiem na jaką ocenę wykonałem zadanie domowe. Ale dopiero jestem w „przedszkolu w gupie REACT-ki”.


function ContactItem({ login, name, department }) {      
      return (
        
  • {name}

    {department}
  • ); } function Avatar(avatar) { let avt; if ((avatar.login).includes("@")) { avt = "https://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50"; } else { avt = comment image`; } return }

    Pozdrawiam

    Wiesław Turzański
    Wiesław Turzański
    2 lat temu

    Dziękuję bardzo za cenne uwagi. Oczywiście zaraz kod dostosuję zgodnie z sugestiami. Co do className to w kodzie mam prawidłowo, ale nie za bardzo wiem jak tutaj wkleić mój kod, tak aby był oryginalny. Wyżej użyłem znaczników code/code i tam wkleiłem swój kod. Ale to nie jest chyba dobra rozwiązanie. Jeszcze raz dzięki za naukę i podrawiam serdecznie. 🙂

    Wiesław Turzański
    Wiesław Turzański
    2 lat temu

    Dzięki.
    Powiem tak, od 4 miesięcy próbowałem ogarnąć Angular-a i początki były obiecujące. Jednak gdy dalej w las to powoli traciłem zainteresowanie, wydaje mi się zbyt skomplikowany, że tak powiem w szczegółach. Oczywiście dla mnie.
    Całe szczęście, że na fejsie znalazłem ten kurs. Pochłonął mnie całkowicie i oprócz zadań domowych próbuję ogarnąć to czego nie udało mi się w Angular. I to wychodzi. Przy okazji uczę się też airbnb, a teraz będę doskonalił disqus jako zajęcia pozalekcyjne. Pozdrawiam

    Dizu Blog
    2 lat temu

    Cześć,
    Dziękuję za cały kurs, jest napisany w bardzo przystępny sposób.
    Mamy pytanie dotyczące proposów; dlaczego nie mogę przekazać w propsie całego url do zdjęcia? np:

    
    function ListElement ({imgUrl, name, description}) {
        return (
            
  • {name}

    {description}
  • ) }

    Pytanie to łącze z ćwiczeniem do samodzielnego rozwiązania, które kończy poprzedni temat. Co można, a czego nie przekazać w propsie (czy tylko stringa?)

    Pozdrowienia 🙂

    Dizu Blog
    2 lat temu

    Dziękuję bardzo za odpowiedź!
    Wszystko jasne i zrozumiałe 🙂

    Dizu Blog
    2 lat temu

    Cześć,
    Wrzucam moje kody. Będę wdzięczna za komentarz.

    
    function MainContent () {
        return (
            
    ) } function ListElement ({avatarLogin, name, description}) { return (
  • {name}

    {description}
  • ) } function UserAvatar ({login}) { let imgUrl=''; if (login.includes('@') ) { imgUrl = `https://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50`; } else { imgUrl = comment image`; } return ( ) }

    Pozdrowienia!

    Dizu Blog
    2 lat temu

    a tak, jakoś po przyklejeniu do komentarza, znaki zmieniły wielkość .
    Dzięki! 🙂

    Maciej Grędecki
    Maciej Grędecki
    2 lat temu

    Cześć, uparłem się, że to zrozumiem. Dlaczego nie wyświetla mi poprawnych avatarów? Przecież w wywołaniu ContactAvatar w ContactItem podaję atrybut, a w funkcji ContactAvatar zaciągam go i wklejam w source w stringa.

    
    function ContactItem({login, name, department}) {
      return (
        
  • {name}

    {department}
  • ); } function ContactAvatar({login}) { return( ); }
    Wiktor Obrębski
    Wiktor Obrębski
    2 lat temu

    Dynamiczne property do komponentow reactowych podajemy bez cudzysłowiów, chyba, że chodzi nam konkretnie o string. Błąd w funkcji „ContactItem”, 3 linijka, do poprawy teoretycznie. Chodź widzę, że system komentarzy tego bloga sam psuje formatowanie kodu i dodaje cudzysłowia. Ciężko stwierdzić jak kod wyglądał w oryginale.

    Podejrzewam, że chodzi o poprawę linijki w funkcji ContactAvatar.
    Klamry w środku są traktowane jako zwykły string, a nie parametr login.
    https://pastebin.com/0W45wfAg

    Maciej Grędecki
    Maciej Grędecki
    2 lat temu

    klasy są camelCase, a komponenty z dużej i camelCase, tylko tak się kopiuje ;/

    Maciej Grędecki
    Maciej Grędecki
    2 lat temu

    Dzięki, myślałem, że wcisnę element js do atrybutu jsx

    FoxCode
    FoxCode
    2 lat temu

    Dlaczego trzeba wszystko zmieniać na className, skąd taki zamysł autorów czy nie łatwiej by było zostać przy class?

    trackback

    […] Podział na komponenty w React.js […]

    Michal Jaracz
    Michal Jaracz
    2 lat temu

    Cześć,
    wklejam swój kod jako zadanie domowe.
    https://wklejaj.pl/12202
    Mam trochę problem z odpaleniem tego w swojej przeglądarce. Używam lite-server, uruchamiając stronę na swoim localhost, ale nie wiedzieć czemu nie działa..

    Michal Jaracz
    Michal Jaracz
    2 lat temu

    dzięki

    Łukasz Marcinek
    Łukasz Marcinek
    2 lat temu

    Dlaczego nie działa mi nawet zaimplementowany kod od Ciebie, jedynie jak przekopiuje cały kod w czystym JS to wtedy śmiga 🙂 ale kod wtedy jest kompletnie nie zrozumiały i wygląda całkowicie inaczej niz w poprzednich odcinkach.

    Łukasz Marcinek
    Łukasz Marcinek
    2 lat temu

    Mam podpięte 3 biblioteki o których wspominałeś w poprzednich odcinkach. kopiuje do swojego pliku index.html.

    Łukasz Marcinek
    Łukasz Marcinek
    2 lat temu

    a można się dowiedzieć jak kompilować jsx jak to z konfigurować ?

    Łukasz Marcinek
    Łukasz Marcinek
    2 lat temu

    Dziękuje 🙂

    Testowanie Testów
    Testowanie Testów
    2 lat temu

    function Avatar({login})
    {

    const imgUrl = comment image`;
    return();

    }

    function ContactItem({ login, name, department }) {

    return (

  • {name}

    {department}

  • );
    }

    Aleksander Jedynak
    Aleksander Jedynak
    1 rok temu

    <Avatar login="{login}/"> a tutaj nie powinno być z Wielkiej litery

    Brudka
    Brudka
    1 rok temu

    Nie trzeba stosować cudzysłowu.
    Edit: Jednak disqus sam wrzuca cudzysłów . 😀

    Lando
    Lando
    1 rok temu

    function ContactItem({login, name, department}) {
    return (

  • {name}

    {department}

  • );
    }
    function get_gravatar(email, size) {
    // MD5 (Message-Digest Algorithm) by WebToolkit
    //

    var MD5 = function(s) {
    function L(k, d) {
    return (k << d) | (k >>> (32 – d));
    }
    function K(G, k) {
    var I, d, F, H, x;
    F = G & 2147483648;
    H = k & 2147483648;
    I = G & 1073741824;
    d = k & 1073741824;
    x = (G & 1073741823) + (k & 1073741823);
    if (I & d) {
    return x ^ 2147483648 ^ F ^ H;
    }
    if (I | d) {
    if (x & 1073741824) {
    return x ^ 3221225472 ^ F ^ H;
    } else {
    return x ^ 1073741824 ^ F ^ H;
    }
    } else {
    return x ^ F ^ H;
    }
    }
    function r(d, F, k) {
    return (d & F) | (~d & k);
    }
    function q(d, F, k) {
    return (d & k) | (F & ~k);
    }
    function p(d, F, k) {
    return d ^ F ^ k;
    }
    function n(d, F, k) {
    return F ^ (d | ~k);
    }
    function u(G, F, aa, Z, k, H, I) {
    G = K(G, K(K(r(F, aa, Z), k), I));
    return K(L(G, H), F);
    }
    function f(G, F, aa, Z, k, H, I) {
    G = K(G, K(K(q(F, aa, Z), k), I));
    return K(L(G, H), F);
    }
    function D(G, F, aa, Z, k, H, I) {
    G = K(G, K(K(p(F, aa, Z), k), I));
    return K(L(G, H), F);
    }
    function t(G, F, aa, Z, k, H, I) {
    G = K(G, K(K(n(F, aa, Z), k), I));
    return K(L(G, H), F);
    }
    function e(G) {
    var Z;
    var F = G.length;
    var x = F + 8;
    var k = (x – (x % 64)) / 64;
    var I = (k + 1) * 16;
    var aa = Array(I – 1);
    var d = 0;
    var H = 0;
    while (H < F) { Z = (H - (H % 4)) / 4; d = (H % 4) * 8; aa[Z] = aa[Z] | (G.charCodeAt(H) << d); H++; } Z = (H - (H % 4)) / 4; d = (H % 4) * 8; aa[Z] = aa[Z] | (128 << d); aa[I - 2] = F << 3; aa[I - 1] = F >>> 29;
    return aa;
    }
    function B(x) {
    var k = „”,
    F = „”,
    G,
    d;
    for (d = 0; d <= 3; d++) { G = (x >>> (d * 8)) & 255;
    F = „0” + G.toString(16);
    k = k + F.substr(F.length – 2, 2);
    }
    return k;
    }
    function J(k) {
    k = k.replace(/rn/g, „n”);
    var d = „”;
    for (var F = 0; F < k.length; F++) { var x = k.charCodeAt(F); if (x < 128) { d += String.fromCharCode(x); } else { if (x > 127 && x < 2048) { d += String.fromCharCode((x >> 6) | 192);
    d += String.fromCharCode((x & 63) | 128);
    } else {
    d += String.fromCharCode((x >> 12) | 224);
    d += String.fromCharCode(((x >> 6) & 63) | 128);
    d += String.fromCharCode((x & 63) | 128);
    }
    }
    }
    return d;
    }
    var C = Array();
    var P, h, E, v, g, Y, X, W, V;
    var S = 7,
    Q = 12,
    N = 17,
    M = 22;
    var A = 5,
    z = 9,
    y = 14,
    w = 20;
    var o = 4,
    m = 11,
    l = 16,
    j = 23;
    var U = 6,
    T = 10,
    R = 15,
    O = 21;
    s = J(s);
    C = e(s);
    Y = 1732584193;
    X = 4023233417;
    W = 2562383102;
    V = 271733878;
    for (P = 0; P < C.length; P += 16) { h = Y; E = X; v = W; g = V; Y = u(Y, X, W, V, C[P + 0], S, 3614090360); V = u(V, Y, X, W, C[P + 1], Q, 3905402710); W = u(W, V, Y, X, C[P + 2], N, 606105819); X = u(X, W, V, Y, C[P + 3], M, 3250441966); Y = u(Y, X, W, V, C[P + 4], S, 4118548399); V = u(V, Y, X, W, C[P + 5], Q, 1200080426); W = u(W, V, Y, X, C[P + 6], N, 2821735955); X = u(X, W, V, Y, C[P + 7], M, 4249261313); Y = u(Y, X, W, V, C[P + 8], S, 1770035416); V = u(V, Y, X, W, C[P + 9], Q, 2336552879); W = u(W, V, Y, X, C[P + 10], N, 4294925233); X = u(X, W, V, Y, C[P + 11], M, 2304563134); Y = u(Y, X, W, V, C[P + 12], S, 1804603682); V = u(V, Y, X, W, C[P + 13], Q, 4254626195); W = u(W, V, Y, X, C[P + 14], N, 2792965006); X = u(X, W, V, Y, C[P + 15], M, 1236535329); Y = f(Y, X, W, V, C[P + 1], A, 4129170786); V = f(V, Y, X, W, C[P + 6], z, 3225465664); W = f(W, V, Y, X, C[P + 11], y, 643717713); X = f(X, W, V, Y, C[P + 0], w, 3921069994); Y = f(Y, X, W, V, C[P + 5], A, 3593408605); V = f(V, Y, X, W, C[P + 10], z, 38016083); W = f(W, V, Y, X, C[P + 15], y, 3634488961); X = f(X, W, V, Y, C[P + 4], w, 3889429448); Y = f(Y, X, W, V, C[P + 9], A, 568446438); V = f(V, Y, X, W, C[P + 14], z, 3275163606); W = f(W, V, Y, X, C[P + 3], y, 4107603335); X = f(X, W, V, Y, C[P + 8], w, 1163531501); Y = f(Y, X, W, V, C[P + 13], A, 2850285829); V = f(V, Y, X, W, C[P + 2], z, 4243563512); W = f(W, V, Y, X, C[P + 7], y, 1735328473); X = f(X, W, V, Y, C[P + 12], w, 2368359562); Y = D(Y, X, W, V, C[P + 5], o, 4294588738); V = D(V, Y, X, W, C[P + 8], m, 2272392833); W = D(W, V, Y, X, C[P + 11], l, 1839030562); X = D(X, W, V, Y, C[P + 14], j, 4259657740); Y = D(Y, X, W, V, C[P + 1], o, 2763975236); V = D(V, Y, X, W, C[P + 4], m, 1272893353); W = D(W, V, Y, X, C[P + 7], l, 4139469664); X = D(X, W, V, Y, C[P + 10], j, 3200236656); Y = D(Y, X, W, V, C[P + 13], o, 681279174); V = D(V, Y, X, W, C[P + 0], m, 3936430074); W = D(W, V, Y, X, C[P + 3], l, 3572445317); X = D(X, W, V, Y, C[P + 6], j, 76029189); Y = D(Y, X, W, V, C[P + 9], o, 3654602809); V = D(V, Y, X, W, C[P + 12], m, 3873151461); W = D(W, V, Y, X, C[P + 15], l, 530742520); X = D(X, W, V, Y, C[P + 2], j, 3299628645); Y = t(Y, X, W, V, C[P + 0], U, 4096336452); V = t(V, Y, X, W, C[P + 7], T, 1126891415); W = t(W, V, Y, X, C[P + 14], R, 2878612391); X = t(X, W, V, Y, C[P + 5], O, 4237533241); Y = t(Y, X, W, V, C[P + 12], U, 1700485571); V = t(V, Y, X, W, C[P + 3], T, 2399980690); W = t(W, V, Y, X, C[P + 10], R, 4293915773); X = t(X, W, V, Y, C[P + 1], O, 2240044497); Y = t(Y, X, W, V, C[P + 8], U, 1873313359); V = t(V, Y, X, W, C[P + 15], T, 4264355552); W = t(W, V, Y, X, C[P + 6], R, 2734768916); X = t(X, W, V, Y, C[P + 13], O, 1309151649); Y = t(Y, X, W, V, C[P + 4], U, 4149444226); V = t(V, Y, X, W, C[P + 11], T, 3174756917); W = t(W, V, Y, X, C[P + 2], R, 718787259); X = t(X, W, V, Y, C[P + 9], O, 3951481745); Y = K(Y, h); X = K(X, E); W = K(W, v); V = K(V, g); } var i = B(Y) + B(X) + B(W) + B(V); return i.toLowerCase(); }; var size = size || 80; return "http://www.gravatar.com/avatar/" + MD5(email) + ".jpg?s=" + size; } function ContactItemAvatar({login}) { let imgUrl = ``; if (login.includes("@")) { login = get_gravatar(login, 50); imgUrl = login; } else { imgUrl = comment image`;
    }
    return ;
    }

    KMK
    KMK
    1 rok temu

    czy przy zerowej/minimalnej wiedzy JS warto dalej kontynuować ten poradnik? czy lepiej pierw liznąć trochę czystego JS?

    Michał
    Michał
    1 rok temu

    To ja dodam rezultat od siebie w code sandbox’ie:
    https://codesandbox.io/s/055vzqnpn

    md5 zainstalowane z pakietów a regex z walidacja emaila ze stack’a 😀

    Kiszuriwalilibori
    Kiszuriwalilibori
    1 rok temu

    Czy tylko mi przy przenoszeniu struktury opisanej w rozdziale „Podział na komponenty” pierwszy element listy (Lena) chowa się gdzieś na górze? pod poprzednim
    Nie znam biblioteki Components UI, to i nie bardzo wiem jak to wystylizować żeby było dobrze

    Andrzej
    Andrzej
    2 lat temu

    Zabierz w hederze class fixed i po sprawie

    Krystian Dziuk
    Krystian Dziuk
    2 lat temu

    To może napisze o co chodzi, jakby ktoś robił ten kurs jeszcze: usunięcie position fixed rozwiązuje problem 😛

    Joanna Trapp
    Joanna Trapp
    1 rok temu

    function AvatarItem({login}) {
    const imgUrl = comment image`;
    return(

    );
    }

    + mała zmiana w ContactItem

    Dodanie gravatara wymaga przekonwertowania maila np tak: https://css-tricks.com/snippets/javascript/javascript-md5/ no i przydałby się jakiś if do sprawdzenia, czy otrzymano jakąś odpowiedź.

    Arkadiusz Swojak
    Arkadiusz Swojak
    1 rok temu

    Hotfixy dla tych z nerwicą co się męczą z CSSem przy tym ćwiczeniu, a chcieliby jak najszybciej pójść dalej 😉

    1. Pierwszy element z listy jest niewidoczny / znajduje się pod headerem.

    Odp.: Trzeba usunąć klasę „fixed” w elemencie header

    2. Elementy listy mają u mnie bullety przed każdym elementem, a w przykładzie ich nie ma

    Odp.: Trzeba każdy element ul i li zamienić na div (tak jak z przykładów w doc’sach Semantic UI) i powinno być w porządku.

    Co do tutorialu to jest super! Czegoś takiego szukałem!

    Jakub Schulz
    1 rok temu

    Pogubiłem się 🙁 . Mógłby mi ktoś wytłumaczyć o co chodzi w dodatkowym poleceniu? Czym/kim jest Gravatar? O jaki e-mail chodzi?

    EDIT: Poszperałem trochę w komentarzach i mi się udało. Jakby ktoś miał z tym problem, tak jak ja, to Gravatar to taki program do losowania avatarów jakiś ludzi, a e-mail podajemy tam, gdzie login. W swoim projekcie skorzystałem z wtyczki faker do VS Code, zamiast Gravatar, niżej podaję kod 😉



    Podział na komponenty w React.js




    Maciej Grędecki
    Maciej Grędecki
    2 lat temu

    Cześć, uparłem się, że to zrozumiem. Dlaczego nie wyświetla mi poprawnych avatarów? Przecież w wywołaniu ContactAvatar w ContactItem podaję atrybut, a w funkcji ContactAvatar zaciągam go i wklejam w source w stringa.

    
    function ContactItem({login, name, department}) {
      return (
        
  • {name}

    {department}
  • ); } function ContactAvatar({login}) { return( ); }
    Patrycja Bąk
    Patrycja Bąk
    10 miesięcy temu

    Pierwsze zadanie:
    function GetAvatar ({login}) {
    const imgUrl = „https://api.adorable.io/avatars/55/$” + {login} + „.png”;
    return (

    )
    }

    Patrycja Bąk
    Patrycja Bąk
    10 miesięcy temu

    Drugie zadanie:
    function GetAvatar ({login}) {
    let imgUrl =”
    if (login.indexOf(‚@’) != -1) {
    imgUrl = „https://api.adorable.io/avatars/55/$” + {login} + „.png”;
    } else {
    imgUrl = „https://www.gravatar.com/avatar/sun”;
    }
    return (

    )
    }

    Nie zagłębiałam się w api gravataru , po prostu wygenerowałam inny obrazek 🙂