Readit News logoReadit News
spankalee · 2 years ago
Returning actual DOM nodes entirely blunts the big advantage of JSX (and non-JSX libraries like Lit) - which is their immediate mode style API, and UI=f(state) model.

You want to return a description of the DOM, rather than the real DOM, because you want to be able to reevaluate your templates repeatedly with new state, and efficiently update the DOM where that template is rendered to.

All the examples here use imperative DOM APIs to do updates, like with this:

    function TodoInput(attrs: { add: (v: string) => void }) {
      const input = <input /> as HTMLInputElement;
      input.placeholder = 'Add todo item...';
      input.onkeydown = (e) => {
        if (e.key === 'Enter') {
          attrs.add(input.value);
          input.value = '';
        }
      };
      return input;
    }

    class TodoList {
      ul = <ul class='todolist' /> as HTMLUListElement;
      add(v: string) {
        const item = <li>{v}</li> as HTMLLIElement;
        item.onclick = () => item.remove();
        this.ul.append(item);
      }
    }
Avoiding those `input.onkeydown = ...` and `this.ul.append(item)` cases, and instead just iterating over items in your template, is probably the main benefit of a VDOM.

(The problem with VDOMs is that diffing is slow, a problem solved by using templates that separate static from dynamic parts, like Lit - a library I work on).

francasso · 2 years ago
From my experience creating complex web UIs, the performance angle of using a vdom is pure fantasy if your application is complex enough.

In fact I now strongly believe it's counter productive, because most people come to it thinking "I can just trigger however many re-renders of this large piece of UI as I like, the vdom makes it ok" and it doesn't, the performance sucks, but now you have architected the app in a way that requires a rewrite to make the app perform well.

I have seen this exact sequence of events four times, by four different teams. The second, third and fourth, as a principal architect consulting for the team I tried to intervene and advocate for a vanilla architecture that is mindful about performance, citing the issues they would likely experience with react, but to no avail. There was a lot of "oh but there many ways to avoid those issues" followed by a list of things I was presumably ignorant about.

I guess most of us need to learn things the hard way.

novocantico · 2 years ago
There were two groups I was hoping vanillajsx would resonate with. The first is people who still buy into the React dream but are beginning to be disillusioned with its inability to deliver on its promises, and the second is people who already are fully disillusioned.

Specifically, I'm hoping to show that vanilla architectures can be not only performant, but easy to maintain with well designed code that uses stable and known patterns. Using JSX just so happens to clean up the code nicely and make the relationship between React and vanilla very visible, but that's really all it did here.

Although to be fair, the hack required to get JSX-as-DOM to work is really unfortunately and I'm not very happy with it, and I would prefer JSX to just render as an object tree that anyone can render however they want. But when I tried that for a few months or a year, it was not nearly as performant as rendering them as strings as soon as they're evaluated, which can then be cached via standard module caching. At least, that's how I got immaculatalibrary to entirely render all HTML files in ~700ms initially and ~70ms on most file changes.

I'll try to do some experimentation next week to see if I can get more performance back out of having <foo bar={qux}>child</foo> to render as {foo:{bar:qux, children:[child]}} again though, because that would absolutely be the ideal, and would unfork JSX in the same way Typed Annotations proposes to unfork JavaScript types.

kristiandupont · 2 years ago
And from my experience building complex web UIs, those team members were right -- there are many ways to avoid the issues and using vdom is great in general. True, there are situations where it falls short, which is why you will want to fall back to other techniques for those bits of architecture. Just like your JS, Python or Ruby server will call a bunch of functions written in C or the like. That doesn't mean you should write your entire backend in C.
johnfn · 2 years ago
The "performance angle" isn't really an angle. It gets bandied around by junior devs new to React, but it's not the primary selling point of React - in fact, it's not a selling point at all. Don't believe me? Just go to http://react.dev and look - no where on the site does it say that React is a hyper-performant library. It's not! If you need blazing performance, you're best off using something much more minimal, or even vanilla JS.

When people say that React is fast, what they mean is that React can dom-diff faster than a naive O(n) approach. It means that updating a component with a thousand nested divs won't crash out your browser, like it might if you were to write the code by hand. It doesn't mean it's an objectively high-performing framework.

What React is good at is forcing you to write code in a clear, comprehensible way. Having every engineer on your team obey F(props) = state is a strict improvement over virtually any other paradigm. (Yes, you can still make a tangle of components if you try hard enough, but the complexity of the tangle is capped significantly lower than the complexity of a tangle of JS without any framework attached.)

