Live data from Hacker News

JavaScript Views, the Hard Way – A Pattern for Writing UI

github.com

71–80 of 141 posts

Re: JavaScript Views, the Hard Way – A Pattern for Writing UI

#71
post #2

The read me says this approach is extremely maintainable, but I’m not sure I agree. The design pattern is based on convention only. This means that a developer is free to stray from the convention whenever they want. In a complex app that many developers work on concurrently, it is very likely that at least one of them will stray from the convention at some point. In comparison, a class based UI framework like UIKit…

Any code base lives or dies by how well it defines and then sticks to conventions. We can enforce it in different ways, or outsource the defining of convention to other tools and libraries, but we still have to use them consistently in the codebase.

I think the OP here is basically proposing that the developer should be directly responsible for the conventions used. IMO that's not a bad thing, yes it means developers need to be responsible for a clean codebase but it also means they will better understand why the conventions exist and how the app actually works. Both of those are easily lost when you follow convention only because a tool or library said that's how its done.

Re: JavaScript Views, the Hard Way – A Pattern for Writing UI

#72

It appears to be exactly the kind of manual-update code that reactive view libraries exist to replace.

Reactive view libraries exist to hide those details. I think the OP is proposing that the benefit of reactive views/state isn't worth the cost and complexity.

Re: JavaScript Views, the Hard Way – A Pattern for Writing UI

#73
I have been writing recently an application in plain "vanilla" TypeScript with vite, no rendering libraries, just old-style DOM manipulation and I have to say I more and more question front end "best" practices.

I can't conclude it scales, whatever it means, but I can conclude that there are huge benefits performance-wise, it's fun, teaches you a lot, debugging is simple, understanding the architecture is trivial, you don't need a PhD into "insert this rendering/memoization/etc" technique.

Templating is the thing I miss most, I'm writing a small vite plugin to handle it.

Re: JavaScript Views, the Hard Way – A Pattern for Writing UI

#74

