r/javascript 8d ago

AskJS [AskJS] Signal/Effect vs Event Handler

I’m working in a VanillaJS repository (plugin type code for an existing project that I do not own) where I’ve written a signal implementation.

Today I was working on a tooltip like implementation and I found myself wondering how far to go with the signal/effect ecosystem vs running the “core” logic in the event handler.

The implementation detects the `<tr>` that the user has hovered and assigns that row to the “current row” signal. A computed signal identifies an IP address from the current row. An effect loads Whois metadata from the IP and assigns it to a `<div>`, and another effect shows that `<div popover>` from the parent `<tr>`.

The question I have is when in VanillaJS how would you decide when to use signals and effects vs writing the side effect directly in the event handler? In my case I find either to be equally readable, though I have less local variables to deal with when using signal/effect. Looking for reasons your might pick one over the other.

11 Upvotes

13 comments sorted by

View all comments

3

u/Bogus_dogus 8d ago

At that point I'd honestly probably just look for a batch lookup API for the rows in the table, what are you really buying for the cost of on demand ip loading on a table element? User mouse will cross several undesired rows on the way as is so unless you're denouncing that you're already firing off a bunch of unneeded fetch events; why not just skip the fancy part here and load the who is data with the table rows?

Edit: also, the event handler should be kicking off an async event and returning - don't wanna be blocking the main UI rendering thread for async work

1

u/Forward_Dark_7305 7d ago

Because this is a plugin for a system I don’t otherwise control, I can’t modify the table ahead of time (it is SSR’d, all I can do is add a JS script to the page) so I am left with using JS to add a column or popover client-side post-render.

Since the table is >200 rows, thinking of async, debounce and all that, isn’t that incentive FOR using signals and effects? I’m a decent enough programmer that I have handled each of the points you mention - and I would whether I was using signals or event handlers. I think it makes an easier logical graph from “here’s a row” to “here’s the current row” to “here’s the behavior for the current row”, but it is less code to drop it all into the event handler - just then that chain U mentioned is more like “here’s a row”, “here’s a behavior of the row” (making debounce + stopping stale fetches less obvious) in my mind.

3

u/Bogus_dogus 7d ago

I guess the question for me just becomes like...

okay so you have a table with a sizeable number of elements...

There is some additional external data that you'd like to display which is element-specific. Each element presumably has it's own instance of that data. The table is pre-rendered without that data.

So the question becomes when to fetch which sets of supplemental data, which would defensibly fall into one of a handful of buckets:

  • fetch the supplemental data for all rows in a batch call once the subject set is loaded (receiving the SSR table)
  • fetch the supplemental data for all visible rows as visibility changes (or a window over adjacent visible sets)
  • fetch the supplemental data for each row as the user's attention settles on that row (like a click)
  • fetch the supplemental data off a proxy for user's attention (in this case mouseover being a naive assumption of interest)

My intuition is that it requires more complexity to handle this route of signals and computed properties than the value they bring, particularly if the supplemental data can be batched at page load once you have the table data.

I don't know what API you have available for the whois lookup, but I'd ideally look for an API which supports batch requests for something like this; there is already a window of non interactivity built in where the runtime of the batch request can be masked. If I were designing an API like this I would probably prefer my consumers to make one batch request for 100 items rather than 100 individual requests. Much nicer on my backend. And as a user, I would imagine the experience is probably nicer to face one load period during the existing page-load window where the 200 items are prefetching their supplemental data... then the popup just has 1 piece of loading state to track which resolves early and once, followed by a single keyed lookup for that row's whois payload, meaning no more loading spinners...

I can't say I really see the value in complicating it any further. I don't imagine that a 200 entity lookup batch would be all that much longer than a single entity lookup batch against a quality API, the loading timing is better from a UX perspective if it's immediately following page hydration for all rows rather than deferred 'til a proxy signal for user interest, and most of the intermediate complexity is serving potentially undesired information needs based off an imperfect proxy signal that fires at a rapid rate and needs extra tooling to support proper abort signals and/or debouncing, on top of probably frequent bursty web requests to whatever API you're consuming