Fork me on GitHub
#react2020-06-13
>
lilactown16:06:42

TL;DR it’s like reagent’s ratom/reaction lib, but a little more disciplined and setup to one day interop with a Concurrent Mode-like scheduler

Aron16:06:19

what do you think of resuming being disabled in react? For me this feature was the biggest pull to it, without this, I am not sure async rendering is really worth it even.

Aron16:06:27

i mean concurrent mode by async rendering

lilactown16:06:12

I haven’t looked at the latest stuff w.r.t. async rendering pausing/resuming in React

dominicm17:06:42

This is fantastic, I like it. I was expecting to have an immediate desire to shift the api, but it matches really nicely with how something like this should look. I'll have to dig in to how this works with react and local state, but this is exciting!

dominicm17:06:03

Is a sink just an action in reaction to a source changing? Any reason to not support add-watch instead of a specific api?

lilactown17:06:54

that means a lot, thanks for the glowing feedback ☺️

lilactown17:06:30

yes, a sink is an object that represents an action in response to a source or signal changing

dominicm17:06:37

It's not actually an action itself then. So it matches the semantics of watch?

dominicm17:06:50

One upside is the lack of names, but one can solve that other ways.

lilactown17:06:51

yes, it might be just aesthetics

lilactown17:06:33

I’ve based a lot of the underlying mechanics of the library on an OCaml library called Incremental, which has separate “observers” that are distinct from computations

lilactown17:06:52

observers just watch a computation and fire an on-change handler, like sinks

dominicm17:06:49

While I like your aesthetics, I think it's better to learn less things and copy the language's existing pieces.

lilactown17:06:52

one benefit (I think) is that this simplifies garbage collection and cutting off computation of nodes

dominicm17:06:20

I'm lazy, less things to learn :)

lilactown17:06:17

like imagine if/when an API to hook into the GC for v8/etc. is implemented

lilactown17:06:32

once a sink goes out of scope and GCd, it can then automatically dispose itself and all connected signals

lilactown17:06:00

harder to do that with signals because they potentially have many different connections

lilactown17:06:34

but maybe it doesn’t really matter and it would work with add-watch too, it’s all just theory

lilactown17:06:35

the other nice think about sinks is that they are always a leaf in the fully connected graph

lilactown17:06:53

so imagine you had a utility that drew a graph of all the nodes that were connected to the thing that is causing your component to re-render

lilactown17:06:33

since you have a sink, you can hand it to that utility and be guaranteed to only see the part of the graph that your component depends on

lilactown17:06:20

actually, that would probably work with signals too since I separate edges to the node and edges from the node...

dominicm17:06:25

You could do that watch key as well, the distinction is reification through key or reification through var.

lilactown17:06:11

yeah, i guess it feels a little weird to have add-watch / remove-watch be side-effecting, in that adding or removing watches may cause a signal to come alive or go dormant

lilactown17:06:11

and having specific nodes that are only for side-effects pleases my pure FP architecture astronaut sensibilities

lilactown17:06:21

but you are convincing me :P

dominicm17:06:43

The lack of remove might be a relevant thing that I've overlooked.

dominicm17:06:13

But I find it strange that it doesn't have a remove now...

lilactown17:06:29

there’s a dispose! function which is essentially remove

lilactown17:06:40

it’s just not in the README. the example is not exhaustive

dominicm17:06:44

Without looking at the docs, I'd know how to remove it if it was remove-watch 😛

dominicm18:06:28

@lilactown do you envision this being used in a let or in a global? Thinking wrt to react

lilactown18:06:36

:thinking_face: is both an acceptable answer?

lilactown18:06:04

it's not like recoil, which needs global unique identifiers

lilactown18:06:54

the primary use case I would expect w.r.t. React is to have serenity sources for things like remote data caching; state that you need to live completely outside of the component tree

lilactown18:06:12

so you might have some sources/signals/sinks that are defed at the global level, but then inside of components you could use a hook like:

(def dbA (s/source ,,,))

(def dbB (s/source ,,,))

(defnc my-component []
  (let [data (use-signal #(merge @dbA @dbB)) ;; dynamically creates a new signal and subscribes to it
        ,,,]))

dominicm18:06:09

Both is the best answer. It indicates your thing is simple.

lilactown18:06:52

yeah it's very much in the same vein as reagent in how dynamic it is