Fork me on GitHub
#clojure-norway
<
2023-07-16
>
slipset07:07:18

Hørte akkurat https://podcasts.apple.com/no/podcast/software-unscripted/id1602572955?i=1000620749913 og syntes den var interessant. Det slo meg at det var et par spm som ikke ble stilt, et av dem var f.eks hvorfor må React komponenter ha bivirkninger.

👀 6
cjohansen08:07:53

Allerede ett minutt inn får høre at et av problemene som skulle løses var "mye duplisert logikk på tvers av komponenter" 😅

cjohansen08:07:45

Ny API-overflate og ny implisitt logikk kommer langt ned på min liste over løsninger på det problemet 😅

cjohansen08:07:00

Men ok, prøver meg med et åpent sinn

cjohansen08:07:53

> I don’t think it was ever clear at the time why you would write it as a function component

cjohansen08:07:25

Denne designprosessen fremstår noe mindre gjennomtenkt enn hva man er vant til fra feks Clojure

cjohansen08:07:45

Denne historien om fibers var interessant. Såvidt jeg forstår så skrev de om hele react til å være async pga problemer som lokal state introduserer? Det virkelig mind blowing her er at de da ikke bare lagde noe nytt. Dersom den underliggende modellen ikke lenger passer så må det være enklere å lage en ny ting enn å snu en bauta

cjohansen09:07:03

"This component has no UI but it does have behavior" 😬 😬

cjohansen09:07:55

Jeg liker formatet og "programlederen" godt, skal høre mer på denne podcasten.

cjohansen09:07:27

> It's pure in the form that it's a function of its arguments and its internal state

😂 4
cjohansen09:07:43

Haha, ja hva skal vi egentlig med ord

teodorlu12:07:39

Jeg synes det er påfallende at Trinh kun sammenlikner "ny React" med "gammel react". Lite fokus på andre løsninger på samme problem. Kudos til Feldman for å gå inn og ta de dialogene.

cjohansen12:07:31

Ja, og argumentasjonen virker veldig prøvende. Hver gang et argument blir plukket fra hverandre finner han frem et nytt, og til slutt har han sagt seg selv imot. Fikk inntrykk av at designprosessen hadde fungert etter samme prinsipp

augustl08:07:15

har hørt første 12 min bare, men tenker at gitt at rendring-steget trenger state (antagelsen til React fra dag 1) er hooks uten tvil ekstremt mye bedre enn OO-greiene de startet med 😇

cjohansen09:07:27

Jøss, så forskjellig kan man altså se ting

😄 2
cjohansen09:07:04

Jeg er forøvrig uenig i den underliggende antagelsen om state også, men der er jeg i minoritet

augustl09:07:31

man kan jo bruke N hooks i samme komponent, det blir vanskeligere med OO

cjohansen09:07:53

Alle eksemplene som kommer opp er på ting som ikke burde kombineres i renderingsteget. De prater stadig vekk om den komponenten som oppdaterer document.title feks. 🔴 wrong answer! Hvorfor skjer det rett fra en komponent??

cjohansen09:07:13

Ikke uenig i at noen form for funksjonskomposisjon er et bedre API for å kombinere vilkårlig oppførsel, men veldig skeptisk til det greiene react har endt opp med

cjohansen09:07:24

React-komponenter som svar på alt er jquery plugins all over. Løsningen er fortsatt den samme: løs det meste på utsiden og lag tynt lim i mellom.

slipset09:07:04

Det var litt sånn jeg følte det også. Bare drit i state i komponenten din, og du har løst alle disse problemene.

augustl09:07:56

ja, føler det er der kjernen av debatten ligger. Eneste ting jeg kommer på som utvilsomt er bedre med hooks er å gjøre global event listening. Typ lytt på click på window inne i en komponent for å skjule en drop-down når man trykker utenfor den, sånt blir fort litt mere knot å orkestrere globalt

augustl09:07:55

aka hooks er fint til å lage dine egne helt generiske greier om ikke annet, det er vel ikke akkurat veldig irriterende at en <select> har intern tilstand på sånne ting og det er kjekt å kunne gjøre sånt i dine egne komponenter og. Ingen businesslogikk, altså

slipset09:07:58

Det er to problemer jeg ser med bare stateless komponenter: 1. Det er noe mer krøbelt å håndtere slik local state, fordi man er avhengig av et state-maskineri på “utsiden”. 2. Det er noe mer krøbelt å lage komponent bibilioteker fordi man er avhengig av en eller annen form for state-management utenfor komponenten selv

