DEV Community

Discussion on: 2021 JavaScript framework

Collapse
 
132 profile image
Yisar

You still haven't explained the inconsistency between the semantics of fine-grained updates and react APIs (hooks). Unless you use an API that doesn't work like react, it's hard to avoid semantic distortion

For example, the following paragraph is more semantic

function Component () {
  let count = useState(0) // will not rerender
  return () => <div>{count()}</div> // will rerender
}
Enter fullscreen mode Exit fullscreen mode

You use APIs similar to react, but you also use fine-grained semantics, which is distorted in itself.

Sometimes I like fine-grained update model, but its semantics should not be distorted.

Collapse
 
ryansolid profile image
Ryan Carniato • Edited

Want the opposite argument? I will play sort of Devil's advocate. I don't fully believe this and I know the answer to the questions I will present but I want you to put this in the perspective of someone who has been using JSX this way years before Hooks ever existed. And has been using fine-grained reactivity longer than React has existed.


Hooks are the distortion. Why would I ever expect a function that executes over and over to retain state in a variable declaration? Why should I be aware of stale closures or the order I write all things in something that runs over and over? How is that the baseline?

Whereas HTML a XML dialect defines declarative interface that updates as attribute values do. Is it so unnatural to believe that a different XML DSL would do the same? Which is more distorted?


My point is you have arbitrarily decided what is the distortion and what is not. We actually are just seeing the exact opposite thing sitting on the same space. Your semantic example isn't fine-grained. It's more granular than that. It happens at the binding level. Whose to say what the meaning of { } is in relation to the static XML parts of the JSX?

Now I understand React is popular and others have copied it so there is weight here. But that's just a sort of preconditioned bias and not inherent to the technology. I have my biases as well. But let's call them out for what they are.

Thread Thread
 
132 profile image
Yisar

I can accept the appropriate distortion of JS semantics, because the idea of compilation itself can only be like this. I didn't defend fre. In fact, in addition to fre, I wrote other frameworks. They all have each other's scenes, but they also have defects.

Thread Thread
 
mindplay profile image
Rasmus Schultz • Edited

@ryansolid I've been thinking about this for a while now...

Hooks are the distortion. Why would I ever expect a function that executes over and over to retain state in a variable declaration

On this we agree. This is what I disliked about hooks from the start. While they were in fact implemented in plain JS, they use global state (and Dark Magic) to make functions work in very unexpected ways.

When a library requires a special linter to tell people when valid JavaScript is not valid, you know they've gone too far with the "cleverness". It's impressively clever - in the worst possible sense of both words.

On this we agree.

Whose to say what the meaning of { } is in relation to the static XML parts of the JSX?

Actually, the spec is pretty clear on this point.

The Syntax section clearly states:

JSX extends the PrimaryExpression in the ECMAScript 6th Edition (ECMA-262) grammar

So this is not a stand-alone syntax - it is an extension to the ECMA-262 specification, building upon it's grammar.

You can see this in the actual grammar, where all the new syntax elements are prefixed with JSX - while the stuff in curly braces (and elsewhere) references AssignmentExpression, an element of the ECMA-262 specification.

While the JSX syntax extension does not have any defined semantics, the cut-off point for that is the stuff in curly braces. The ECMA-262 AssignmentExpression element has very clear and detailed semantics attached to it.

It's still not clear to me if Solid changes these semantics - my impression is that it does, in some subtle ways? Something to do with how it handles observables at compile-time? How would the compiler would even know at compile-time what is or is not an observable, given that JavaScript has no static type information? Does it use some sort of inference? That would seem a bit risky or fragile. What happens when it can't capture the type information it needs?

It makes me uneasy - for the same reasons hooks make me uneasy.

Thread Thread
 
ryansolid profile image
Ryan Carniato

Yeah Solid doesn't even have an isObservable. All we do is wrap things in functions. If it is a function it could be reactive so call it in a computation.. Otherwise just execute the expression. I know that if there are no member expressions or no call expressions it doesn't need to be wrapped. For components I do the same thing except instead of using computation I literally assign it to the props objects, and things that need to be wrapped are put in a getter.

This all seems like it would add some overhead but because we group attribute reactivity in templates as long as something is reactive you haven't created anything extra that has meaningful impact. It also isn't fragile since it is deoptimized by default. It will always work, just often it can work better. And this somehow is still performant enough for the common cases. The worst case is you create a couple computations that only run once and never update.

In essence we don't generally even really rewrite the JS expressions passed in to the JSX. We just choose whether or not to wrap them in functions based on a very simple heuristic. So all the JavaScript expressions execute the way they are written. The only exception of that is handling ternary/boolean operators that branch to things that would be wrapped. We do independently wrap the condition in those cases in a computation to prevent repeated execution. I honestly wasn't intending to go this way but since it is completely analyzable and people like this shorthand (instead of using our <Show> component) it was a reasonable addition.