unconed · 2 years ago
Yes and the solution is to put on your big boy pants and to actually do your front-end application architecture properly.

Separate source of truth from derived data. Separate possibly valid user intent from validated state. Use contexts to organize the data dependency graph of your application. Ensure all your widgets use a consistent value type in and out, don't let events contaminate it. Use something like cursors or optics to simplify mutations and derive setters automatically.

I've never had an easier time building very complex UI functionality than with React. But it requires you to actively start reasoning about change in your code (what doesn't change), and this is something most people are not used to.

Personally I think React compiler is folly for this reason: they are taking the most interesting part of React, the part that lets you write apps that are incremental from top to bottom, and telling you it's too complicated for you to think about. Nonsense.

The issue is just that React makes pros feel like idiots unless they eat some humble pie and grok the principles and the reasons behind it. Which is that React is what you get when you try to come up with a UI architecture that can make entire classes of problems go away.

Without a VDOM, one way data flow, and diffing, your UI won't just be slow, it'll be full of secret O(n^2) cascades, random ifs to stop infinite cycles, random "let's update this state early so other code can immediately use it" ordering issues, and so on.

darepublic · 2 years ago
More than once I got asked on interviews why react is faster than vanilla JS and I had to tell them no, it isn't.
george_sp · 2 years ago
I've faced the same issue with multiple teams,in different business domains, some with rathe heavy UIs (canvas rendering, sophisticated graphs etc). From my experience, modern frontend frameworks seem to not have taken into account these kinds of problems. To my recollection, in all of those cases, we ended up managing state and rerenders with vanilla, rather than react or angular.

A rewrite on those occasions, I do not consider possible. Most businesses are way to deep into frameworks.

What I personally advocate is to choose frameworks with valid escape hatches, and then make sure to staff a team with JavaScript programmers rather than some-framework Andies.

In an even larger scale, I advocate for web-component based solutions. I try to stay close to vanilla as much as I can. Whether I like it or not, it's the highest value professional decision, imo.

k__ · 2 years ago
Wasn't the issue mostly solved with signals?

As far as I understand, signals make it much easier to keep the DOM updates to a minimum.

kitkat_new · 2 years ago
you shouldn't project from react to vdom in general:

https://dioxuslabs.com/blog/templates-diffing

JasonSage · 2 years ago
I agree with the sibling comment that this really depends on the user. To take a different approach: JSX is just a different DSL to the createElement function call pattern (see Preact.h for example) and all of the benefits you’re describing come from the framework and runtime.

More concisely: JSX is just an alternate function call syntax with some useful applications.

For example at my last company we used JSX to make test data factories that had an XML-like look but were using a builder-pattern in the element creation that was able to make contextual decisions about what was in the final data. Nothing to do with React, DOM, or inability to express the same thing declaratively without JSX.

spoonfeeder006 · 2 years ago
> For example at my last company we used JSX to make test data factories

Thats really interesting, can you elaborate more?

For example did you use a specific JSX compiler? Was that written in house or used a 3rd party library?

recursive · 2 years ago
> You want to return a description of the DOM, rather than the real DOM, because you want to be able to reevaluate your templates repeatedly with new state, and efficiently update the DOM where that template is rendered to.

Depends who "you" are. I prefer to have my DOM nodes updated in place without all the reconciliation machinery. (no implication about what you want)

ericmcer · 2 years ago
If you work on a team of suitable size I would hesitate to not leverage a VDom. I trust myself to not trigger dumb reflows, but the way I see a lot of people using React this could be a perf nightmare.
spankalee · 2 years ago
You don't need diffing or reconciliation to turn a description of DOM into DOM. Lit works without a VDOM.

If all JSX does is return a DocumentFragment that you then need to imperatively add event listeners to and imperatively update, how is it much better than innerHTML?

novocantico · 2 years ago
> is probably the main benefit of a VDOM

I get the "no more imperative updates" dream. I've used these frameworks for probably a decade. I've mastered them.

Me personally, I prefer imperatively updating my DOM. I get completely fine-grained control over what's happening. I can architect it to be an extremely efficient machine. I can make it extremely easy to add/change/remove/fix features in my apps without forcing myself to think according to anyone else's opinionated methodology.

