DEV Community

Cover image for Making the Case for Signals in JavaScript

Making the Case for Signals in JavaScript

Ryan Carniato on March 03, 2023

Amidst all the conversation around Signals the recent weeks, I have forgotten to talk about arguably the most important topic. Why should you care?...
Collapse
 
ryansolid profile image
Ryan Carniato

Are you adverse to calling functions? Are you adverse to awaiting promises? Did .then make you miserable? We have what we have in terms of available syntax. I can understand if compilers can ease this for sure and likely will. But we've had all sorts of syntaxes over the years. Is it fun to prefix things with this.?

If Signals were new I might have similar reservation I suppose. But when I think of the realm of all possible syntaxes I've used over the years from node callbacks, to psuedo classes in the early frameworks its hard to see what you are getting at.

In any case that has been the norm for some number of developers for years and it isn't really different than anything else. I suppose if it bugs you that much don't partake but I'm not really seeing it.

Collapse
 
leob profile image
leob • Edited

The only thing that surprises me about the "signals hype" is that, in my mind, Vue has had this for ages, and they call it "reactive" or "refs" - ironically something ('reactivity') which React does NOT have :-D

This has, for me, always been the big advantage of Vue over React - reactiveness baked into the framework - hence the FRAMEWORK can optimize it, and the onus of preventing unnecessary re-rendering isn't put on the developer, as React does.

Are "signals" fundamentally different then from something Vue has had for ages? Vue is underrated, it should be way more popular than React.

Collapse
 
ryansolid profile image
Ryan Carniato

No. Vue hid away their reactivity early on which is why they don't get the nod but they were there. The reason the hype has been coming recently though is the return of finer grained rendering. So dropping the VDOM (which both React and Vue use) and using reactivity to manage rendering. Vue is building their own version inspired by SolidJS, called Vapor.

Collapse
 
leob profile image
leob

Thanks for mentioning Vapor, I missed that one!

