Hacker News new | ask | show | jobs
by jitl 1207 days ago
It’s kinda funny to see “signals” coming round into fashion or popular discussion in front-end tech Twitter. Mobx is a signals state management library has been around for 7 years. Notion used signals internally for state management and often when engineers joined they’d ask why we use signals over Redux, can we switch to Redux because it’s more modern, etc. Now it’s 4 years later and for some reason this pattern is all the rage. I’m glad I didn’t waste time on Redux just in time for trends to move on.

To discuss more specifically TLDraw’s Signia library, I think the ability to do manual diff tracking & incremental updates for computed stores is an interesting “escape hatch”. Docs here: https://signia.tldraw.dev/docs/incremental

Most signal libraries I’ve seen try to lean hard into magic auto-tracking of dependencies which means they make it really easy for the developer to correctly observe a lot of dependencies, cool on correctness, but then have a very limited set of tools to deal with the performance implication of some computation needing to re-run a whole bunch. The differential tracking here means that if you see such a hotspot, you can get really manual optimization of recomputation without needing to squeeze into the libraries pre-packaged observable collection API.

Downside of this API is it seems quite easy to get it wrong.

Another thing I like about Signia is the use of logical time. I saw this first in Jotai internals, then in Starbeam. I haven’t dug into the source of the library yet but I think logical time is a good approach and makes inspecting internals make a bit more sense than inspecting systems (like Notion’s) that rely purely on update notification listeners.

3 comments

Similarly Angular 1 allowed component oriented development far before react. But people seem to think React invented it.

The problem with angular 1 components (isolated scope directives) was simply that not many understood it as a best practice until far too late, and the framework allowed you to do all kinds of terrible designs like shared scope/multiple controllers per file, which was the more common way to develop. Also performance was poor.

Feel the same way about signals. Vue has been doing it for years (just not tied into render optimizations). I used a similar model via angular 1 back in 2014 even, via watch chains. Much less performant though. Can also do it via redux by defining a special third arg which defines state depenencies (which we do here).

Nothing really novel about a tree-like series of derived states. Interesting that social media is ablaze like its something new

Same here, I have been spreading mobx everywhere I have gone. There's usually some resistance but once people got used to automatic dependency tracking, they never go back.

I've seen so many projects get bogged down in props hell, then gobs of context api and performance problems when too many things react at once.

Mobx has been solving these problems for a long time now!

I recently started ripping Mobx out of my app. Mobx solved exactly 1 problem for me, which was passing data horizontally (to siblings/cousins) and even to non-React components.

But now `useSyncExternalStore` solves that. No context needed. Can read and write state anywhere, even outside components. No "observe" or "track" shenanigans. Efficient updates (can listen to a subsection of the tree).

valtio is a modern mobx-like implementation that uses `useSyncExternalStore` (via useSnapshot - https://valtio.pmnd.rs/docs/api/basic/useSnapshot).

Its still not quite as nice as MobX, as passing larger objects down the component tree means you need to mix snapshot and non-snapshot state. But it makes me hopeful about `useSyncExternalStore`

That appears to be in beta still? What store are you using with it?

I'll keep an eye on it! But mobx does more than that, like a lot of component optimizations and utilities. It's been so good for so long, I'm not in a rush to get rid of it.

`useSyncExternalStore` was shipped live in React 18.0 and is fully ready for production use.

Source: I'm the primary Redux maintainer, and worked with Andrew Clark of the React team to nail down the semantics and behavior needed by `useSyncExternalStore` in practice. They had the idea, but discussed a lot of the necessary use cases with us and other lib maintainers, and a lot of its internal implementation is directly related to how React-Redux's `useSelector` hook was implemented already.

I built the first working code that used it by prototyping React-Redux v8's switch from our own internal subscription handling to `useSyncExternalStore` instead and gave Andrew feedback:

- https://github.com/reduxjs/react-redux/pull/1808

There is a schism between "JS influencer Twitter devs" and "Building actual apps devs"

I have stopped taking seriously people that rely on novelty to sell you their next training.