cjohansen10:07:49

Ja, det er en tradeoff

slipset10:07:23

Men, man kunne jo funnet en vei rundt det og, hadde man prøvd litt.

const myThingWithLocalState = (props) => {
  const state = {};
  const stateManagement = ...// noe mer mekk og mygel for å manipulere state
  return myPureThing = ({...state, ...stateManagement, ...props}) => {
    ...
  }
}

cjohansen10:07:35

Jepp. Og som du er inne på: det kan løses uten konkrete rammeverk, bare funksjoner.

slipset10:07:04

Problemet her er vel at myThingWithLocalState ikke rerendrer dersom vi endrer state?

slipset10:07:53

Men nå beveger jeg meg så langt utpå dypt vann at det er vanskelig å svømme tilbake.

😄 2
augustl10:07:29

stemmer, man trenger vel hooks (pun intended?) inn til renderingen for at den skal rendre på nytt osv

😄 2
slipset10:07:55

react.pleaseRerender(this)

augustl10:07:58

og så trenger man "kall denne på unmount" etc - og finner opp hooks på nytt :)

slipset10:07:41

Jo, men det jeg aldri helt skjønte fra podcasten var problemene med de gamle onWhatever hooksa?

augustl10:07:54

du kan ikke ha to "gjør dette på unmount" i samme komponent

slipset10:07:08

Jeg merker meg et par ting mhp hooks: 1. Utviklere bruker flere useState i samme React komponent, f.eks i en form, så bruker man en useState pr form element. 2. For meg så er useEffect nærmest uleselig

augustl10:07:23

med hooks kan du lage en helt gjenbrukbar frittstående sak for å lagre bittelitt state, lytte på noen events, osv

slipset10:07:26

Men hvorfor i alledager vil du ha to “gjør dette på unmount”?

slipset10:07:28

const onUnmount = (whatever) => {
  doThis(whatever);
  doThat(whatever);
}
Dette er da ikke rakettkirurgi?

augustl10:07:32

er ute og går, skal komme med noen eksempler etterpå

slipset10:07:20

> med hooks kan du lage en helt gjenbrukbar frittstående sak for å lagre bittelitt state, lytte på noen events, osv åh, du mener en funksjon?

augustl10:07:46

en funksjon vet ikke noe om render staten :)

slipset10:07:11

åjoda, hvis den bare får den som parameter.

slipset10:07:10

Jeg merker meg at det kommer en kjemperant her fra meg, snart!

😅 2
slipset10:07:14

Men den kan kondenseres ned i en tweet: > De fleste utviklere velger feil når de velger hvilke funksjoner som skal navngis og hvilke som skal være anonyme

cjohansen10:07:53

Jeg skjønner ikke hvordan react holder styr på state med hooks jeg. Du kaller en funksjon, og så kaller den useState. Hvordan i kættæn vet react hvilken state som skal hvor?

slipset10:07:30

const [setUsername, getUsername] = useState(username);
Sånn ca.

slipset10:07:14

useState returnerer en array med funksjoner som du skal bruke for å manipulere state’n.

slipset10:07:54

Et av poengene til programlederen var jo at “dette er så iffy at du burde føle litt smerte når du gjør det”. Jeg synes det er et godt poeng.

slipset10:07:11

hooks gjør jo alt som er feil enklere å gjøre 🙂

cjohansen10:07:40

Ja, kjempepoeng

cjohansen11:07:16

Det jeg ikke skjønner er hvordan du ender opp med samme state når funksjonen som gjør det der kalles flere ganger.

cjohansen11:07:12

Når du har endt opp med et API som du trenger en lint-regel til som stopper deg fra å bruke den i en conditional så burde du ha tenkt litt lenger på problemet

augustl11:07:07

den avhenger av rekkefølgen de kalles i. Så du kan ikke ha hooks i en if-statement i render-funksjonen

cjohansen11:07:08

Så rekkefølgen er det implisitte limet jeg etterlyste over?

cjohansen11:07:45

Hvordan håndterer den da at en komponent får et nytt barn som har en hook?

augustl11:07:12

eksempel på kode som er lettere å få til med hooks enn klasser imo. Veldig kjekt å kunne ha en liten lokal effect som selv avgjør om den skal ha en teardown (hvis visible? ikke er true, returnerer den ikke en funksjon, og funksjonen som returneres av effekten = teardown når input-props endres)