(so you can tell I haven't actually used or followed Vue for some time - right now using ... React! Lol, for practical reasons that are more or less beyond my control)

That's great news to hear, speaks volumes about the flexibility of Vue's architecture.

Thread Thread
 
ryansolid profile image
Ryan Carniato

Right, this is the power of Signals. It gives you all the glue you need to model any number of things efficiently and cohesively.

 
peerreynders profile image
peerreynders • Edited

Rich Harris the author of Svelte, made the claim that “Frameworks aren’t there to organize your code, but to organize your mind”. I feel this way about Components. There are always going to be boundaries and modules to package up to keep code encapsulated and re-usable. Those boundaries are always going to have a cost, so I believe we are best served to optimize for those boundaries rather than introducing our own.

The Real Cost of UI Components (2019)

In SolidJS components exist for DX but aren't some kind of fundamental building block.

Collapse
 
appurist profile image
Paul / Appurist

It poses an interesting question about the purpose of code. Should we optimize it for making it easier to write or easier to read?

I've been a professional developer since 1984, focusing on web development for the last 15 years. One of the overriding rules I've learned in 4 decades is that maintainability and readability are by far more important than most other factors, including performance. Readability and maintainability lead to more understandable code, which tends to be more reliable (less buggy), and more performant naturally, since the developer(s) can more easily see where poor performance may come from.

So for me, it's a question of do you optimize for "the 10% case" or "the 90% case". Code tends to be (WORM-like) written once and read many times and while there may be updates, for each subsequent change, the user is again reading it and trying to understand it in order to make a change. Very little code is fire-and-forget, or in this case, write-only (and just run repeatedly without reading it again). Even if it is, there are two access points for us humans, writing it and reading it and we're much more likely to need to do the second repeatedly than the first. (This is subjective but I believe it is accurate enough for this discussion.)

Maintainability is the critical decision, which means readability is. So there's no doubt in my mind that ease of writing is less important than ease of reading. Writing involves reading anyway. You look at that code you just wrote and try to determine if it makes sense, if it's good, ready to ship. You do that by rereading the code after writing it. If it's readable, it's more likely to be understandable and all of that happens while writing it too. It's less likely to have a bug or miss the major purpose for writing it in the first place.

The "both" answers are just avoiding your question. Yes both are important but reading is more important, and the longer the code survives, the truer that becomes.

So I'm all-in on optimizing for reading.

 
peerreynders profile image
peerreynders • Edited

For components though, they are objects by their very nature (i.e HTMLElement) and so this is perfectly at home.

What needs to emphasized though is that Web Components aren't the components that consumers of component-based frameworks are looking for.

WC-technology isn't about application components, nor UI components but DOM components and require client side JavaScript to work; WCs are a product of the CSR -era.

Now there are people in the industry who recognize how to make WCs more PE and server friendly but when it comes to SSR it's usually something like:

We can accomplish both of these goals by employing a build step. And that’s what solutions like lit-ssr, WebC, and Enhance are helping to accomplish.

i.e. to "use the platform" fully you actually have to embrace non-standardized technologies (and there really is no hydration story).

Stepping back, WCs actually seem more of a sophisticated client side rendered alternative to iframe (About Web Components).

In a recent move

similarly SolidStart will be using the same Astro/Bling foundation for a server×client development platform (effectively forming the AST-Alliance).

So even if signals don't click for you, TanStack Start may be of interest to you (especially as Preact is supported from the get-go; they investigated progressive hydration back in 2019).

Perhaps something to think about for your "tinkering agenda".

Collapse
 
brucou profile image
brucou • Edited

I see where you are coming from. Syntax does matter. For this reason, some folks prefer JSDoc comments to TypeScript even when TypeScript delivers better typing. For the same reason, we build new languages or add new constructs to existing ones. Programming is reading, thinking, and writing. A programming language should support that. I actually posit that programming is thinking first, and reading and writing second. So being able to express concepts directly as you think them helps a lot minimizing that discrepancy between what you imagined you wrote and what you actually did (where bugs lie).

With that said, I don't see signals entering the JS language any time soon. One key issue being that there is no agreement in their semantics, which is the first thing that must happen before standardizing on syntax. So the alternative is going to be what we have today, compilers, preprocessors, or JS-like languages -- all with similar but different semantics and widely varying syntax/API. I think Svelte got the balance right (see my point about JSDoc comments vs. TypeScript) with making a new language that complects JS/HTML/CSS and reactivity with just enough new pieces to make it quickly learnable.

Collapse
 
chrisczopp profile image
chris-czopp

To me, no magic in signal's internals means no magic when using the mechanism. That ultimately means simplicity and predictability which is something we all strive for.

 
srav001 profile image
Sravan Suresh

Although I agree that a setter is less ergonomic to use, it has nothing to do with signals.

Vue also uses signals. It is only a name for a type of reactivity.

Solid calls the primitives signals itself whereas Vue calls it ref/reactive.

Thread Thread
 
peerreynders profile image
peerreynders • Edited

The absence of this is precisely what tells me a given component-based framework’s design is fundamentally flawed. And I say that as no faithful adherent to any particular programming paradigm.

(1) Prevalence of this typically happens when methods are used rather than functions. In turn it happens when JS Objects are used in the role of "objects" rather than records (i.e. as associative arrays). So they tend to surface more with OO style code. There is nothing wrong with classes, they have their uses especially since the introduction of custom elements.

In SolidJS libraries this is typically used in the role of the function context.

For example in SolidStart I used this:

function userFromSession(this: ServerFunctionEvent) {
  return userFromFetchEvent(this);
}
Enter fullscreen mode Exit fullscreen mode

(2) SolidJS is not a component-based framework. SolidJS is a state library that happens to render. You can author in a component style if that is what you want to do.

(3) What gets drowned out in the signals discussion is that there are also reactive stores.

In my SolidStart TodoMVC demo I use signals to augment server side data with client side state but then reconcile the result into a store before projecting it onto the DOM in order to minimize DOM updates:

function makeTodoItemSupport(
  filtername: Accessor<Filtername>,
  todos: Accessor<TodoView[]>
) {
  const [todoItems, setTodoItems] = createStore<TodoView[]>([]);

  const counts = createMemo(() => {
    /* … more code … */

    filtered.sort(byCreatedAtDesc);
    setTodoItems(reconcile(filtered, { key: 'id', merge: false }));

    return {
      total,
      active: total - complete,
      complete,
      visible,
    };
  });

  return {
    counts,
    todoItems,
  };
}
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
deliastruble profile image
DeliaStruble

This article provides a compelling argument for adopting signals and enhances our understanding of modern web development. Great read! cricketbuzz.com register

 
leob profile image
leob • Edited

Saying goodbye to "this" is a big pro in my book, not a con ... "this" is, and always has been, hugely confusing in Javascript, with its prototype based inheritance and its other historical baggage / weirdness ... saying goodbye to it and switching to a functional paradigm is a blessing as far as I'm concerned. It would be different if Javascript were a real classical OOP language like Java or PHP or whatever - but it isn't.

 
leob profile image
leob • Edited

If that took you just 5 minutes then I think you're smarter than most people - I've always found JS's prototypal inheritance one of the more confusing concepts in programming languages - what's more, I don't really need "this" when programming JS, I'm perfectly able to get by without it, using objects only as "data objects", manipulating them with functions.

But yeah, different folks, different strokes.

(yes arrow functions do help, but then you need to use them consistently, I prefer to avoid "this" altogether)

P.S. I do like your idea about using "native" components (web components?) at the 'component' level, and using Vue (or React) components as the "glue" (pages/presenters) to tie them together ... the idea being that components (which contain no, or almost no, logic) will be reusable across frameworks, and you use the frameworks (Vue, React etc) at the application/"business logic" level - providing a more clear organization than everything being "component soup" :)

(I also see this as a more promising and practical approach than the efforts to use ONLY web components and NO frameworks)

Collapse
 
arnebab profile image
Arne Babenhauserheide

Is there a difference between these and signals and slots in Qt?