nine_k · 2 years ago
If you have little state, or simple uniform state, you can actually store it in the real DOM efficiently, as values of controls, or lists of similar DOM nodes under a common known parent. If most of your DOM is static, and you only need small bits of interactivity, React is an excessively heavy tool.

The farther you get into complex GUI territory, the more you want a declarative, functional approach, because it makes things simpler. The closer you are to a handful of controls with simple logic, the more you want to just imperatively tell them what to do, and leave the rest of the page alone, because it makes things simpler. We now just have better tools than jQuery for that.

newzisforsukas · 2 years ago
there is no reason something imperative cannot be declarative. the war is one of style, not capability, so saying you gain "fine-grained control" is kind of meaningless, imo

Dead Comment

LAC-Tech · 2 years ago
Returning actual DOM nodes entirely blunts the big advantage of JSX (and non-JSX libraries like Lit) - which is their immediate mode style API, and UI=f(state) model.

I feel like this is one of the leakiest abstractions in all of computing. There's a reason there's an entire cottage industry around react; how to stop things rendering multiple times, refreshing needlessly, etc.

littlestymaar · 2 years ago
Yeah, as much as I liked the idea of an “immediate mode API which is in fact retained under the hood which makes things both ergonomic and performant”, the reality is that React failed to deliver on that and every sufficiently big app ends up having performance problems that are then fixed by opting out of the immediate mode illusion.
skrebbel · 2 years ago
JSX in SolidJS directly returns DOM elements much like in the top part of this post, yet it does not have these disadvantages. It's true that strictly put it's not immediate mode like React and Lit are, but the framework is designed such that there's few practical downsides to that.
PKop · 2 years ago
UI is not a pure function of state[0], "UI state" is relatively stable and does not have to be recreated constantly when data input changes.

[0] https://blog.metaobject.com/2018/12/uis-are-not-pure-functio...

>you want to be able to reevaluate your templates repeatedly with new state

No you don't. It is inefficient and increases complexity. You then have to extract and keep track of state yourself where the platform/UI components could have done much of this themselves.

    Calling the same method over and over again is wasteful.

    So we don't do that.

    First, we did not start with the obviously incorrect premise that the UI is a simple "pure" function of the model. Except for games, UIs are actually very stable, more stable than the model. You have chrome, viewers, tools etc. What is a (somewhat) pure mapping from the model is the data that is displayed in the UI, but not the entire UI.

    So if we don't make the incorrect assumption that UIs are unstable (pure functions of model), then we don't have to expend additional and fragile effort to re-create that necessary stability.

dminik · 2 years ago
This really just isn't true. If your state updates are at the component subtree level (like react) a vdom is a good choice. But, if you make your state changes more granular, you can get away with skipping VDOM entirely and work with just* regular dom nodes. Look at Solid or Svelte. No VDOM there, just pure granular updates.

*List reconciliation still has to happen, but you don't need to pull out an entire vdom. You just have to have some mapping between list items and their resulting DOM nodes.

SkiFire13 · 2 years ago
TBF while Solid and Svelte don't use a VDOM on which they perform diffing, they still ultimately create a tree parallel to the DOM which is used to track dependencies.
croes · 2 years ago
Svelte and SolidJs work pretty well without VDOM
austin-cheney · 2 years ago
Whether you like this project or not, your comment so completely misses the point. You are confusing the JSX syntax, which is what the author wanted by extracting it away from React, for all the React candy. This is a missing the forest for the trees kind of thing.

This mind numbing reliance upon layers of abstraction nonsense around state management is why I really don't like React. State management is ridiculously simple. State management, when done correctly, is the most primitive example of MVC with no abstractions needed.

SkiFire13 · 2 years ago
State management is not simple. You have to constantly keep in sync two different piece of states (your data model and the UI). Making sure that when you modify some parts of your model then everything depending on that is also updated is one of the hardest things to guarantee. Fundamentally this is because it is non-local: you cannot tell what will change by just looking at the definition of what you're mutating.

You might be able to handle this while you're alone and you know everything about your codebase, but the moment you're working with someone else or in a team this will no longer be the case.

Deleted Comment

lucideer · 2 years ago
If the above is what you need there's not strong reasons not to use React or similar. But for most things that will lead to an interest in "Vanilla JSX" this line of thinking is premature optimization - the advantages of vdom are extant but enormously overstated. JSX has many other advantages.