(let [element-id (js/React.useId)]
        (js/React.useEffect
          (fn []
            (when visible?
              (let [global-click-listener
                    (fn [e]
                      (when (not (.. e -target (closest (str "#" element-id))))
                        (on-visibility-change false)))]
                (js/window.addEventListener "click" global-click-listener)
                (fn []
                  (js/window.removeEventListener "click" global-click-listener)))))
          (clj->js [visible?]))

        ...hiccup...)

augustl11:07:22

lista med hooks er lokal til et komponent, så det hånterer react-renderen uten problemer

augustl11:07:49

en annen ting som er kjekt med useEffect vs OO-metodene, er at man kan ha to av de i samme funksjon, som kan lene seg på hvert sitt dependency-array og gjøre hver sin teardown i ulike faser osv osv

augustl11:07:33

husker også at jeg fikk lettere bakoversveis når jeg så functional components med hooks for første gang og lurte på akkurat det samme, hvordan i alle dager funker denne magien liksom. Mulig det er stockholm-syndrom, men for meg føles dette som en helt naturlig primitiv nå

augustl11:07:14

har en del andre eksempler på “kjekke hooks” for hånden - men de lider av at all state-håndtering i hele appen gjøres av React (ikke mitt valg…) så det er kanskje ikke så nyttig å dele… 😄

cjohansen11:07:13

Php-style er kanskje det beste man kan få til som har bred appell :man-shrugging:

augustl11:07:02

jeg må innrømme at jeg ikke ser noe feil med at et komponent som har et klikk-event som viser noe dropdown-aktige greier, bruker en hook som i koden over til å også skjule seg selv på window click utenfor dropdownen

cjohansen11:07:44

Nei, ikke noe galt i akkurat det. Men det er jo bare et helt minimalt utvalg av hva folk bruker dette sølet til

augustl11:07:12

et godt poeng… 😄

cjohansen11:07:39

På én måte er det bra at CLJS ikke gikk for elm-modellen og heller omfavnet eksisterende js-løsninger. På den annen side syns jeg det er trist at cljs-miljøet er så innmari fornøyd med mye av rælet fra JS-verdenen, I stedet for å bygge opp et solid alternativ "av og for" Clojure

augustl11:07:19

reagent og re-frame er vel på en måte bare cljs-land som har funnet opp sitt eget (dårligere?) API for hooks ja 😞

augustl11:07:47

fin diskusjon her egentlig - har slitt med å skjønne hvorfor folk har en beef med enkle react-hooks som bare gjør suuuper-basic ting som man kan se på som utvidet rendring-logikk og ikke noe business-logikk-greier. Og det var jo ikke rart, for det var ingen beef 😄

augustl11:07:48

har Richard Feldman gjort noe i Clojure-miljøet forresten? Kjenner han veldig igjen fra et eller annet, men husker ikke hva…

teodorlu12:07:13

> har Richard Feldman gjort noe i Clojure-miljøet forresten? Kjenner han veldig igjen fra et eller annet, men husker ikke hva… Feldman har hatt både https://open.spotify.com/episode/5NwerUaneNq46lENS83Ycm?si=af81750966854738 og https://open.spotify.com/episode/55b6ZseffvlVVj5iCtUg1p?si=4e4da2f069dc4933 på besøk i podkasten sin, men jeg tror ikke han har brukt en seriøs menge tid på å sette seg inn i Clojure. Største problemet jeg ser med sterkt typede språk som Haskell og Elm (og kanskje også Roc, uten at jeg har brukt det) er herk rundt serialisering og deserialisering av data. Når man først har typer, vil man gjerne at de typene gir garantier. Da må man ta stilling til hvilke verdier som er kjent, og hvilke som ikke er kjent. Rich snakker litt om dette i https://www.youtube.com/watch?v=YR5WdGrpoug. Feldman var sentral i Elm-miljøet, hvis det var noe du brydde deg om!

augustl13:07:43

det står skrevet… Liker også at Hickey gir Kotlin tommel opp, der har man typesikker null-håndtering uten å brekke bakoverkompabilitet om man gjør noe så ekstremt som å si at en funksjon som før returnerte en optional foo nå alltid returnerer en foo

😁 2
teodorlu13:07:35

Hvis det står i en bok, er det nok sant! 😁 Godt poeng at det er fint å ha kontroll over serialiseringen, og ikke sende med noe man ikke ønsker på vei ut.