This might be heresy to many JS devs, but I think 'state' variables are an anti-pattern. I use webcomponents and instead of adding state variables for 'flat' variable types I use the DOM element value/textContent/checked/etc as the only source of truth, adding setters and getters as required. So instead of: /* State variables */ let name; /* DOM update functions */ function setNameNode(value) { nameNode.textContent =…

> use the DOM element value/textContent/checked/etc as the only source of truth How do you manage redundant state? For example a list with a "select all" button, then the state "all selected"/"some selected"/"none selected" would be duplicated between the "select all" button and the list of elements to select. This is the fundamental (hard) problem that state management needs to solve, and your proposal (along with t…

They could always fall back to storing a value in a hidden element in the worst case. All/some/none selected is often done with an indeterminate state checkbox https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/... that can represent all three states.

Maybe I don't understand the problem you are talking about.

Re: JavaScript Views, the Hard Way – A Pattern for Writing UI

#75

This might be heresy to many JS devs, but I think 'state' variables are an anti-pattern. I use webcomponents and instead of adding state variables for 'flat' variable types I use the DOM element value/textContent/checked/etc as the only source of truth, adding setters and getters as required. So instead of: /* State variables */ let name; /* DOM update functions */ function setNameNode(value) { nameNode.textContent =…

A couple of issues that will arise from this:

• Using DOM attribute or text nodes limits you to text only. This is, in practice, a very big limitation. The simple cases are Plain Old Data which can be converted losslessly at just an efficiency cost, like HTMLProgressElement.prototype.value, which converts to number. Somewhat more complex are things like classList and relList, each a live DOMTokenList mapping to a single attribute, which needs unique and persistent identity, so you have to cache an object. And it definitely gets more intractable from there as you add more of your own code.

• Some pieces of state that you may care about aren’t stored in DOM nodes. The most obvious example is HTMLInputElement.prototype.value, which does not reflect the value attribute. But there are many other things like scroll position, element focus and the indeterminate flag on checkboxes.

• Some browser extensions will mess with your DOM, and there’s nothing you can do about it. For example, what you thought was a text node may get an entire element injected into it, for ads or dictionary lookup or whatever. It’s hard to write robust code under such conditions, but if you’re relying on your DOM as your source of truth, you will be disappointed occasionally. In similar fashion, prevailing advice now is not to assume you own all the children of the element, but to render everything into a div inside that body, because too many extensions have done terrible things that they should never have done in the first place.

It’s a nice theory, but I don’t tend to find it scaling very well, applied as purely as possible.

Now if you’re willing to relax it to adding your own properties to the DOM element (as distinct from attributes), and only reflecting to attributes or text when feasible, you can often get a lot further. But you may also find frustration when your stuff goes awry, e.g. when something moves a node in the wrong way and all your properties disappear because it cloned the node for some reason.

Re: JavaScript Views, the Hard Way – A Pattern for Writing UI

#76

Earlier quoted context omitted.

Posts are sanitized on the server side. This is client side code.

Server-side sanitization means that your view code is inherently vulnerable to injection. You'll notice in modern systems you don't sanitize data in the database and you don't have to manually sanitize when rendering frontend code. It's like that for a reason. Server-side sanitization and xss injection should be left in the 2000s php era.

Where do you suggest we sanitize values? Only in the client, when rendering them?

Re: JavaScript Views, the Hard Way – A Pattern for Writing UI

#77

Earlier quoted context omitted.

This approach is simple but does not scale. People did this long time ago, perhaps starting with SmallTalk in 80’s and VB/Delphi in 90’s. You need separation between components and data. For example you got a list of 1000 objects, each having 50 fields. You display 100 of them in a list at a time. Then you have a form to view the record and another to update it. You may also have some limited inline editing inside th…

So, state is simple, stupid simple. The way to keep it simple is to have a single state object, which is the one place where state is organized and accessed. The way to make it scale is architecture . Architecture is a fancy word that means a repeatable pattern of instances where each instance of a thing represents a predefined structure. Those predefined structures can then optionally scale independently of the pare…

I feel like you completely misinterpreted their comment. They replied to a comment saying that state should not be centralized. They said that if the state decentralized (as in held by individual child components) it's difficult to coordinate between sibling and parent/child components.

It seems like you're saying that it's easy to do UI with a centralized state, therefore agreeing with them whilst having the tone of disagreement.

Re: JavaScript Views, the Hard Way – A Pattern for Writing UI

#78

Earlier quoted context omitted.

This is begging for injection attacks. In this case, for example, if parsed_text and filtered can contain Generating serialised HTML is a mug’s game when limited to JavaScript. Show me a mature code base where you have to remember to escape things, and I’ll show you a code base with multiple injection attacks.

Posts are sanitized on the server side. This is client side code.

Although appealing, that’s an extremely bad idea, when you’re limited to JavaScript. In a language with a better type system, it can be only a very bad idea.

The problem is that different contexts have different escaping rules. It’s not possible to give a one-size-fits-all answer from the server side. It has to be done in a context-aware way.

Field A is plain text. Someone enters the value “Alpha & Beta”. Now, what does your server do? If it sanitises by stripping HTML characters, you’ve just blocked valid input; not good. If it doesn’t sanitise but instead unconditionally escapes HTML, somewhere, sooner or later, you’re going to end up with an “Alpha & Beta” shown to the user, when the value gets used in a place that isn’t taking serialised HTML. It always happens sooner or later. (If it doesn’t sanitise or escape, and the client doesn’t escape but just drops it directly into the serialised HTML, that’s an injection vulnerability.)

Field B is HTML. Someone enters the value “”. Now, what does your server do? If it sanitises by applying a tag/attribute whitelist so that you end up with perhaps “”, fine.

Re: JavaScript Views, the Hard Way – A Pattern for Writing UI

#79

This might be heresy to many JS devs, but I think 'state' variables are an anti-pattern. I use webcomponents and instead of adding state variables for 'flat' variable types I use the DOM element value/textContent/checked/etc as the only source of truth, adding setters and getters as required. So instead of: /* State variables */ let name; /* DOM update functions */ function setNameNode(value) { nameNode.textContent =…

> I use the DOM element value/textContent/checked/etc as the only source of truth

Interesting idea but breaks down immediately in any somewhat serious application of reasonable size. e.g. i18n

Re: JavaScript Views, the Hard Way – A Pattern for Writing UI

#80

Earlier quoted context omitted.

Server-side sanitization means that your view code is inherently vulnerable to injection. You'll notice in modern systems you don't sanitize data in the database and you don't have to manually sanitize when rendering frontend code. It's like that for a reason. Server-side sanitization and xss injection should be left in the 2000s php era.

Where do you suggest we sanitize values? Only in the client, when rendering them?

Depends on what you mean by sanitising.

If you mean filtering out undesirable parts of a document (e.g. disallowing element or onclick attribute), that should normally be done on the server, before storage.

If instead you mean serialising, writing a value into a serialised document: then this should be done at the point you’re creating the serialised document. (That is, where you’re emitting the HTML.)

But the golden standard is not to generate serialised HTML manually, but to generate a DOM tree, and serialise that (though sadly it’s still a tad fraught because HTML syntax is such a mess; it works better in XML syntax).

This final point may be easier to describe by comparison to JSON: do you emit a JSON response by writing `{`, then writing `"some_key":`, then writing `[`, then writing `"\"hello\""` after carefully escaping the quotation marks, and so on? You can, but in practice it’s very rarely done. Rather, you create a JSON document, and then serialise it, e.g. with JSON.stringify inside a browser. In like manner, if you construct a proper DOM tree, you don’t need to worry about things like escaping.

Post reply on HN