It's also not even an either-or. I've worked on a codebase that did both: React was loaded for some views & others were served with a lightweight JSX renderer.

kolme · 2 years ago
Nice, I love lit-html(1)!

I wanted to add my two pennies to the discussion. You are of correct that with that approach you lose the declarativeness but sometimes you don't need that, if the thing is mostly static.

I went this road many years ago for a project. The nice thing of this approach is getting rid of all the ugly DOM API but enjoying it's performance over innerHTML.

(1) I absolutely love lit-html but don't like the rest of the lit components framework. Luckily you can use it independently!

Deleted Comment

AltruisticGapHN · 2 years ago
I'm having fun using lit-html with vanillajs, after I saw a tweet from Marc Grabanski suggesting he didn't use the full Lit library. Admittedly I am then not taking advantage of all the reactivity goodness, but I also really dislike the decorators syntax and 95% of the time I just don't need the reactivity after the first render.

It works great! I was amazed at how you can do so much in templates, it's pretty much everything I could do in Vue templates, though a little more verbose.

I built my own `VanillaComponent` class, which has a mount() method which calls the render() function which I define on the child class.

My VanillaComponent class looks like this:

    import { html, render } from "lit-html";
    
    abstract class VanillaComponent {
      abstract render(): ReturnType<typeof html>;
    
      private _mountPoint?: HTMLElement;
    
      mount(this: VanillaComponent, target: HTMLElement) {
        target.textContent = '';
        this._mountPoint = target;
        this._update();
      }
    
      _update() {
        let templateResult = this.render();
        let rootPart = render(templateResult, this._mountPoint!);
      }
    }

So I can write something like

    class MyComponent extends VanillaComponent {
      constructor(props: { label: string }) {
        this._props = props;
      }
      
      render() {
        return html`<button>${this._props.foo}</button>`;
      }
    }
Then I can instance like so:

    let myComponent = new MyComponent({ label: "I am a button" });
    let target = document.querySelector("#demo");
    myComponent.mount(target);

The base class stores the root node (target), so later I can do

    myComponent.update()
to re-render, taking advantage of lit-html's "diffing" logic.

