Dzisiaj na tapet trafia książka Pawła Kamińskiego React. Wstęp do programowania.
Miejmy to już za sobą: tak, książka jest już częściowo nieaktualna. Zawiera bowiem opis Reacta 16, podczas gdy mamy już Reacta 18. Dodatkowo pozmieniały się też nieco biblioteki opisywane w pozycji (np. React Router). Ale dopóki nie upowszechni się coś, co można nazwać Continuous Publishing (Ciągłe Wydawanie), to raczej tego problemu się nie uda rozwiązać.
Chyba najpoważniejszym zarzutem, jaki mam względem tej książki, jest fakt, iż jej większość poświęcona została komponentom klasowym. Na samym początku autor wprowadza podział na komponenty klasowe, które zawierają logikę, oraz komponenty funkcyjne, służące wyłącznie do renderowania przekazanych im informacji. Niemniej w ostatnim rozdziale, poświęconym hookom, przyznaje, iż hooki są w tej chwili popularniejszym sposobem tworzenia aplikacji w Reakcie (s. 271-272), co niejako zaprzecza podziałowi widocznemu w całej reszcie książki. Nie sądzę, by w tej chwili (ani w roku 2021, kiedy książka wyszła) należało poświęcać tyle uwagi komponentom klasowym zamiast funkcyjnym. Według mnie większość kodu w książce powinna wykorzystywać właśnie komponenty funkcyjne i hooki. Natomiast komponentom klasowym w zupełności wystarczyłby ostatni rozdział, w którym zaprezentowana byłaby alternatywna metoda tworzenia komponentów, która w tej chwili jest rzadziej preferowana przez developerów.
Drugim poważnym zarzutem jest to, iż książka zaczyna się od krótkiego wprowadzenia do języka TypeScript. Problem polega na tym, iż po tym wprowadzeniu TypeScript nie jest użyty już ani razu w dalszej części książki – cały kod w Reakcie napisany jest przy pomocy czystego JavaScriptu. Co więcej, odniosłem w trakcie lektury wrażenie, iż TS i JS są traktowane jako synonimy – a to nie jest prawda. To mimo wszystko dwa oddzielne języki. W jednym miejscu JSX również jest zrównywany z TS-em, gdy autor stwierdza, iż Babel służy do transpilacji TS-a do JS-a (s. 78) – podczas gdy transpilowany był właśnie kod w JSX-ie.
W książce jest też nieco błędów merytorycznych. Jednym z nich jest nazwanie hoistingu (wynoszenia) użyciem zmiennej przed jej zadeklarowaniem (s. 37-38). Możliwość użycia zmiennej przed deklaracją jest jedynie możliwym skutkiem ubocznym istnienia hoistingu – a i to nie zawsze występującym. Co więcej, definicja zaproponowana w książce oznaczałaby, iż w przypadku let i const hoisting nie występuje, co nie jest prawdą. Hoisting występuje przy każdym rodzaju deklaracji zmiennej i jest w rzeczywistości „wynoszeniem” jej deklaracji na początek zakresu (np. bloku lub funkcji). To, iż w przypadku let i const nie da się użyć zmiennej przed miejscem jej zadeklarowania w kodzie, jest związane z zupełnie innym mechanizmem – Temporal Dead Zone.
Temat hoistingu powraca nieco później, gdy mówione jest, iż IIFE przed nim chroni (s. 51-52). To nie jest prawdą, bo wewnątrz IIFE hoisting też zachodzi. IIFE chroni przed czymś innym: wyciekaniem zmiennych do zasięgu globalnego. Dodatkowo, w przypadku deklaracji zmiennej przy pomocy słów kluczowych let i const, IIFE może zostać zastąpione zwykłym blokiem.
A skoro już jesteśmy przy zasięgu globalnym, jest także poruszony temat wskazywania przez this domyślnie na obiekt globalny wewnątrz funkcji niebędącej metodą obiektu. Jako przykład jest podane this.price, które ma zostać nadpisane przez zmienną globalną price, deklarowaną przez słowo najważniejsze let. Mniej więcej chodzi o taki przypadek:
let price = 100; function test() { console.log( this.price ); } test();Problem polega na tym, iż do nadpisania nie dojdzie i console.log() wyświetli undefined. Spowodowane jest to tym, iż this.price w tym kodzie równoznaczne jest z window.price. Ale zmienna globalna price nie jest tym samym, co window.price. Zmienne globalne, które równocześnie są własnościami obiektu window, stworzyć można wyłącznie przy pomocy słowa kluczowego var. Co więcej, istnieje prosty sposób, aby wyłączyć podstawianie obiektu globalnego pod this: włączyć tryb ścisły. Wówczas użycie this poza obiektem spowoduje błąd:
'use strict'; // Włączamy tryb ścisły. let price = 100; function test() { console.log( this.price ); // Błąd, ponieważ teraz this === undefined. } test();Na stronie 42. z kolei jest informacja, jakoby TS pozwalał nadpisać typ zmiennej. Nie jest to prawda i zaprezentowany kod wyrzuca w TS-ie błąd. Gdyby tak się nie działo, stosowanie TS-a nie miałoby tak po prawdzie sensu.
Jest też kilka innych mniejszych błędów merytorycznych i złych praktyk, takich jak zagnieżdżanie obietnic (s. 71) czy błędny opis metod HTTP (s. 194-195)
Nie mógłbym też nie wspomnieć o błędnym tłumaczeniu destrukturyzacji, która została przemianowana na przypisanie destrukcyjne (s. 143). Co ciekawe, jest tam choćby podany „oryginał” angielski, destructive operator (operator destrukcyjny). I, prawdę mówiąc, ciekawi mnie, skąd dokładnie pochodzi taki termin.
W książce jest też spory problem ze skrótowcami. Mamy zatem – dość często spotykane – NPM (rozwijane dodatkowo do Node Package Manager) zamiast npm, AJAX zamiast Ajax czy SASS zamiast Sass.
Na początku znajduje się także opis różnic między SPA a MPA (s. 12-15), który sugeruje, iż w przypadku MPA przejścia pomiędzy podstronami są zawsze statyczne i ogólnie strony te wykazują się zdecydowanie mniejszą dynamicznością. A to nie jest prawda – można tworzyć aplikacje łączące cechy SPA i MPA. Osobiście uważam to wręcz za dobrą praktykę.
Warto też chwilę pochylić się nad jakością samego wydania. Na stronie 38. spotkać można źle złożoną tabelkę, która miała pokazywać, czym różnią się poszczególne sposoby deklarowania zmiennych (var, let i const). Niemniej brak odpowiednich krawędzi między komórkami sprawia, iż let i const wyglądają na opisane osobno, mimo iż są opisane razem. W wielu innych miejsach w kodzie prezentowanym od nowej linii pojawia się duża litera na początku (np. Const zamiast const), co sprawia, iż kod staje się błędny.
No i zastanawia mnie jeszcze jedno: książka została wydana w listopadzie 2021 roku. W jej treści natomiast znajduje się informacja, iż najnowsza wersja standardu to ta z 2020 (s. 17). Wersje ES wychodzą zawsze w czerwcu, co oznacza, iż książka musiała powstać w okresie od czerwca 2020 do maja 2021. Z innych części książki (np. przypis na stronie 12.) wywnioskować można, iż książka powstała w wakacje 2020 roku. Pytanie zatem, dlaczego została wydana niemalże 1.5 roku później? W świecie technologii webowych, a zwłaszcza bibliotek pokroju Reacta, to jest praktycznie wieczność… To nie pierwszy raz, gdy zwracam uwagę na opóźnione wydanie książki. Mam tylko nadzieję, iż to nie jest jakiś trend a pojedyncze przypadki.