squint 2024-10-22

And thanks to @tonsky for the logo of course!

1
❤️ 1

I'm using jotai atom as the global state, akin to how you'd use re-frame, and then React useState for the ephemeral component state, seems to work pretty well

🎉 1

Interesting. What's the utility of the anime/setAnime over deref/dispatch? Does it keep the read/writes more coordinated in some way?

Or I guess another way to ask - if it were possible to put a deref/dispatch idiom over jotai's api, would that be a good idea or a bad idea? And why?

I think slapping deref/dispatch over jotai would work fine, and jotai also supports cursors

so you effectively have reagent semantics with it

I find the biggest advantage of reagent approach over hooks is that the state of the data isn't coupled to the DOM tree, and you can inspect it any time you want, you also don't have to jump through hoops if you have two components in a tree that need to share state

@yogthos the same author also has a different state handling library called zustand: https://github.com/pmndrs/zustand not sure what the trade-offs are

admittedly, I only skimmed the other lib, but I get the impression that jotai fits better with clj semantics

yeah, but perhaps there's performance considerations. not sure. I also noticed that zustand works with immer as well

that could be handy, but yeah not sure what the implications are for bigger apps

it does look like jotai also has immer extension btw https://jotai.org/docs/extensions/immer

and just tried it, looks like it works seamlessly

(ns App
  (:require
   ["jotai" :as jotai :refer [useAtom]]
   ["jotai-immer" :as jotai-immer :refer [atomWithImmer]]
   ["react" :refer [useState]]))

(def !anime (atomWithImmer
             [{:title "Ghost in the Shell"
               :year 1995
               :watched true}
              {:title "Serial Experiments Lain"
               :year 1998
               :watched false}]))

how do you mutate the atom?

the example still uses useAtom according to the docs immer atom provides a different writeFunction which I assume leverages structural sharing?

I mean, how do you change the value

oh that's same as before

(let [anime setAnime] (useAtom !anime)]
  ...)

the setter function handles the updating

although now I'm curious if you can update a specific value this way since setter just takes a whole new state

so the setter function does the draft stuff

and then you should just use the mutation ! functions from squint

so it's basically a swap?

yeah looks like

specific value, do you mean like a cursor?

I wonder how hard it would be to make a little wrapper around jotai + immer that provides reagent semantics 🙂

I was thinking something like (swap! foo assoc :bar :baz)

well immer expects you to really mutate the value

since it watches it via some proxy layer

so I guess here it would be (setAnime (assoc! anime :foo :bar))

so you'd use assoc! and conj! etc

and magic happens? 🙂

yes, this is why I asked how you did it ;)

that's the idea of immer

mmm, looks like setAnime would take a function that takes the draft

it looks like you can pass a draft to it as well