squint

pez 2024-10-22T10:38:41.297149Z

Thanks for creating this awesome t-shirt, @borkdude! 🙏 https://x.com/pappapez/status/1848673030970520005?s=46&t=2szMNNiUUdq3HoUKFCutLg

2
🔥 1
❤️ 8
3
borkdude 2024-10-22T10:39:09.607489Z

\m/

borkdude 2024-10-22T11:09:53.082049Z

And thanks to @tonsky for the logo of course!

1
❤️ 1
yogthos 2024-10-22T15:19:08.537539Z

made a more fleshed out example for jotai/react https://github.com/yogthos/squint-jotai-example/blob/main/src/App.cljs

🎉 3
yogthos 2024-10-22T15:20:12.023709Z

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
john 2024-10-22T15:47:56.669459Z

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

john 2024-10-22T15:50:06.386929Z

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?

yogthos 2024-10-22T16:08:11.558889Z

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

yogthos 2024-10-22T16:08:33.015449Z

so you effectively have reagent semantics with it

john 2024-10-22T16:22:14.361069Z

nice

yogthos 2024-10-22T16:23:59.117509Z

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

john 2024-10-22T16:26:59.488779Z

yeah, same

borkdude 2024-10-22T20:18:59.838079Z

@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

yogthos 2024-10-22T20:47:58.265619Z

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

borkdude 2024-10-22T20:52:46.546399Z

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

yogthos 2024-10-22T20:54:07.520199Z

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

yogthos 2024-10-22T20:56:36.398909Z

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

borkdude 2024-10-22T20:58:30.793489Z

right

yogthos 2024-10-22T21:03:45.369049Z

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}]))

borkdude 2024-10-22T21:05:25.125249Z

how do you mutate the atom?

yogthos 2024-10-22T21:06:51.861249Z

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

borkdude 2024-10-22T21:07:12.845339Z

I mean, how do you change the value

yogthos 2024-10-22T21:07:37.090409Z

oh that's same as before

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

john 2024-10-22T21:07:37.539229Z

like useState

yogthos 2024-10-22T21:08:04.649629Z

the setter function handles the updating

borkdude 2024-10-22T21:08:57.244239Z

nice

yogthos 2024-10-22T21:08:58.126429Z

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

borkdude 2024-10-22T21:09:05.462799Z

so the setter function does the draft stuff

borkdude 2024-10-22T21:09:15.882269Z

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

john 2024-10-22T21:09:54.478529Z

so it's basically a swap?

yogthos 2024-10-22T21:10:03.328219Z

yeah looks like

borkdude 2024-10-22T21:10:27.551639Z

specific value, do you mean like a cursor?

yogthos 2024-10-22T21:10:33.742269Z

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

yogthos 2024-10-22T21:11:15.757239Z

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

borkdude 2024-10-22T21:11:35.475439Z

well immer expects you to really mutate the value

borkdude 2024-10-22T21:11:41.575389Z

since it watches it via some proxy layer

yogthos 2024-10-22T21:12:22.143859Z

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

borkdude 2024-10-22T21:12:26.748229Z

so you'd use assoc! and conj! etc

yogthos 2024-10-22T21:12:28.881669Z

and magic happens? 🙂

borkdude 2024-10-22T21:12:34.621129Z

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

borkdude 2024-10-22T21:13:51.157589Z

that's the idea of immer

john 2024-10-22T21:21:13.441379Z

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

yogthos 2024-10-22T21:22:15.077999Z

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