However something I have not been able to solve with lit-html only, is when I compose parent and child components I have to do something like :

    class MyDialog extends VanillaComponent {
      render() {
        let childComponent ...  // another VanillaComponent previously instanced
        return html`
          <div>
            ${childComponent.render()}
          </div>

So the child component I need to explicitly call render() to get the TemplateResult for the parent template.

But this means I can not do `childComponent.update()` because I don't know the root element of child component, since I did not mount it explicitly myself.

I mean technically because of the lit-html optimizations, I can do `.update()` on myDialog (the parent component) after any child component's props changes, and it will only re-render what is necessary... but let's say my child component has like 1000 cards... it seems very wasteful and it would be ideal if I could re-render only the child.

I wonder if there is a trick to get around that with just lit-html?

mst · 2 years ago
It's always worth checking the lit built in directives list for the one you've still missed (or at least it is for me ;).

I think in this case the ref() directive - i.e. https://lit.dev/docs/templates/directives/#ref - may be what you want. If it isn't exactly, reading how it's implemented would be my first step towards building something similar that is.

novocantico · 2 years ago
Thanks for taking some interest in my project. It came from being frustrated with the state of SSGs over the past 10 years. I mostly just make static websites, and I wanted something that was simple and intuitive to me, and JSX seemed like a great fit. But I got very tired of the disproportionately scaled complexity of JSX frameworks like React. Long story short, I made an SSG that just renders JSX as strings. It was natural to extend that to the browser to just render JSX as DOM elements. And in a few cases (mostly layout) it lends well to shared components. Overall I'm happy with what I came up with, although some of it is admittedly a little hacky, and IDE support isn't as good as it could be.

[edit] Oh also, this solution works really well for SEO. That's another problem I didn't find solved well in other JSX frameworks.

shepherdjerred · 2 years ago
Just curious, have you seen Astro? I feel like it's the perfect SSG, but maybe you have some reservations that VanillaJSX solves.
_heimdall · 2 years ago
I'm a big fan of Astro, though I could see it being a bit more of an adjustment for JSX users than Svelte users since Astro's syntax was originally based on Svelte.

That said, JSX can be used easily with Astro as long as you get used to at least a bit of The `.astro` syntax for wrapper components and pages/layouts.

novocantico · 2 years ago
For all "have you tried ___" questions, the answer is the same. I've been trying all these new techs for the past 10-15 years, regularly, as soon as they come out, for the first few years with much with excitement, and later with disillusionment and less regularity.

Another user below said

> We've recently moved one service from next to Astro and it was just removing a ton of boilerplate and 'dance around' code.

And I get why it happens. When you first try out a new framework, you allow yourself to learn and add its inherent complexity, knowingly and intentionally. You say to yourself, "it's part of the dream, it's going to work out; there's a vision, just trust the process." This is true with literally all frameworks.

But they never deliver. The complexity is never worth it, and in the end, the intentionally added complexity is always intentionally and gladly removed when it becomes clear that it was unnecessary complexity. This is what I am glad to have learned so thoroughly that I no longer try to learn new frameworks when I initially see its complexity, imagine adopting it in view of my experience, and recognize that its almost always not worth it.

Look at the code on vanillajsx.com. Besides JSX and types, it's plain JavaScript and DOM manipulation. Translating it to document.createElement would add almost no lines of code. There's no unnecessary complexity. That's the whole point of the site. The simplicity of discovering and removing unnecessary complexity is wonderful and refreshing, and I think a lot of people agree.

vips7L · 2 years ago
SSG?
newzisforsukas · 2 years ago
astro is nearly, if not as, "complex" as react, no?
dimal · 2 years ago
Love the idea. FYI, on your demo page, the todo app is 404. And you might want to spell out static site generator instead of saying "SSG" on your docs. I didn't know what SSG was, even though I've used static site generators. I had to ask the AI.
fredmerc · 2 years ago
A JSX for Django server side would be cool.
megaman821 · 2 years ago
Not exactly JSX, but I came across a package django-cotton[https://github.com/wrabit/django-cotton], that is html syntax first components.
WesleyJohnson · 2 years ago
How would you envision this working?
thelastinuit · 2 years ago
not the hero we deserve but the villain we need
AltruisticGapHN · 2 years ago
Have you looked into lit-html?

Coming from Vue I was really surprised it does a lot of what Vue templating does, including attaching events, with just vanilla JS templates. And when you use VSCode lit extension, you get syntax highlighting and full type checking inside the templates.

I learned about lit-html after a tweet from Marc Grabanski, where he said he used lit-html with vanillajs, not Lit.

After some experimenting I found it works great and it seems like you are trying to solve something very similar.

When you use the lit-html template package you can do basically evetything that is described in the Templates chapter

https://lit.dev/docs/templates/overview/

... without all the other abstraction of components that are part of lit-element.

https://lit.dev/docs/libraries/standalone-templates/#renderi...

todotask · 2 years ago
Large WASM payload on your site could be optimized.
hyperhello · 2 years ago
What I’m seeing here is not new. It’s this vanilla pattern but with enough back support to leave off the framing and get the syntax highlighting:

Var button = html(’<button>im a button</button>’);

The html() function is trivial, but it just doesn’t feel like real programming to do this, even though there’s nothing else to it in the end.

mock-possum · 2 years ago
Tagged template literals for html view templating is what I LOVE about Lit and lit-html. It’s JavaScript you can run natively in browser, no server or pre processor/build step necessary.
hyperhello · 2 years ago
Downvote me but tell me why. The example is using .onclick, .textContent, etc in a completely vanilla way. I'm just pointing out you can get all the way vanilla and it still works. What's the issue?
cribbles · 2 years ago
These "what ifs" are kinda funny because the origins of JSX can be traced back to Facebook's XHP[1], which took explicit inspiration from E4X[2], an early JS standard that looked and behaved similar to the library described here.

[1] https://engineering.fb.com/2010/02/09/developer-tools/xhp-a-...

[2] https://en.m.wikipedia.org/wiki/ECMAScript_for_XML

spankalee · 2 years ago
E4X had the unfortunate downside of returning actual DOM instances, which needed to be updated imperatively. That's why JSX eclipsed it, and there hasn't been a serious proposal for HTML templating in JS since then.

But maybe we can revive the general idea with a modern take: https://github.com/WICG/webcomponents/issues/1069

lolinder · 2 years ago
> had the unfortunate downside of returning actual DOM instances, which needed to be updated imperatively.

Isn't this what we have in TFA?

megaman821 · 2 years ago
There are separate proposals from web components that get rid of imperative updates. https://eisenbergeffect.medium.com/the-future-of-native-html...
olliej · 2 years ago
Also E4X was only ever implemented in Firefox, never really got traction even in Firefox.

But even considering the single implementation problem, it also was just not a good language model, nor was it well specified or defined and it brought with it a pile of weird baggage and complexity.

Then because it was The Future there was no real thought into proper interop with JS (it was essentially a completely independent spec so adopted general syntax but specified in a way that meant JS could not simply adopt that syntax).

Sephr · 2 years ago
> E4X had the unfortunate downside of returning actual DOM instances, which needed to be updated imperatively

Firefox never shipped the optional E4X DOM APIs. I wrote a polyfill for them at the time.[1]

1. https://github.com/eligrey/e4x.js/blob/master/e4x.js

kreetx · 2 years ago
With "imperatively" you mean that the user of the templating system has to do it imperatively, and that is bad? Asking because imperative updates seem to be the way to go within the implementation, instead of creating new instances of elements every time.
SkiFire13 · 2 years ago
> which needed to be updated imperatively

VanillaJSX seems to suffer from the same problem though.

olliej · 2 years ago
Fun fact, E4X is the reason JavaScript has ‘for(of)’ instead of ‘for each’ (the reason we didn’t get ‘for (:)’ is even dumber - it would conflict with ‘:type’ annotations a few TC39 members were convinced would magically be in the language)
rlt · 2 years ago
Like the type annotations that are now in TypeScript?
IshKebab · 2 years ago
There is a proposal to add them, though it does seem to be stalled.
recursive · 2 years ago
I also made a UI library based on the idea of jsx template expressions that produce real DOM nodes. It also binds model objects to attributes, eliminating some of the imperative event handler boiler-plate. I think it's a great idea, but of course I would.

https://github.com/tomtheisen/mutraction

It lets you do stuff like this.

    const model = track({ clicks: 0});
    const app = (
        <button onclick={() => ++model.clicks }>
            { model.clicks } clicks
        </button>
    );

    document.body.append(app);

merlindru · 2 years ago
VanJS deserves a mention here! https://vanjs.org/

Another interesting thing is that other JSX libraries like Solid.JS also return DOM nodes, and I love that this idea is gaining traction

The closer we get to the platform we're using, the better. Being removed by layers of abstractions CAN be useful, but in practice, I haven't found a use for abstracting away the platform. (yet.)

Maybe huge projects like Facebook benefit from this tho (which I haven't worked on)

croes · 2 years ago
Isn't SolidJS useless in the bundle size comparison?
novocantico · 2 years ago
That may be a point in favor of imlib.

Technically this is the only code bundled with vanilla jsx:

https://vanillajsx.com/@imlib/jsx-browser.js

sophiebits · 2 years ago
These examples are cool but I think it’s important to note that none of them show components whose props can change over time, since that ability doesn’t seem to be modeled at all. Clever if you don’t need that but I’m having trouble seeing how it would scale to more complex apps.
novocantico · 2 years ago
The technique I used here and in all my browser-side code is the exact same technique used by VS Code internally, and it scales very well. The only difference in my code is it's more concise than writing 10 lines to construct and setup a DOM element the typical way.

Honestly, the real interesting part about my framework is literally everything else. Returning strings from JSX on the ssg-side; being able to import raw source directories and manipulate string|Buffer at ssg-time; the extremely efficient and lightning fast module system I wrote on top of chokidar and swc; probably more I'm forgetting, but basically the JSX-as-DOM is only the most visually interesting part. But really just a party trick.

[edit] Case in point: the source code to vanillajsx.com is extremely concise and clear and short, I literally wrote the whole thing today with zero deps (besides imlib), and the JSX-as-DOM demos are the least innovative part of it: https://github.com/sdegutis/vanillajsx.com/tree/main/site

novocantico · 2 years ago
I just added a more complex todo app to the bottom of the page. So it should give an idea of how a more complex hierarchy can respond to events elsewhere in the hierarchy and update themselves and each other accordingly.
tombl · 2 years ago
Yup, in order to scale this approach to any real size (and still have confidence that everything is working together like you expect), a proper reactivity solution is needed.

For those that appreciate this approach of JSX returning concrete DOM elements, Solid works exactly like this, with the addition of a proper reactivity layer.

numpad · 2 years ago
Maybe I'm missing something, but how would this prevent you from using setTimeout/setInterval? But I agree that these projects often work great in small use cases, but quickly crumble under "real world" scenarios.
novocantico · 2 years ago
I admit that the two most complex "interactive apps" I've built with this are not that complex according to many standards:

* https://www.immaculatalibrary.com/books.html (src = https://github.com/sdegutis/immaculatalibrary.com/blob/main/...)

* https://www.immaculatalibrary.com/prayers/ (src = https://github.com/sdegutis/immaculatalibrary.com/blob/main/...)

_heimdall · 2 years ago
I'd be hesitant to run something like a 30fps render loop in a web app. Its been years since I last saw or tried that in a real world app but it didn't end well for performance.

Your best bet would be to queue up specific UI changes that need to be made as diff's rather than checking the entire UI state. At that point, though, you might as well run them immediately as the change is needed.

If that was still a perf problem you would end up chasing a very complex solution like react fiber to partially update the UI on a loop while periodically pausing for user events.

sophiebits · 2 years ago
Sure, if you blow away the entire app on every state change. But that would lose not only state defined in components (like `i` in ClickMe) but also all state implicitly stored in DOM elements (selection, focus, scroll position, input value, media playback).
throwitaway1123 · 2 years ago
I would almost certainly never implement a UI as a render loop, but if you wanted to go down that path requestAnimationFrame is a much more idiomatic way to do it if you want to match the user's display refresh rate.
hellojebus · 2 years ago
I'm by no means an advocate of this library, and never plan to use it, but to support component props that trigger rerenders, a'la React/Vue, I would use JS Proxies here. Wouldn't be that hard to implement.
sophiebits · 2 years ago
How would you suggest using Proxy?
flowerlad · 2 years ago
This is very similar to Vanilla TSX: https://github.com/wisercoder/uibuilder

Here’s an app written using Vanilla TSX: https://github.com/wisercoder/eureka/tree/master/webapp/Clie...

config_yml · 2 years ago
Reminds me of Action Script 3 which had XML at the core of the language. It was a fun language to work with, but famously failed to become ES4. Oh well, took us 10+ years to arrive close to that with Typescript and JSX.
quink · 2 years ago
https://en.wikipedia.org/wiki/ECMAScript_for_XML - Firefox had it too, but people at large just didn't want it, so it got removed. It got disabled for web pages with the release of Firefox 17, 6 months prior to the first release of React.
sltkr · 2 years ago
Personally I never heard about it. So it might not be that people didn't want it, but that it wasn't promoted much.

Also, it sounds like the only browser to ever support it was Firefox? That was probably much more of a limiting factor for adoption.

mhitza · 2 years ago
People didn't want it because browsers didn't support it (except FF, as you noted). Some of us had our fingers crossed that other browsers would pick it up.
shove · 2 years ago
I don’t recall being able to construct XML inline like this unless maybe that was a Flex server thing?
zoogeny · 2 years ago
I don't recall being able to do the XML construction inline either, but that just might be my memory.

However, the XML selector syntax was a godsend. Recursively parsing an XML tree is really a pain. E4X would allow you to do things like:

    var foo = someXml..childNodes.@attribute;
I'm not even sure if that would work actually. There were a bunch of operators for doing things like getting a collection of children that all had the same tag so you could work with XML like:

    <someXml>
       <intermediateNodeYouWantToSkip>
           <childNode attribute="1" />
           <childNode attribute="2" />
           <childNode attribute="3" />
           <unrelatedNode />
       </intermediateNodeYouWantToSkip>
    </someXml>
Another post here said people didn't want it, but I don't think that was the real reason it was dropped. There was a lot of drama at the time about Flash in general and a massive debacle about EcmaScript 4 (which ActionScript more or less adopted). There was also the whole XHTML thing happening.

Basically JSON as a format won out over XML and ES4/XHTML were ditched. Frankly, a world that revolved around XML/SOAP would have been a nightmare, so I guess killing off the easy processing of XML in JavaScript helped to stave off that potential future. XSS, XSLT and E4X were all casualties.

dugmartin · 2 years ago
It was an extension to ES4 called E4X - it allowed inline xml along with a new xml data type. More info here: https://evertpot.com/ecmascript-4-the-missing-version/
noduerme · 2 years ago
I think parent must be referring to Flex components. AS3 itself had an XML library which I recall being absolute hell to work with. The better way to send things over the wire with AS3 was with AMF.