Czechitas-podklady-WEB / daweb-vyuka

Studijní materiály pro DA Web na kodim.cz
https://kodim.cz/czechitas/daweb/
4 stars 38 forks source link

Grafomanský výlev na téma chybových hlášek #784

Open jficz opened 2 months ago

jficz commented 2 months ago

Můj trochu delší příspěvek na slacku. Dávám sem, aby se to nezmizelo, můžeme z toho třeba někdy časem vyextrahovat něco přímo do lekce.


index.jsx:18 Uncaught TypeError: Cannot read properties of undefined (reading 'add')
...

TypeError velmi obecně naznačuje, že někde pravděpodobně nesedí typy proměnných. To je první indicie, která nás může navést správným směrem, byť zrovna v Javascriptu je chyba typu TypeError spíš zavádějící, než užitečná.

Naštěstí se tu chybu snaží vysvětlit hned v další větě: Cannot read properties of <něco>:

Properties mají jen objekty. Například když máme objekt person = { name: "Blanka", age: "21" }, tak name a age jsou "properties" objektu person. Hláška Cannot read properties of <něco> říká, že se v kódu snažíš přistoupit k property, kterou to něco mít nemůže, což speciálně v Javascriptu pravděpodobně znamená, že to něco neexistuje.

A to je i náš případ, protože to něco je ve skutečnosti undefined. Kdyby ta hláška skončila tady, tak by to pro nás zas tak užitečné nebylo, protože nevíme, co přesně z toho řádku je undefined a tak tu máme poslední nápovědu, text v závorce: (reading 'add'). Tím nám říká, že ta property, kterou nemůže přečíst, se jmenuje add.

index.jsx:18 Uncaught TypeError: Cannot read properties of undefined (reading 'add')
^^^^^^^^^ 
|_______|--- jméno souboru, kde je chyba

index.jsx:18 Uncaught TypeError: Cannot read properties of undefined (reading 'add')
          ^^
          ||--- řádek v souboru, kde je chyba

index.jsx:18 Uncaught TypeError: Cannot read properties of undefined (reading 'add')
             ^^^^^^^^^^^^^^^^^^
             |________________|--- typ/kategorie chyby

index.jsx:18 Uncaught TypeError: Cannot read properties of undefined (reading 'add')
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     konkrétní chybová hláška ---|_________________________________________________|

A dál to můžeme rozebrat takhle:

Uncaught TypeError === nesedí typy proměnných. V Javascriptu bohužel trochu matoucí. K pochopení je nutné přečíst si celou chybovou hlášku.

Chybová hláška je

Cannot read properties of undefined (reading 'add')
^^^^^^^^^^^^^^^^^^^^^^^^^
|_______________________|--- popis konkrétního problému (`nemůžu přečíst (nějakou) property`)

Cannot read properties of undefined (reading 'add')
                          ^^^^^^^^^
                          |_______|--- "tohle je ta věc, u který nemůžu přečíst property"

Cannot read properties of undefined (reading 'add')
                                     ^^^^^^^ ^^^^^
                                     |_____|+|___|--- property, kterou se snažím přečíst, se jmenuje 'add'

Abychom pak mohli zanalyzovat tu konkrétní chybu, musíme vycházet z těhle informací.

Víme soubor (index.jsx) a řádek (18), tak se tam podíváme. Pravděpodobně tam je tohle:

  ? bulb.classList.add('bulb--on')

Teď už budeme muset aplikovat nějaké znalosti a zkušenosti. A dbát na dobré rady zkušenějších. Jedna taková dobrá rada je "přečti si tu chybovou hlášku vždycky nejdřív úplně celou do konce".

Uncaught TypeError je divná věc, které nerozumíme a nic moc nám sama o sobě neřekneme, budeme tedy číst dál.

Cannot read property of undefined už nám může dávát trochu smysl, protože víme co je property a tušíme, co je undefined. Na tom řádku (na první pohled) vidíme dvě věci, co můžou být property, classList a add, ale nevidíme tam žádný undefined.

Čteme dál: (reading 'add')

A jsme doma! Teď už je jasné, že k chybě došlo při pokusu o "načtení" property add, protože to něco, z čeho se tu property snažíme načíst, je undefined. My se tady to add snažíme načíst (přesněji v tomhle případě "zavolat", protože je to funkce) z bulb.classList. To může znamenat jen jednu věc - že bulb.classList je undefined.

Už ale nevíme proč je undefined. S tím nám bohužel ta chybová hláška vůbec nijak nepomůže. Na to už budeme muset zapojit šedou kůru, fantazii, znalosti a zkušenosti.

Víme, že bulb je něco, co jsme si sami vytvořili - nejlepší je tedy začít tam, kde ten bulb vzniká.

Proč rovnou celý bulb a proč neřešíme bulb.classList? (nejméně) ze tří důvodů: 1) bulb jsme si vytvořili my, je tedy zdaleka nejpravděpodobnější, že k nějaké chybě došlo při vytváření 2) classList je property, o které víme že ji ten bulb musí mít, pokud je vytvořen správně (samozřejmě po tom, co jsme si důkladně zkontrolovali překlepy :wink: ) 3) ze zkušenosti časem budeme vědět, že tahle konkrétní chyba znamená, že bulb sice (v nějaké formě) existuje, ale bulb.classList už ne, což je v rozporu s bodem 2 a prakticky potvrzuje bod 1

To nám poměrně jasně naznačuje, že v bulb máme něco jiného, než co tam předpokládme. Konkrétně předpokládáme, že tam máme nějaký element. Každý element má property classList, náš bulb ale žádný classList nemá. Co s tím?

Podívejme se, jak bulb vzniká:

const bulb = document.querySelectorAll('.bulb');

Tady by nás mělo trknout, že děláme querySelectorAll(), který, už podle názvu, pravděpodobně bude vracet víc elementů najednou. Pokud si to z hlavy nepamatujeme*, podíváme se do dokumentace, kde se (mimo jiné) říká, že querySelectorAll() vrací pole elementů (array of elements), tudíž je jasné, že v proměnné bulb nemáme element, ale pole. A pole nemá property classList.

Jak to opravit? To už záleží na tom, čeho chceme dosánout. V tomhle případě chceme skutečně zpracovat všechny žárovky, tudíž chyba je primárně na řádku 18 (ale zároveň by bylo fajn tu proměnnou přejmenovat na bulbs) a musíme ji opravit tam. Pravěpodobně nějakým cyklem (např. forEach).

A po tom, co provedeme celou tuhle poměrně náročnou analýzu a syntézu, zjistíme, že to vlastně máme udělat úplně jinak a celý kód zahodíme. Vitejte ve světě programování! :)

*) nikdo po vás nikdy nebude chtít, abyste si všechno pamatovaly. Mnohem užitečnější je umět si informace najít

podlomar commented 2 months ago

Kubo, pojď to napsat jako článek na blog Kódím.cz

jficz commented 2 months ago

dobrej nápad :) okej, zkusim to nějak učesat a zgeneralizovat