Fork me on GitHub
#react
<
2021-10-08
>
Roman Liutikov08:10:27

> I do wish they put some thought into how to support libs like MobX and reagent which have boxes that lazily calculate their value on subscribe @lilactown could you elaborate on this?

lilactown15:10:22

the problem that useSyncExternalStore is solving is that you don't want to subscribe to an external store during render, because using their new scheduling your component render might be run multiple times before mounting, or run and then never mounted. so what useSyncExternalStore does is handle reading the value during render, subscribing during an effect (after mounting) and checking to see if the value changed between render and subscription, and handling if the subscribe function or anything else changes to read the (potentially) new value and resubscribe.

Roman Liutikov08:10:08

I guess you are referring to shared cached results between subscription instances? re: ref counting, that’s what re-frame does to dispose cached values

Roman Liutikov13:10:55

The other day I was looking into a way of measuring time from a certain point to when a browser paints React’s update. For example time from a button pressed to when a certain component renders on a screen. In class-based components the end mark would be when componentDidMount/Update is called and in functional components it’s useLayoutEffect hook. But I was looking for a generic mechanism, that would work in both Reagent’s class-based and functional components. So far I’m using React’s Scheduler (via scheduler package), it’s a scheduling mechanism that React relies on. It works really good and executes a callback exactly after browser finishes layout and painting.

(scheduler/unstable_scheduleCallback scheduler/unstable_ImmediatePriority stop-measuring)
ImmediatePriority is a priority level at which both componentDidMount/Update and useLayoutEffect hook are executed. We are using this approach currently to retrieve precise measurements in UI perf metrics.

lilactown15:10:22

the problem that useSyncExternalStore is solving is that you don't want to subscribe to an external store during render, because using their new scheduling your component render might be run multiple times before mounting, or run and then never mounted. so what useSyncExternalStore does is handle reading the value during render, subscribing during an effect (after mounting) and checking to see if the value changed between render and subscription, and handling if the subscribe function or anything else changes to read the (potentially) new value and resubscribe.

lilactown15:10:57

however, there are some libraries which conflate reading a value with subscribing. like reagent's Reaction and other derived computations

👍 1
lilactown15:10:44

and yes, the main benefit of Reaction et al. is to cache their results to avoid recomputing the derived values on every read

lilactown15:10:34

this caching bumps into React's model which might run your component render many times before mounting, or never mounting. In the worst case when your Reaction has no other subscribers, you're basically left with two options: 1. Recompute the derived value every time until the component mounts and subscribes, caching the value 2. Subscribe during render, and handle the memory leak this causes if the component never mounts

lilactown15:10:22

(1) really sucks if e.g. your re-frame sub is expensive, like a datascript query, it can end up causing quite a bit of thrashing in the app until mount. there's also a bug in re-frame which makes this worse: https://github.com/day8/re-frame/issues/657

lilactown15:10:10

I bothered one of the React devs on twitter and they recommended to do manual ref counting of subscriptions and run a timer that disposes if a component never "really" subscribes https://twitter.com/lilactown_/status/1431623810638286851?s=20

😨 1
martinklepsch20:10:05

Has anyone here played around with XState or generally statecharts for React apps? We have a lot of complex behavior and it feels like a potentially nice tool to just reduce the number of states the app can be in

Lucy Wang12:10:20

(thx @lilactown for inviting me to this channel!) Hey @martinklepsch yeah in my experience using a statecharts or finite state machine is really a huge gain when writing applications with complex control flow (regardless of being a react app or not). IMO its benefits comes in three ways: 1. it forces us to think clearly about the states that the application could have, instead of hurrying to create a bunch of bool flag vars like is-logging-in? is-errored? is-retrying? . This is kinda very much like what TDD forces us to do - think clearly about the module behavior before writing the implementation, but in another dimension. 2. Maintaining the complex application logic is much much easier when it's modeled within a statecharts. 3. Visualization. It's esp. useful for documentation & collabration. I haven't spent much time in this but quite a lot people love this. That's why I created https://github.com/lucywang000/clj-statecharts when I can't find a handy statecharts library to use and XState is kinda awkward to be used in a clj/cljs project. btw I think modeling (an app or just one of its modules) with a statecharts is quite a good example of a "principled system" ( instead of an "adaptable system" as https://vvvvalvalval.github.io/posts/2018-07-23-datascript-as-a-lingua-franca-for-domain-modeling.html#adaptable_vs_principled by Zach Tellman.

🧡 1
martinklepsch12:10:34

Yeah these all ring true, after some messing around I actually found XState quite usable and especially during the learning process I really found the visualizer incredibly helpful to think about the state of my machine.

👍 1
martinklepsch12:10:24

Have you considered giving a talk on the topic? I’d love to see one 🙂

martinklepsch12:10:53

(The re:Clojure CFP is still open today: https://www.reclojure.org — and the submission form looks pretty manageable 🙂)

Lucy Wang01:10:58

@U054W022G has invited me to that conference but I really not a public speaker type, and has not much time left besides daily job and a 2-year baby boy

martinklepsch23:10:14

Played around with one random use case (sequencing/visibility of educational popovers) https://github.com/martinklepsch/xstate-clojurescript/blob/master/src/main/starter/browser.cljs#L42

martinklepsch23:10:02

Gotta love that inspector 😄

Lucy Wang12:10:20

(thx @lilactown for inviting me to this channel!) Hey @martinklepsch yeah in my experience using a statecharts or finite state machine is really a huge gain when writing applications with complex control flow (regardless of being a react app or not). IMO its benefits comes in three ways: 1. it forces us to think clearly about the states that the application could have, instead of hurrying to create a bunch of bool flag vars like is-logging-in? is-errored? is-retrying? . This is kinda very much like what TDD forces us to do - think clearly about the module behavior before writing the implementation, but in another dimension. 2. Maintaining the complex application logic is much much easier when it's modeled within a statecharts. 3. Visualization. It's esp. useful for documentation & collabration. I haven't spent much time in this but quite a lot people love this. That's why I created https://github.com/lucywang000/clj-statecharts when I can't find a handy statecharts library to use and XState is kinda awkward to be used in a clj/cljs project. btw I think modeling (an app or just one of its modules) with a statecharts is quite a good example of a "principled system" ( instead of an "adaptable system" as https://vvvvalvalval.github.io/posts/2018-07-23-datascript-as-a-lingua-franca-for-domain-modeling.html#adaptable_vs_principled by Zach Tellman.

🧡 1