Take it any you want, as _signals_ or something else, what has been lacking in the JavaScript world and reimplemented many times is... functional reactive programming!<p>Our own take on this is <a href="https://github.com/okcontract/cells">https://github.com/okcontract/cells</a> where we try to stick as close as possible to the spreadsheet analogy. We're using it to build a very complex web app and it's doing marvels.
This is not entirely like the original signals, but using event emitters instead.<p>I found <a href="https://dev.to/ryansolid/building-a-reactive-library-from-scratch-1i0p" rel="nofollow">https://dev.to/ryansolid/building-a-reactive-library-from-sc...</a> to be a much better ‘from scratch’ example. This is by the maker of SolidJS
Isn't this just an implementation of the Observable pattern? IIRC the difference between observables and signals is that signals don't recompute the value unless any of its sources change, by using a dependency graph. Also, .effect() is just what used to be called .subscribe() in knockout.js and others.
While not 100% same thing, I've been a happy user of nanostores to manage state in vanilla JS.<p>It has `computed` too which works very similarly. On top of that, it has integrations with front-end frameworks such as React.<p><a href="https://github.com/nanostores/nanostores">https://github.com/nanostores/nanostores</a>
This seems a bit different from the kind of signals frameworks have, where dependencies are tracked automatically (no dependency array), and you can sort of chain stuff automatically, so for example you can have an effect that depends on 3 memos that depend on 4 signals or whatever else, and you never experience non-fresh values.<p>If you want to look a bit deeper into this I had written another sort of toy implementation that much more closely resembles what the frameworks are actually doing: <a href="https://github.com/fabiospampinato/flimsy">https://github.com/fabiospampinato/flimsy</a>
Nice! I recommend checking out mithril/stream [0], it's framework-agnostic and quite small but comes with your standard map/lift/etc. Does everything you need and with a standard, flexible interface.<p>I think the code itself is messy and outdated ES5, so I rewrote it in TypeScript and made some improvements to QOL, clarity and performance and use that package liberally across a lot of codebases. I'll post it here sometime whenever I push it to GitHub.<p>[0] <a href="https://mithril.js.org/stream.html" rel="nofollow">https://mithril.js.org/stream.html</a>
Ok, the EventTarget is a very cute trick and I haven't thought much about implementing signals this way.
However, all "serious" signal libraries have at least computed (higher order signals), and a way to sample a value, meaning get the value from a signal without triggering its effects, and no you can't just call foo.value because this won't work with computed signals, and a way to batch multiple write calls to multiple signals, which is often implemented by swapping the effects in and out of the update phase of the signal.
I really don’t see the point. All changes come from events whether user, system, or network events. All you need is event handlers, which is obviously already there at the lowest level.<p>The rest of the stuff the article mentions like rerendering and DOM diffing are all extremely inefficient framework nonsense that is entirely unnecessary.<p>So, to achieve the desired result be event oriented in everything you do, keep things simple, and don’t let framework nonsense distract from common sense.
> In case you've been living under a rock, here's the example from Preact's documentation that neatly summarizes what signals do:<p>> [blank box]<p>Okay, very cool
It takes like 1 more example to actually have “signals” that automatically wire up dependencies between computed() and signal(). Without that, what’s the point?<p>Rich man’s signals provide a really interesting way to structure incremental computation, sometimes called “self-adjusting computation”, without manual book-keeping elbow-grease from the programmer. Ideally, one can use signals as containers for the inputs to your program and receive a program that automatically does the minimal possible re-computation when a signal changes.<p>Without that, “poor man’s signals” is just “stores” from React’s 2014 era.