LongCut logo

The Physics of Solid 2.0

By Ryan Carniato

Summary

Topics Covered

  • AI Images Beat Lazy Stock Photos
  • Colorless Async Pushes Blocks to Leaves
  • AI Writes Better Than Raw Human Drafts
  • Effects Need Known Dependencies Pre-Async
  • React's Delayed Commits Ensure Consistency

Full Transcript

All right, everyone. Welcome to my stream today.

I've been last minute doing bug fixes, which is pretty par for the course here.

It's one of those things. I didn't

advertise a stream earlier just because I didn't have time to create a cover and then as soon as I'm like ready to advertise it, I realized that there's actually a pretty big regression um that

would actually get in the way of me doing the stream. So, I fixed that um this morning. Um, but I still haven't

this morning. Um, but I still haven't done the latest uh the latest stuff. So, um, for like a new beta release. So, I'm just actually in

beta release. So, I'm just actually in the process of pushing that out right now.

Nice. Okay. So, everything is perfectly clean now. So, I'm just about to press

clean now. So, I'm just about to press go on on on that um PMP change set version. And I know you guys can't see

version. And I know you guys can't see what I'm doing cuz it's on my other computer, but I'm very excited today to to go a little deeper into Solid 2.0. We

we've talked a lot of theoretical stuff.

And then the last stream, I knew that the beta was going to be pretty broken out the gate, so I just used it as a excuse to kind of test it, right? Um,

today I've fixed a lot of stuff in the last two weeks. So today I think we can actually like showcase some of the mechanics a little bit better. I mean

not not that last week or two weeks ago didn't showcase some pretty cool stuff.

But yeah, anyways, yeah, everyone come say hi in the chat. The AI thumbnails are going out of town. I want to talk about this a bit too cuz see I have a very different perspective and maybe it's because of my age and I think maybe

this is going to be one of those things that like you know you know when people call people boomers or whatever you know

that kind of perspective. Um, I I think my perspective on on AI is kind of like they'll be probably making fun of millennials, you know, in a few years.

Um because I don't like a lot of people see a lot of AI stuff and they consider it cringe because it you know I understand because

of the the the low amount of effort um it takes to generate or create stuff but um

if you were going to spend a low amount of effort anyway I think the the the output's better. I I don't I I I don't I

output's better. I I don't I I I don't I don't like I I've been getting a lot of push back on using AI generated images and I'm like thinking about what I would

actually use instead and I mean we could we can look at this on stream you know actually you know give give me a second here but let's look at the YouTube

covers that I create versus the YouTube covers when an artist creates them versus the YouTube covers that AI generates. um for

me and you tell me which ones are the best or the worst, but we can do we can do this right now.

Yeah, we're going to talk about this article uh a bunch today because I I I realized kind of like in hindsight like I'm very much down a path and the article is an introduction of some topics but a lot of people are like yeah

so what what's this mean for solid? I'm

like I thought I laid that out and but I like I didn't connect those dots. So

yeah, I would many of those. Yeah. Yeah. Well,

I I am a programmer, not a visual artist. So, I'm I'm going I'm This is

artist. So, I'm I'm going I'm This is kind of what I want to Let's Let's just do this right now cuz I honestly I keep on getting this feedback and I I'm

sorry, you guys. I I think it's a very I think you kind of got to look at it for what it is. So, let's let's look here.

Let's go to my YouTube channel and uh yeah, let's just call it out right here.

Okay. So

these are some video covers that I made myself. So these ones actually AI

myself. So these ones actually AI generated this image uh inside the painting. Uh David made this image. I

painting. Uh David made this image. I

did this one and I did this one by just putting these three labels on top of a pre-made image. So I didn't really make

pre-made image. So I didn't really make this image. Okay. But let's look at my

this image. Okay. But let's look at my live streams because there's there's more examples here.

This is a live stream cover where I took a stock image. This is an AI generated image. Actually, let's just go right off

image. Actually, let's just go right off the top. AI generated. AI generated. AI

the top. AI generated. AI generated. AI

generated. Um,

actually AI generated, but then I put the labels on top.

Uh, this one is someone's art, so I gave them credit for it. I found I found someone's art. This one is

someone's art. This one is um AI generated. This one I found a stock image and put the word async

signals above. This one I found a stock

signals above. This one I found a stock image and put microf's done first. Uh,

this one's a screen cap from a talk.

This one someone an artist actually created. They took the image and they

created. They took the image and they put it together. Or no, maybe I did this one. I feel like this is better than my

one. I feel like this is better than my average guys from Marco made that one.

This is from a slide. I took a pre-existing image and put a slide on it. This one was AI generated. This one

it. This one was AI generated. This one

I took a table and put my face on it.

This one I took an image, put my face on it. This one I took a photo that I took

it. This one I took a photo that I took on a mountain and put my face on it. Um

I image put my face on it. Put

this one actually. I add the layer some fire on top and a logo on top of a sci-fi image. Screenshot image. Oh yeah,

sci-fi image. Screenshot image. Oh yeah,

look at this one. I just took an image.

I also just took an image here. This

one's AI generated. Kind of looks weird.

I I like that the these old AI generated ones are a lot worse than the new ones.

Like they actually garble stuff in a weird way. Um

weird way. Um took some like Iron Maiden background and put a logo on it. Someone an artist made this one.

My my point is I I I I don't An artist made this one too. I don't know if this was AI help, but this was made by an artist. Um stock image. I I my point is

artist. Um stock image. I I my point is I I I actually think on average the AI images are better than like when I do something like this, like where I just

like take some stock image and put a font on it. I

for articles. I love lowfidelity handdrawn sketches than AI. Yeah, I mean I'm not going to hand draw those sketches. We can do the same exercise on

sketches. We can do the same exercise on dev tube because I mean I'm coming I forget where I got

that image from with the solid in there. Uh, someone

might have created it, but if you look, my articles are infamous for using like clips of Twitter and which is why a lot of them are no

longer around or meme drawings because literally I'm not creating the the art, right? Like I find like stock image clips and then I find

memes to support them. Like

occasionally there's diagrams. But see, one of the things I learned really early on with articles is especially dense articles where there's a whole freaking lot of text and a lot to get on, you have to kind of force the gaps in for your readers um yourself because

otherwise if you just give them the blob, it's going to feel heavy. It is

already heavy. So things you'll see that I'll do very often is between sections I'll add extra like line spacing like these kind of dividers even though I don't really need to. I I learned this

earlier from the from the from editors when writing articles. is just you're writing highly technical articles that were very dense and people will probably reread sections multiple times and

they'll try and get through it all.

Breaking up the flow is incredibly important. Even if it's just like for

important. Even if it's just like for spacing things like these are just blank spots without any images. The images let them like temporarily relax their brain.

So, like there's a whole like I I will fight people on this AI image thing because to me it is 100% improvement. I

I don't understand how people could even argue otherwise.

They look cheap, but are they worse than me literally going pixels?

Atomic atoms in space.

All right.

Reactivity expanded cover chopped like that. This is basically

that. This is basically what you're getting in in here. We go.

This one looks like one I would use with a like graphic designers can do the the work, but am I going to hire graphic designers every time I want to write something?

This is it's just completely insane to me the push back on the AI image generation stuff. I I I I get like if

generation stuff. I I I I get like if that's not the pri like primary goal of the thing and the actual goal is mechanical in terms of actually spacing

and writing like as I said the memes where they fit are a lot better but the images are also valuable and if you look I I've been using this pattern forever um even if it's not I also you know

obviously have code examples where I can do it but in stuff that's fairly like conclusion like what is this it's it's a spinning top. I mean, some of these make

spinning top. I mean, some of these make you think more, but let's compare this to like um an a AI generated image, right? I actually think this cover makes

right? I actually think this cover makes a lot of sense, right? You have like signals kind of like flowing through and then you have like this rocky hazardous place, but then where React sits and like it actually has more contextual

meaning in terms of what the actual article is about, right? Sometimes these

text things are a little bit existence, but like it actually better corresponds with what is is being said. And obviously if I don't like the

said. And obviously if I don't like the images like I kind of tweak or look at the look at the like the kind of takeaway, right? Like I the the art of

takeaway, right? Like I the the art of of actually choosing these images is like a little bit tricky anyways like client side routing without the JavaScript. Does that cover make any

JavaScript. Does that cover make any sense to you? Like it makes sense to me.

I'm playing on it. I apply the same kind of thought process into how I look at AI images when I find like an an opportunity to kind of play around with

the idea. Um, right? Like

the idea. Um, right? Like

I to me the process is the same but the results are just infinitely better. I I

don't I I don't And the funny thing is I got I've been getting push back on this repeatedly, but it's like it's not like the push back has an actual um workable suggestion or solution

behind it. It's just like I don't like

behind it. It's just like I don't like this. And it's like part of you got to

this. And it's like part of you got to go like okay well I have to think about why they don't like this and what that actually says. But then when you like

actually says. But then when you like think about the the actual output quality in a holistic sense being better, it's

hard to like really care that much about about the I don't like this.

You don't see the value in creating image yourself, then you can't pretend any image in the article adds value besides space. Yeah, that's what I'm

besides space. Yeah, that's what I'm saying. It's mostly space and then like

saying. It's mostly space and then like a little bit of like like visualization of a concept or a relational thing. Just

enough to trigger the mind to be like, "Oh, okay. I'm not I I'm getting all the

"Oh, okay. I'm not I I'm getting all the words. I'm just I'm just like, you know,

words. I'm just I'm just like, you know, I'm like it's a distraction.

Yeah, sorry. Like I I I think when when I actually like solid start

I mean some of these I work I mean I don't know I as I said this is going to be probably considered a boomer taste because take because it's or type or

millennial take or something because what I'm doing is arguably distasteful, but it's like

what it's replacing is not actually good in any like intrinsically better in any sort of way.

So like the and the people are like, "Oh, we'll just get rid of the images."

It's not that is not the solution. So

what I've done is found a way to streamline like my process to to actually make a tangible improvement.

And I my one one thing I've noticed over time is that like the AI images have gotten better and over time I I think one of the funniest things and we'll talk about this in a in a minute when we

get to this article, but I there's there's something really funny here. I I have a conversation here uh

here. I I have a conversation here uh with with a response in my in my in my uh to my article here or someone's like uh let me see here

uh where is it? Thought it was really funny.

Let's see if I can find it. It was one of the very first responses to my article.

Uh, let me see.

Okay, this one here. The uncomfortable

truth through naming signals didn't fix the async problem. They just delayed it.

React achronous was a mistake. It was a shape that constraint become visible.

The frameworks that pretend async is special case are the ones that will break first when the graph gets complex enough. Yeah, thankfully my worker two

enough. Yeah, thankfully my worker two has shown that we don't need to be mutually exclusive things. We can

consistently address async and keep all the advantage of signals. We just have to be open to it. Difference is you're building the constraints to a design instead of pretending it doesn't exist.

That's the line between a framework that teaches you something and one that gets out of your way until it doesn't.

Looking forward to seeing where solid 2.0 lands. I this was the first comment

2.0 lands. I this was the first comment response in this in the on my article and I was like wow someone gets it. you

know, like this is this this is a really reasonable, well thoughtout response and like a lot of times these are not the

kind of responses I get and then I I you know I make small clarification and the person seems legitimately excited about it. I find out later.

it. I find out later.

Are we having discussion about images and stuff? Yeah, a little bit right now.

and stuff? Yeah, a little bit right now.

Yes, these stock images are charming and authentic compared to AI generated ones.

I suppose they they feel stolen and they like and they and they and they kind of miss

a little bit. I mean,

yeah, I mean, it's tricky. The stock

images are great when the when the artists give them for free and then I can discredit them. Obviously, paying

for stock images is a whole other thing. It'd be interesting to to

thing. It'd be interesting to to basically guide the AI to have the aesthetic of stock images. Like there's

something about the the the stuff that like, as I said, really is repulsive to some people, but doesn't bother me in even the slightest.

But sorry, the reason I I I I brought up this conversation here is apparently this this isn't a real person and I was

actually talking to an AI. Um, and I had no idea idea. Someone actually pointed this out to me on X. They're like, "Do you realize this this this interaction was with an AI?" And I was like, "No, they just sounded like the most

reasonable person that I've ever come come across." And I'm like, "That should

come across." And I'm like, "That should have been my my clue." Um, if someone responds reasonably, they're probably

not a real person. Um,

and I what I'm getting at is I'm I'm expecting these lines to blur even more in the future to the point

that the that the like current distaste that we're experiencing right now is going to be basically meaningless in a short

period of time. Um,

obviously you will be able to tell, at least for a long period of time, the craftsmanship of a true expert, like of someone who's actually really good at

what they do, that's hard to to replicate. But

replicate. But um if you're not in a position to pay someone to commission your artwork

um like the funniest thing about this is we'll talk about AI writing too because I I want to talk about this a little because um and we'll get into the topic today,

but I just want I want to talk about this again because it's like again this is an example of where people's distaste of it. I read stuff

for its value. The reason I don't like AI written stuff is because it does it isn't valuable usually. It it usually regurgitates. It usually doesn't

regurgitates. It usually doesn't actually provide true insight. it

usually uh doesn't position things in a in a sensible argument. It's too like the way it thinks what's logical presents its argument isn't like really all that compelling. Sometimes it feels

like it's being like smacked at you with like a hammer. But if if an AI generated article actually had relevant content, I wouldn't care if it was AI generated.

Again, this is like such a weird constraint. It's the the content is more

constraint. It's the the content is more important than the delivery. You know

what I mean? Like there's an aesthetic artistry to certain things. Uh but if that's not your primary out go out

outgoing goal or goal, who cares? Like

the important part is to clearly communicate. It's not like

communicate. It's not like again this is why I I I get the impression that my perspective is going to age very poorly or something cuz

people might care about this stuff. But

from my perspective, it's like focusing on the wrong things. People, you know, like I don't get like okay

let's flip this example around hypothetically, right? Like

hypothetically, right? Like AI makes me feel undervalued, underappreciation. It's like the person

underappreciation. It's like the person didn't care enough.

flipped around, does it mean that the person found a more efficient way to get to the same means if the content is actually valuable? Like, I'm just I'm just I'm

valuable? Like, I'm just I'm just I'm just kind of throwing this this out here.

I there is craftsmanship in the art and if you have the time to do it, there's probably real value there. But

otherwise like who cares?

I mean, there's definitely mis Okay. And

I I want I want to give an example here because I I agree with you like from the perspective of like earlier in in in the

week before I uh before I I posted this where very clearly I basically asked AI

to write me an article, right? Um and

sorry, let me just quickly get this um this release going. I just need PM change set version. Just want to see if

I can just hit commit, so to speak, on this.

Yeah, beta 4, beta 4, beta 4, beta 4.

Okay cool.

Sorry. B2.0

beta 4. That way, like it'll all be out there by the time we're actually doing anything important. Okay, perfect. and

anything important. Okay, perfect. and

then commit that precommit. What the?

precommit. What the?

It's fine. I could freaking It's being weird right now. Um,

some weird.

Okay. Uh, but my my point is I wrote this forward here.

Oh, sorry. Just reading some chat here.

Just draw some simple sketches that help native adventure people stay on a topic like Theo and Pirate Software does. I I

will do that during my Excala draw. I

have something a thing. But like for for articles like you could be like you should spend an extra 45 minutes to an hour uh actively

working on your articles if it means the images are better or you but like I I have the code examples where they're relevant. Here's an like sometime I will

relevant. Here's an like sometime I will just use the code highlighting instead of using an image often in my articles.

Um I don't have infinite time. I this is my secondary thing. So I mean I guess you

secondary thing. So I mean I guess you can appreciate that I like you be like look I don't appreciate that you don't spend as much time as you should on this and it's like I'm looking for ways to

spend less time on it. So you know the the the the value is in the content.

We're going to do some Excalibur draw today.

If they if I AI images are not for the kind of thing, what are they for? I

mean, that's that's that's an interesting question. I mean, this is

interesting question. I mean, this is pretty much I I think the use of AI images is for like presentations or like little like Yeah.

Okay.

Okay, now let's do this pmppm build pmpp test and if this all goes well I will be releasing beta in this case imagery are side dash to

the point not the art and it's not there as the only consuming the content it's more how pacing the reading is exactly okay so I got AI to write something for me. And this is going to be relevant

me. And this is going to be relevant more to the content of the stream because I was like I had I've been talking with Copilot a ton and like going over stuff and I was like which is

more just like my think out loud thing.

Um and I was like I feel like all these aspects kind of are pointing at a bigger truth. Can you

help me like put that like get more tighter on what that truth is? And I you know so I wrote this forward and then AI wrote the

article and I've written if you've seen on the stream I've used HackMD to generate article type stuff and AI lots of times as like concept stuff just like kind of like oh you know give me a sales

pitch or a message to contributors or like some kind of like kind of like different types of writing. But you're

right, they all kind of it's not I for me with AI, it's not it's not the phrasing or the pacing as much as like the the line of argument

they take is very indicative of like their personality, right? So like for me when when I I look at this um obviously

there's a lot of AI ob like things here like uh the limiting factors no m looking for like the really there's

there's always those real like I'm just going to drop this in chat. You guys can probably pick out the AISMs like hugely.

Yes. Unsplash

was that didn't add much value anyways.

Yeah, pretty much as far as I'm so for me this is that that it's just an upgrade. Okay, so I'm I'm going to drop

upgrade. Okay, so I'm I'm going to drop this article in here. Um

the the one about determinism and you you could probably see some of the telltale signs of AI here. But on the other hand, as I said, they

like I' I've done enough of this that it's very obvious, at least for me, when I'm like writing something like I can't get AI to write the article I want to

write it. This one was is basically a

write it. This one was is basically a point form list, so it kind of works.

Um, but you can you can never get it to write a real human feeling narrative. I

find um ASIC is no longer a side effect. It's

part of where the values identity limits need that do. I I do think we should this this whole thing is probably worth talking about. March 9th was that did I

talking about. March 9th was that did I cover that on my last stream 14 days ago would have been the 4th. So yeah, this

is we should talk about this content on thing. But my my point is like um

thing. But my my point is like um I I do find myself using AI in new and interesting ways while I'm I'm I'm

working on on on on stuff like for my article that I did post the one that we're going to go into today about React and variance thing. I did I I I I basically asked Copilot and I extracted

this out at the time because I didn't want to like lose in the conversation. I

said let's see the outline below. Was it

optimized for for that title sharp competing structure to both value where is it depending the article now reframes and has two archers strange still correct basically

um I wanted to I I asked AI at the very beginning I was like I want to do an article about this but I want to make sure that I don't miss any of the key points. Can you like give me like a a

points. Can you like give me like a a rough outline of like all the points I should touch? and

should touch? and it it did um and kind of like gave it like sections. The funniest thing is if

like sections. The funniest thing is if if you actually followed this as for writing your article, you wouldn't end up with a very good article in my opinion. And in fact uh this is the kind

opinion. And in fact uh this is the kind this is kind of what AI would have generated if AI had written the last article I wrote because it would have been like two

rejected because two red the sync constraints print principles color sync track the reactive the right variance but the wrong model around them shared constraints both varants ran into modern

UI's default stream transitions cannot optional color nullable y for suspense blah blah blah blah design decisions got right must be except from commit blah blah blah react wrong. We're

predictable double renders effect using world to hook. What's all too like you could already see that it's trying to build a narrative where it's like us versus them, you know, cuz it's very to the point. This the way react sorry AI

the point. This the way react sorry AI doesn't like leaving things open-ended.

It doesn't like talking about general truths. It's like it wants something

truths. It's like it wants something actionable out of it. So, it's like every single section in here is like structured in this kind of like and this is why you should do solid blah blah

blah blah blah blah. And it's just like it's it's a bit much. And this is kind of like like

I I you could almost never trust like I I can already see the narrative gap that you like that you find in these canarles. AI is biased towards sounding

canarles. AI is biased towards sounding smart.

Yeah, everything is bullet points. Yeah,

I mean I asked for if you actually want to see I could probably pull back the original prompt on on on on this, but I was like, "Give me an outline. Do not

write me an article. just give me an outline of what you think the key talking points would be around blank, right? And then I like I I I took this

right? And then I like I I I took this and I just started writing and then I was like, you know, and I kind of just like I was like, okay, that this is not the narrative. But this is useful for me

the narrative. But this is useful for me was it was very helpful for me to be be able to identify like like I mean I already knew this stuff, but it kind of laid it out. So I was like

because the big the hardest part about when I write articles is and my normal process is that I end up just like writing huge blobs per sections and then deleting like half the paragraphs

because I write too much and then I go back and I'm like okay I realize something in this part but I need to get it back into the original message. So I end up rewriting it again

message. So I end up rewriting it again and then I rewrite it again and then I rewrite it again. Obviously, if you learned this in grade school, if you start your article with an outline, you can at least know that you don't forget

anything, so you can actually write it into the initial narrative, right? Um the it to be fair it got all

right? Um the it to be fair it got all this information because copilot might have a short context window that it keeps on sliding stuff out but because

uh I mean I can probably show you here because of of uh like these conversations I've had over time and like things that is kind of

frozen into memory currently. If I just jump in on a new topic today and ask it about some aspect of solid 2.0 or something. It doesn't like remember the

something. It doesn't like remember the specifics, but it remembers the general thing. So like it's very much it knows

thing. So like it's very much it knows in principle what I'm trying to do. So

you know when I give it a I was trying to I was this is how I got the idea for the stream the stream title today. Um because I was like I was like

today. Um because I was like I was like I've been doing a ton of Salt 2 beta fiction. It's been two weeks since the

fiction. It's been two weeks since the last stream. I also published this

last stream. I also published this article. It sounds like one of those

article. It sounds like one of those deep work sprints where you disappear but dropped a big piece of thought leadership blah blah blah blah blah blah blah blah blah blah I I I need to think of tomorrow's dream and I need a title concept hidden physics of react and how

solid 2 solves them differently blah blah blah that's ultimately what led me to where where I am today but it it was very it doesn't take very much context

because of like the baseline that I've set for it for it to be able to jump directly into like what I need out of it.

Um, third 2.0.

Um, let me see if I can.

But I I know people were really interested in this. So, I'm going to I'm going to show you this because this is actually a multi-day process

that kind of that was going through while I was writing that last article.

I need to write an article around the two controvers changes of solid 2.0 deferred commiss effects. I don't want to write the article I don't want you to write the article. They clearly have an AI voice, but I'd like you help laying out the structure and the points. That's

how the conversation started, right? And

then the thing that I copied was I gave it some clarity, blah blah blah.

And the thing that I ended up copying was right after I was like, we so still giving it clarity, I'd rather lay out the article by

headers and bullet points. And then like how would you change this on where we're

how would you change this on uh by changing the title and then this was the thing that we just looked at and then I just started dumping my literal intro and I ended up rewriting the first

thing because I it didn't tie together.

But if you look at this, this this is like basically verbatim of like what actually ended up in the article and except it basically was like

it was it it added like as when you know I got rid of this part.

It's all too late. It's been a journey like it basically added the right periods and commas and kind of like semicolon type stuff. Uh

so then strong section media pivots this then it's like okay and if you look what I end up doing is basically taking what do you think about framing for interesting async characters? I basically just

async characters? I basically just dumped because I use Grammarly right but Grammarly um costs money for grammatical fixes. it

just does like like spelling but for complex structure sentence fixes it actually um it actually costs money. So

basically what I would do is write like three or four paragraphs at a time and go can you correct the structure of this everything involve foundation line option the async moves us out of

impaired comfort zone async is about red that's a question what's available stale up something fl and out of synchronous declared assistance at least that way it looks most parameters by the time it's a different axis we understand parts of the intersect it appears unpredictable

has impact the whole system with a bit of work can be modeled in consistent way essentially This process can take is is is

essentially how I ended up with the article. Right? So people noticing

the article. Right? So people noticing AISMs weren't completely off but I also wrote every single paragraph in here.

As you know, I've been working the last sing territory.

You know where was the other one we just saying everything in the web building the entire platform the network brown you know like I didn't add this dash but

it fits better with the the flow right comfort zone right things same thing blah blah blah async look at fal state flitting in and out like this is my

exact wording um like it it's basically a grammar corrector um

but It's enough to give us a slight voice on this that I I get rubbed people the wrong way. Um,

but AI could have never written this article. Do do you know what I mean?

article. Do do you know what I mean?

Like when when you go and and be like, hey, with these points, write the article. He doesn't write this kind of

article. He doesn't write this kind of narrative structure. doesn't construct

narrative structure. doesn't construct this sort of I have not had any and this shouldn't be surprising to you because it's not like

it's it's a bit like trying to execute a plan without plan mode. The problem is with writing. Plan mode would basically

with writing. Plan mode would basically essentially force you to the get the the right tone, narrative structure, all that. you the plan you'd basically have

that. you the plan you'd basically have to write the article like you'd have to write the whole article first to actually sufficiently do what plan mode would do for for for code by by by

comparison. Um,

comparison. Um, and this is another example and I'm bringing this up right now before we get into the more solid 2.0 know stuff just because this has been controversial cuz there a lot of people talked about the

AIness of this article and they were upset about it and I'm like I'm thinking about like I know what if I if id set AI to write this article it would be

nothing like this. Um like I actually have the artifacts as I was showing to prove that. Um, but

prove that. Um, but when I look at this, the way it reads compared to my Yoda speak, you know,

this feels much nicer, much more professional, much more hopefully understandable, um than you know, my writing typically is. It

actually tightens up little bits of phrasing things where I miss words. I,

anyone who's ever edited my articles before they get published knows exactly what I'm talking about. I I used to I for for years I've used like four or five people like different people

different articles but I I always run my articles through a bunch of human review because they're tend to not be understandable otherwise. If you look at

understandable otherwise. If you look at my hackmds versus my dev2 articles like the ones that I write you can tell a worlds of difference. Part of it is because of the amount of time I spend editing but the other part is because I

other people actually read it and edit it because what I write tends to not make sense.

uh co-pilot's like on something old like five uh GPT 5.1 or something right which is what what I was doing I was posting whole sections and being

like what do you think about this that that's what I'm saying like you you AI would not generate it but when I I see this come back which is basically identical to what I wrote but like added

the spacing timing pausing slightly rewards like a thing here or there. I'm just like this is Yeah,

there. I'm just like this is Yeah, honestly, this is much better, you know, add some quotations around my, you know,

like is it my questioning like you're like, okay, this actually reads better.

It's a question of every UI thing. Can I

show this or expose something? This is

like this reads a billion times better.

I mean, I've streamed for six hours, so you know, I'm sure we'll get to whatever you want to talk about.

This is important though. I needed to get this out of the way. Um, mostly

because this is Yeah. Again, what what is my goal? My

Yeah. Again, what what is my goal? My

goal is to clearly communicate with people.

Yeah, this is the this is the gist of it. The challenge is you let's say that

it. The challenge is you let's say that this experiment was a little bit heavier-handed than I usually go.

Was it worth it?

If it's less than six hours, it's AI.

Um, yeah, just replace me with AI. Um,

did it did it work? And the answer is depending on who you talk to.

I I got that first comment in the in the in the in the comments and I was like, yes, it worked. And then I found out find out that AI wrote it and I was like, okay, well, maybe maybe maybe it

didn't work. Um

didn't work. Um Um, which which is a little bit harsh.

Um, sorry. I actually should actually do the

sorry. I actually should actually do the publish command now.

Um, sorry, I just need to quickly get my authenticator app going here so that I can actually publish. Do not

challenge for the next five minutes.

Okay.

All right. Thank god. Okay. Beta out.

Okay. Um,

yeah. Uh, the funniest thing is this.

I'm going to talk about the contents of these articles in two seconds. I just

the last bit of this conversation is, uh, I want to go to Reddit. Um, and I I uh and let's see if I can I can find what

I'm looking for.

Uh, all right. Here we go.

all right. Here we go.

Great article. The TLDDR is you basically have the deep Oh, so the person Oh, they deleted it. Okay. Well,

good to know.

So, is it only good comments now? Basic.

Oh, yeah. Here it is. I think it would be helpful if you adjust your title and note in your post that this article is basically a subtle plug for solid. You

posted in the react sub. This isn't

really advice for react dev. It frankly

reads more as haha. You you react peons are stuck with the stuff and you don't have to deal with felter solid. Thank

god Rick Hanlon. Remember him? React

core team had him on the stream. You're

wrong. This is absolutely great content for reacts. It explains the exact reason

for reacts. It explains the exact reason for choices we made that I've struggled to explain to React devs myself and several times even says it's not about the framework being better than the others.

Thank you, Ricky. Thank you. Honestly,

I think the takeaway is even with AI, people still don't really understand anything um you know, if they don't put

the time in to. So yeah, I I was really happy reading the article and and seeing how much clearer the points were and I'm like, "Oh, I wish I thought of doing it

that way. Oh, this is much nicer." Like

that way. Oh, this is much nicer." Like

just little like little it's the structure, the paragraph per paragraph were the same, but it was just like, "Oh, added this word here, paused here, and you're like, "Oh, okay." Yes,

exactly. Right.

Um, so like more people came to defense, so whatever.

But yeah, this is if you look at this article, it's it got downloaded on Reddit React forum like past zero. Like

basically everyone downloaded this article. No one upvoted it. Um, which is

article. No one upvoted it. Um, which is insane, but it's also par for the course of Reddit. You know, we've often said

of Reddit. You know, we've often said that like on average the developers on Reddit are like like YouTube comments sometimes are pretty low bar. Reddit is

like the bottom. You know, you can like go on there, say something reasonable, and then I mean it's almost like like like I think my response where I was

like I was like uh it seems reasonable to me got downvoted a bunch. Okay,

that's not the message. It's four. Okay,

this was like minus 6 at one point.

Um, when I'm like literally saying like, "No, that's not what the article says."

Like I'm not sure people on Reddit, like I I guess they would need to know how to read if they were going to like write this stuff, but I'm actually like I'm sometimes not sure if they know how to read.

Um anyway, so yeah, my my my takeaway on this is is that um

maybe the thing that I thought I was attributing to the clarity of my writing is is actually not my writing's fault

completely. I I thought that if I could

completely. I I thought that if I could like clean things up in a meaningful way, people would get what I'm what I'm talking about better. It could be still problem with my narrative structure. It

could still be other stuff, you know, because that's I obviously didn't write that article, but um I like my narrative structure. I like

the arguments I make. So, I would never change that. Um,

change that. Um, but it was it was it's definitely frustrating when you write an article that's literally like, "Look, React fans, here's some ammo. You guys were right." And the person's like, "You're

right." And the person's like, "You're just trying to rub solid in people's faces. You're just like," and it wasn't

faces. You're just like," and it wasn't just them. Like, there there's multiple

just them. Like, there there's multiple comments to this to this degree and like in in this kind of thing. And I was just like, "How do you how do you get there?

How how like do I just give up?

Um anyway, uh enough on the AI topic. Let's get let's get to the topic at hand. I think I've I've probably talked your guys ear off about this. I don't I don't generally

about this. I don't I don't generally like talking too too much, but I had to address this because there's a bit of an elephant in the room.

>> Yeah. Yeah. Yeah. Well, we'll see if we can get Delaney on. I I think I think it's I think I think data star is interesting because it tries to sidestep

a certain category of problems which I I think I I think in a sense the way I would look at data star just holistically before actually like going deep into it is

it's it's really taking that htmx perspective that you you like yag me you're not going to need it and and just like look

HTMX is just missing this last little bit. This is how you just stretch into

bit. This is how you just stretch into that next zone a little bit farther. My

challenge with this is is once you introduce that zone, you you have a new set of problems you should be solving and you can pretend

those problems don't exist and you can basically be like, "Okay, I'm okay with it. My scope is right here and you

it. My scope is right here and you you'll be fine." It's kind of like a bit like some of the issues I have with Astro Islands. But then it's like once

Astro Islands. But then it's like once you cross that threshold, it's insufficient and then at that point you have to rethink everything and you

kind of end up where actually I where I'm sitting. So it's like

I'm sitting. So it's like there's this interesting tension between solutions that that uh um you can clearly go they belong over

here and one's trying to expand over more of the range. And the thing is if you take those I just belong over here solutions and try and expand them beyond

their range. Uh sometimes you can hit a

their range. Uh sometimes you can hit a really sweet spot, but you can also hit a zone where you're butdding right up

against like models that would be more suitable um uh for you know like like you're you're just hitting that piece.

So it'll be interesting talking to Laney and and figuring out exactly where that line falls.

React and especially react in a serious community I see.

It is a big mind shift. But the the thing is and I think this is still true.

Delaney still doesn't believe in shared client state.

He believes that not everything has to go back to the server which is which is which is key like that you can keep interaction while keeping that kind of like partials sub view. The challenge is

when you have partials that share state like island same kind of concept. There

is a fundamental mismatch here on shared state works with cl server side rendering right like how do you you get the old update panel thing. I we're

going to talk about it I'm sure when I get to Delaney on it's just it's it's kind of fundamental. It's not like a it's it's a physics thing. And I like talking about these things in terms of physics, which is the whole reason that

I wanted to uh do the stream today because um these things feel like rules that are

discovered rather than inventions, things created by people. I think that's really important.

Cash in the cash is really interesting.

It's like 13 content probably it makes sense to me especially if they're using that with something like server islands like I I I think we

we just we just need to um I mean there's only a few core mechanisms behind all these things and even if we figure out how to model the

data or the transport layer like slightly different you're like you're still dealing with the same types of problems you can like kind of shift it around so I haven't actually looked at

this specific specifically, but I I'm guessing um I'm guessing that's the realm in which it's operating in. I could be completely

wrong though.

Okay, so let let's talk about physics here. Um I'm going to change my view

here. Um I'm going to change my view slightly so we can get into the topic of today. Um because

today. Um because I want to start with this article mostly. I I think my hackmd about yol

mostly. I I think my hackmd about yol 2.0 0 is interesting um about temporal determinism and all that. It is

interesting but it's kind of like a AI point and I don't I don't know if we want to talk anymore AI right now. Um I

think I've made this point on stream over and over and over G again essentially that the shape of our solution is important but there's no point talking about the

shape of our solution until we actually look at the shape of our solution. So

let's start let's instead start from from here right let's start by talking about

why react was right and why this is actually physics not DX consideration

right and then we'll talk about how solid 2.0 solves that.

So, if you haven't read the article, it's worth a read.

React was wrong. React was right because Angular was oh so wrong.

Or Angular.js original. Yeah. I mean,

Angular.js had its challenges. it. I

think conceptually Angular.js came from a really reasonable place. It was like look we have data we bind it. We update

what changes. Honestly, anyone

engineering a solution for front end at the time that seems like what the problem was. You have a bunch of

problem was. You have a bunch of imperative writings all over the thing.

Let's make it declarative. Let's just go this change to this change. Like it had the shape of the solution it knew it wanted to solve.

it didn't have any of the guarantees on propagation. This is the whole problem

propagation. This is the whole problem with the the early systems. They they basically were just like a wrapper over jQuery, right? They were just like,

jQuery, right? They were just like, okay, well that's imperative spaghetti code. Let's make it declarative

code. Let's make it declarative spaghetti code. Like the the process in

spaghetti code. Like the the process in in which we could like do these updates wasn't as refined. Right? Back then it was just like about the abstraction. It

was like how do we get the DX? It's like

okay, you know, we'll do we'll dirty check everything. We don't care. just

check everything. We don't care. just

make sure that when I say that this state is tied to this thing that it will update. That that was our primary

update. That that was our primary concern. React was kind of more like no

concern. React was kind of more like no we need guarantees here otherwise it's zgo like literally anything could go wrong.

Right.

The problem with the react approach was it's it was too simple. Right. the the

both it's it's both the benefit and the like it's both react is like who cares just rerender everything and you're like how can that be good enough and they're like you know what we figured out a way

to make it good enough that's their whole premise but it it was never like arguably the the the best solution to the problem but they didn't approach it

like engineers solving a specific you know like mechanical problem they kind of were like holistically this truth needs to emerge from our system, right? And almost everything

system, right? And almost everything from there flows out from React. Um,

does solid get compiled into web components? No. I don't know why anyone

components? No. I don't know why anyone would want to do that. I mean, we can support web components and people can put solid code in web components, but

it's kind of like web components are kind of a waste of like they're just a thing. It's like I can have a component

thing. It's like I can have a component and then I can also make it a DOM element for some reason.

AngularJS had its good side. To this

day, no modern framework has better modal dialogue DX than Angular. Spent

months trying to recreate mega powers in React. Yeah. I mean,

React. Yeah. I mean,

and also I feel like Angular spent a lot of time fixing very specific problems that were fit their real needs.

Sometimes React's solutions seem kind of heady, like kind of academic. And to be fair, I'm in an

of academic. And to be fair, I'm in an interesting place because with Sol 2.0, like at a certain point, you you you sit there and you batching

up bugs all over the place and like see these patterns emerge and you're like, the solution does actually need to happen at that level, right? the level

at which React kind of tends to operate at. It doesn't mean you should like

at. It doesn't mean you should like change to just doing what React does, but you have to like step back and be like, look, is there a systematic problem here? Are we is it our fault?

problem here? Are we is it our fault?

Right? Almost every major framework uh change in the last like five or six, seven years has been around that. Back

in the day, it was originally just like pure DX play, but now new frameworks now have been mostly coming out of like is it our fault thing and being like saying yes. Like Quick was like saying like is

yes. Like Quick was like saying like is hydration being slow like that piece our fault and Quick's like it's not the developer's fault, it's definitely the framework's fault. That that's their

framework's fault. That that's their premise.

Solid's perspective was is the UI getting updated slowly or in like like not as efficiently as possible and like

weird like kind of like rerenders and all this kind of like obscure uh kind of weird mental model pieces the developer's fault and it was like no

it's the framework's fault like I feel like that has been has been kind of like the sign here originally it was just like you I don't want to write jQuery

anymore. But then it's evolved into like

anymore. But then it's evolved into like us recognizing that the abstraction or the tool should be providing something that it does that it doesn't currently.

Why do you hate web components so much?

Um, okay. I mean, I can answer this actually

okay. I mean, I can answer this actually pretty simply because they they they actually aren't that much of a problem in a certain sense. You could say that

they're just extra. They're just like an option. And and if if they were just an

option. And and if if they were just an option, I'd be like, okay, the problem with web components and why I have so much thing is they're unnecessary and

then their existence influences other decisions. So, it makes it a very

decisions. So, it makes it a very awkward place to be because basically we've tagged on something that arguably is optional and then tried to base

everything else off their existence in a way that like over complicates and undermines the ability to do things in the most simple, direct, and performant

way. So it's like

way. So it's like like on the surface as someone who using these APIs could be like okay well you don't have to use web components I can just use web components

on in principle cool go for it but like the reality is the impact of their very existence makes everything

else worse. So

else worse. So I I think I could even be okay with that except for like web component people keep on coming around and being like hey do you know why do this or do this with

web components and it's like if you knew what you were doing you would even ask that question. It's it's like yeah yeah

that question. It's it's like yeah yeah sure go ahead do that with your web components but why would I have to worry about that cuz like they don't add any value like it's like do you know what I mean? Like it's it's like I it's a

mean? Like it's it's like I it's a combination of like their impact on the platform and the fact that like people seem to be like really wanting to push them when like it almost like not

understanding what they do and it's kind of like you have to like repeatedly be like okay well sure like you can go do that with your web components. You don't have to do

web components. You don't have to do anything in solid to do that. we support

web components, you know, we we've taken that hit, but it's like um it's like it's like I have to it feels bad after a while being the one to have

to deflate people's expectations around web components, right? You almost get kind of like annoyed or frustrated with the people pushing them because it feels like they they're selling a a lie or

something like that that that's usually the challenge there. it I don't the technology in a sense could just speak for itself but there's a lot of misconceptions around them and it's not

that I I don't think that they're incapable of doing things it's just like it's like it's one of those things it's like yes you can do this with web components but then like you can also do this without web components and it's

arguably better so why do you why are you conflating web components with this So, you don't hate white women, you hate the culture around it.

Um, I don't have the the same conflict with React or or that. I I think the thing is React knows exactly what it's doing. I mean, maybe not all of its

doing. I mean, maybe not all of its fans, but React actually generally is fairly straightforward. You know, like

fairly straightforward. You know, like it's very clear to me at least what the trade-offs and the design decisions are and how that flows. It doesn't feel ever

um like it's dishonest.

Um anyway what does any of this have to do with anything? Well,

anything? Well, React's ivory tower and oversimplistic design gets us to

certain places much sooner than others would have got to because most of us were just building apps and just trying to build things. And if we hit a few awkwardnesses, we're just like, do we have the tools to deal with them? Yeah,

we do. That's the pragmatic approach, right? You kind of like figure out where

right? You kind of like figure out where the lines are. I think there's a Ryan Florence tweet that we covered a couple weeks ago that was like this. And then

honestly, you just when you have to ship, you just fill in the real you fill in those gaps with whatever crap you have available and you move on. I mean,

AI works the same way. You just kind of move forward to it. At a certain point though, you have to really ask about like where those lines are drawn. And um

in React's case, there's like two really really big reactisms that piss people off a ton. And I think it's important to look at why they exist. Um one of them

is the set state and then state not committed one. And the other one is um

committed one. And the other one is um the fact that they have these dependency arrays. Now

arrays. Now the set state and state after one wasn't always a clear picture in like react 0.13 or 014 like 14.13 there were cases

where you could read the next state and eventually point they were just like no stop doing that we need to make this um we need to like settle on this one

behavior.

This one is funny because I I'm calling out effects particularly because you don't need

the reason that effects are special here is because technically the side effects should happen independent of the rendering. like dependency arrays on

rendering. like dependency arrays on your use memo or use callback or whatever like other mechanisms you're using in React aren't necessarily important because you know that that

code's all going to run during render.

It's basically part of the render pure part. So the mechanical need for uh

part. So the mechanical need for uh dependencies might you know be seen as a shortcut but for effects

you do need to know the dependencies before you run any effects um because the those dependencies like you need to make sure that all the

effects run cons at the same time. If

you run some effects and then you get interrupted or something can't go and you run other effects, you end up with torn UI. So you have to make sure that

torn UI. So you have to make sure that you know all the dependencies up front.

And signals libraries kind of got away with not necessarily doing this because you can kind of ask for

the data wherever you need it. So

they're just kind of like, okay, well we'll just create effect, you know, whatever. read the stuff and then it it

whatever. read the stuff and then it it could you know it'll just get it and who cares if like we process some of the pure calculations late you know if it's

lazy pole system or if we you know do some part of an effect and then do some other stuff and then do some other effect and do this and kind of isolate it across because there was no possible

way because everything is synchronous for for any of those interruptions to escape that render frame like you knew for sure that you know some stuff might kind of flip around a bit, but in the

end, you're going to end up with in the same tick, you're going to end up with a consistent UI. And I think once you understand like these kind of two

fundamental things don't hold up during async, you're posed with a a very kind of interesting question. And I think and this is why I I want to talk about this

and I'm talking about this like physics because this is kind of a fundamental truth. I I'm very open to people in chat

truth. I I'm very open to people in chat arguing with me saying why both of these things in React are terrible. I'm but

try to argue that these are aren't necessary is a much harder task.

Uh, is your latest YouTube video a good introduction? Not really. My my what

introduction? Not really. My my what React developers should know about signals is a good introduction to React developers who at least know like what a

signal is and then they've been hearing all this bad stuff about it. It's morely

the to it's more mostly myth busting. I

don't have a great like intro to signals video in the same way that I have an intro to signals articles, but even my articles like how to build a signal system, depending on what level um of

what you're looking for, you might find it better elsewhere.

And only thing a program with effects can do is heat up your CPU.

Yes. And a lot of the stuff that we're going to talk about today in terms of physics is kind of understanding this like if a tree falls in in the woods and

no one's there to listen uh like did it make a sound? Like that is that is part of of what we'll be talking about today.

React's biggest gotcha for me personally is that use state doesn't update when you source it from a prop and prop changes later use effect. Almost

everyone does this. This is why solid 2.0

does this. This is why solid 2.0 directly addresses this. I also want to talk about why solid 2.0's design is better than dependency arrays even though it feels like dependency arrays.

Um this is a problem not unique react at all. And I came to the same conclusion

all. And I came to the same conclusion about three or four years ago when I started working with solid 2.0 designs when I I I realized that this was like the biggest source of people needing

synchronization is that you're when you construct the graph you can't create the the dependency through state which is kind of crazy because react rerenders

almost everything about react makes you think that like you would like oh if the props change coming in I should be able to reset my state and the answer is you actually have to create a side effect to

do Now you can key the component but that's such a brute force way of doing it. The

other thing is you can derive your actual state from your local state and the props and then kind of like calculate it in line. Um that will also

work but these are very like complicated ways to do things that are very clearly trying to set up a graph like dependency change in a rerender

model. It it

model. It it I said it's not you need to react at all, but it feel like at a certain point I was like this is the gap.

Yeah. I mean, I don't know if you've seen Solid 2.0, but that's that's exactly what we did. You're in the stream. You definitely know what I'm

stream. You definitely know what I'm talking about, right? In React, when you have state and you pass a function to it, it just it's a safety guard for when

you have work to do. If you want to know what I mean for people who uh sorry not Excalibur uh I'll just use play I'll just use solid playground for for for for

explanation here. We actually use this

explanation here. We actually use this trick on Ricky stream. But essentially

like when you do use state in a React component and you have something like expensive first of all if you do use state zero

and your component reruns because um I'm going to call it count uh count set count excuse because you

might have moved count, you know, like did an event and set it to to three or four or whatever because you have to persist the state in React when like the

component reruns, it doesn't reset it back to zero. It keeps whatever the count is. It makes sense. But the

count is. It makes sense. But the

problem is if you have like expensive calculation is how you're thinging it would be the problem is because this code actually runs even though it returns back out

like a cache value out of here because this reruns every time you wouldn't want to do that. So React gives you the ability to pass the function in but the function only runs initially. Um

essentially it's just a way of guarding.

So it's like look if if someone passes a function into this use state don't um don't rerun this expensive calculation

keep the cache values only run this initially um so it doesn't solve the problem right the whereas um if you have

create signal your components aren't rerunning and for that reason this behavior is implicit because you like it will never rerun. So it will

never run this out again. So the fact that this updates is fine. You'll never

have to worry about it. Which lets us overload this now. Like basically you this would be perfectly fine because the

component only only runs once.

But it means we can do this too and and have the function like most things in a signals library mean that it actually reruns. So whenever the props

actually reruns. So whenever the props change you can reset. So this behavior of deriving state which is very natural

is something that we can do um very naturally in this model.

Yes.

Yes. Exactly. You want you want to reset. This happens a ton in forms and

reset. This happens a ton in forms and what most people do is they they they put use effect in

um the better solution is to yeah I the the things that get allocated and throw away immediately tend to have way less of a memory impact than you'd expect.

um I've found.

But yes, this this this is a this is a source and it's a little bit off topic today, but it's a it's a key place to pro kind of show like how you can adhere

to the same sort of physical rules but by slight adjustment in the execution model not be subject to the same downsides. Okay. So

downsides. Okay. So

with something like this all like 70 no I'd say 80% of state synchronization bugs or sorry needs for effects go away right off the bat

because suddenly you're not like writing like there's so much wrong with with with doing with doing with doing this right use effect sorry let's go back even

further I want to go back to the yeah there's so much wrong with doing with doing this

um count prop value uh depends on props value um

because like it's actually telling the component to rerun again right off the bat like like because it runs sees a state uses the effect now the effect

doesn't run until afterwards so it goes through renders with count uh being zero. I I it's possible that if it sees this no actually wouldn't even

know even with that invalidation it run it renders with count being zero and then it cycles through and renders again.

You've never had to do this with you. You're You're telling me you've

you. You're You're telling me you've never done what's in front of me in React?

I I I I feel like you hit this problem within the first two hours of using React. Like every developer has hit this

React. Like every developer has hit this problem.

You've never used use effect to synchronize state.

Sorry, I I I'm I'm I'm I'm like whenever you see those horror examples on Twitter with forms and all that, it almost always boils down to

someone doing something like this.

Like React had to write a whole doc section specifically on avoiding this pattern because it's literally what everyone does.

Yeah, people do it now, but this is like the like this is like the the dumb pattern. Everyone I I don't know if

pattern. Everyone I I don't know if React ever suggested this was a good pattern.

We have UI live management to lots more.

We have tons of this. Yeah, like this is the problem is this is a very common shape like it's called the ephemeral override state like scenario like this is like

the what is a good pattern in React?

Sure. Two things. The easiest pattern for this in React is is this uh let's do value

so we can see it.

The easiest pattern for this in React is that when you call this component, you do this key props. If you do this, every time value

props. If you do this, every time value changes, the whole component is going to reset, which means it's going to create new state hooks, which means it's going to get the latest value. Um,

right? Like it's basically going to throw away all your previous state and reset reset it this way. This way you don't need synchronization. Now,

obviously, if you have multiple of these and then you'd have to come up with like an interesting like if key or value like I mean I guess you'd be fine with it over rerendering but you know get all

your get all your depths in here so to speak you know um I guess if I made this an array that would be awkward because then the array

would be a new instance every time. Um,

but you you can basically create your dependency array for your effect in your key really really I I'd be interested at some point to hear why how felt by broke your brain. I mean unless it's like what I've

brain. I mean unless it's like what I've been talking with the async stuff which I think is breaking everyone's brain.

I understand in the thing I just don't see reason to store a prop value and use state. Okay,

state. Okay, picture this. I I I I mean the example

picture this. I I I I mean the example with forms is really really really easy.

Um I have an input, right? Bunk. Actually I

I deleted too much function input. Okay.

So now it is an input component. Okay.

Input. Okay. And our input component is going to graph uh an actual native input. Okay.

Now, we want some sort of way of this component saying what its value is.

But I mean, I it's going to be a complicated input. It's going to have

complicated input. It's going to have like other functionality in here, which is why you wrapped in a component. But

we also want the ability to manage it in here. So like essentially we don't

in here. So like essentially we don't want to save we don't want to do like this like we don't want to like on like input might not be because it has immediate feedback but like some kind of

component like on save or something like we don't actually want to to pass our information back until we we commit it.

like let's like let's pretend our input has a button to save instead of like in instant typing. So our input bas

instant typing. So our input bas basically wraps like uh like you have to press enter to commit the value. So

there's this temporary state that essentially gets initialized from here but does not get communicated back up here to get pushed back down. It

actually stays inside the component while you're editing it and then when you press like enter or on save it actually communicates the information back up. So in this scenario,

back up. So in this scenario, if the input ever coming in changed, you need to actually reset this count, but you also want to have a temporal

override until you're ready to communicate the change back up. It's

just like a temporary uh state. I I used an input here. Um

but basic basically the idea is that you have some kind of like temporary like scratch pad that doesn't doesn't impact the rest of the system. it just lives locally,

right? In this kind of scenario,

right? In this kind of scenario, you you're you you're going to need to initialize it with this, but then you're also going to like, you know, maybe there's a button in here, too.

I I mean, I'm just making stuff up here, but then like on click, this calls on save, right? So

at the end when you click on save it will hopefully you know we'll do something like you know value you you'll probably set it to like set

my own set my count to value and then you know my count or whatever like is here like

you you'll close the loop but generally speaking this has to be although even though it's derived from this, it needs

to um it it needs to uh have its own temporal override. And as I said, this

temporal override. And as I said, this this pattern is relatively common. forms are where you see this like a billion times, but

it it also happens in other situations like um just like places where you need to isolate changes from the global store or like places where you like any place

where you you do some kind of speculative change and and it doesn't have to be like over the course of like a specific life cycle, right? It's not

we're not talking about like like optimistic updates necessarily. We're

talking about like something that could persist a while. Um, sometimes errors are another example of kind of like a speculative kind of override where the life cycle isn't necessarily tied to

either the action itself or to the the persistence in the in the store. It's,

you know, these kind of patterns naturally emerge.

No, that's that's what I was getting at with with key. You'd have to like you'd have to like somehow register them all and any of them would actually cause a

change potentially. Um

change potentially. Um the if you I don't need to go too far, but it's like uh React docs have a whole page on this. Uh when not to use use

effect.

You might not need an effect. Beautiful.

These docs are worth reading for every single person in any framework, but it's very react specific, but I think I think this is important.

React key is such a hacky solution.

Yeah, I I don't like it, but I understand because it's often the simplest. Like they're examples

simplest. Like they're examples literally what I talked about the like this example here the obvious answer is you should just derive it like

this is a use memo case you don't need to like make it a separate state for full name set name but what if it's writable

then you actually well see the the if you can calculate it during rendering this is better right but some sometimes you need it

stapes add little thing like they have a ton of examples in here. This like react knows this is an

here. This like react knows this is an issue which is why they have quite an extensive thing right post request like this is so common

where's the key example it should be yeah here's the key example Oh, this is this is the general better approach where you like but even because

what this can do is React's smart enough that if you invalidate its own state in the course of rendering the component because this component

here is like the state is part of the same component, it goes, oh, when it go before it like renders the component and the JSX structure like the virtual DOM, but then before it actually tries to

realize it or reconcile it, it goes, uh, in the process of this, we came invalid again, don't continue, like don't go on to the diffing and patching stage. Rerun

this component with the updated state again. So, it's more effective. If you

again. So, it's more effective. If you

use use effect, unfortunately, you actually cause a full render cycle where it actually does do the diffing and patching and then comes back around again. So this is better to do inline

again. So this is better to do inline writes um during the course of of this.

Um but I mean this is also kind of weird because it does cause the component to rerender again. Um

rerender again. Um but because the component is the only how should I put it? Because the

component is the only unit of reactivity that react has it it actually like it doesn't have many choices here.

Rerunning the component is better than rerendering running the the render cycle.

Most of this article is just David's.

Yeah, David from Xate made this thing.

Anyways, I'm not here to necessarily solve React's problems for you. This one

is solvable. Uh, and I I I showed you how we solve that with Solid 2.0. Very

simple. You just derive the state. Done.

whole class of use effect just goes away. Um, but these two problems are

away. Um, but these two problems are trickier.

No, it's actually it actually stays working like create memo.

The reactive update overrides your local setters.

The idea is that the derived value is the override. So you you derive it

the override. So you you derive it initially, you can override it and then it can always be reset by the derived state coming in which is what exactly you want in all of those use cases. Now

you could be like well what if I wanted it only to initially work reactively and then um and then just override it. Well

I mean in that case you didn't need any of this mechanism. You could have just like unttracked the read or just like set the value like that's the default because our components don't rerun,

right? Like the default is

right? Like the default is like the default for all frameworks or like like React is this. It's like it's derived initially and then you override it and it's all the the hard part is

actually making the override re like or making it reset the override.

Right?

So, I I want to talk about both of these because uh the these are controversial because these are arguably the things that people love most about signals and

hate the most about React. I can just autotrack anything. I don't have to this

autotrack anything. I don't have to this delayed commit because I can literally just ask for the signal or the drive signal or anything down the chain afterwards and get the answer right

away. And the problem with async is

away. And the problem with async is those two things are no longer true. So

let le let's start with probably the most controversial truth even though it's the least deniable one, right? No one no one can argue with this first flush one and I'll

kind of explain a bit why. Um okay now this is this whole thing is just explaining uh just async. We we can talk about that in a a minute if we have to but I want

to talk about this commits thing first.

Right? I've covered this so many times in the past, but I wrote an article a while ago. Probably worth it. I was

while ago. Probably worth it. I was

really struggling around the time solo 1.5 with this.

Sorry. Is it possible to reset a derived signal's derived value after updating it? I mean, that's what it would be

it? I mean, that's what it would be doing right?

It reruns the memo and then that's what it ends up with.

Um, so this is an old experiment that I did where I I was showing this React example where I had state, drive state, and then a DOM element. And I was like, after I

set count, what the hell do we get if we log all three of these? So this is just a counter.

Oh, uh, we actually have that. It's

called refresh in Solid 2.0. Um, so yes, you could do that if you wanted to, but the the primary way of doing that is actually just updating the the prop the

reactive props.

No, like you don't even have to set signal. You can literally just tell the

signal. You can literally just tell the computed to to run again, right? Usually

it will automatically run because the props change, but if the props didn't change and you wanted to do a reset, we we have this specific mechanism. It's

very useful for async, but it could be useful in this case where you're just like hey like reset it to like just rerun the computation again or in the case of async refetch this again, you know, like

for invalidation. So yes, we we we do

for invalidation. So yes, we we we do have this mechanism.

I the big the big thing is like having extraneous set values are kind of the things that I I I kind of want to

avoid. I think

avoid. I think like when you h I think it's a lot cleaner to think about it like I need to reset this computation rather than like have to like write it back. Do you know

what I mean? Like cuz like there's there's more truth in like talking about the derivation of it than like just being like okay in this condition then write this and because I know that this is what the source is then it'll be

fine. I mean you can do that but that's

fine. I mean you can do that but that's that's not like as clean.

Yeah. As refresh is literally rerun this computation.

Yeah.

Truthfully, the value shouldn't have changed in most cases. But here's But with the with over Yeah.

Yeah. So, the reason I showed this is because this we were I was working on Marco. We discovered this and then we

Marco. We discovered this and then we realized that every framework logged something different. React log 0000, Vue

something different. React log 0000, Vue log one 120, spelt 3 or 4 logged 1 0 0 and solid was 122. And if you look at

this on in a in a in a in um in the abstract only react and solid are correct arguably because like they're the only ones that are

consistent like zero if if count is zero then double count is zero and then the DOM is zero consistent. If you look at solid also consistent if count is one

double count is two it's zero. spelled

mimics JavaScript um things because if you update count then double count and current count couldn't be updated. So,

like it makes sense from a JavaScript thing because the the stuff hasn't happened, but it is an inconsistent view. Like you're

view. Like you're like arguably I'd argue you shouldn't be reading after you set the count, but it is

there's there there's like it's hard to argue with this expectation because it like in a synchronous frame it makes sense. And then Vue was kind of like

sense. And then Vue was kind of like we'll do the reactive stuff but not the DOM stuff.

Now the truth is at the end of this article I was like maybe spelt is just right because and and the only reason I said this was because I'm like React is so painful. No

one likes React.

This is great but it's it can be bad for performance. Solid solid's granular so

performance. Solid solid's granular so like you can get away with doing this but like fundamentally speaking like as a general solution if you do like 10 updates you probably don't want to render 10 times you know. Sure, each

update is pinpoint, but there's going to be cases where that's not the case. So,

as a default, this is like putting a little bit more on the user to be like smart about performance. And like this, like it's okay. I don't hate it, but um

maybe not amazing. Um this one everyone hates.

This one I can at least explain even if it's like less than ideal. And this one is like this kind of magical happy place but also

maybe alive. In the end, what ended up

maybe alive. In the end, what ended up happening is everybody just ended up going to view uh more or less. Um solid is still on

this right now. Um unless you call batch explicitly, but generally my plan for solid 2.0 is this. My spelt five is

this. Um, and that's how I like we were

this. Um, and that's how I like we were all going to be here with Vue and React was going to be by itself. That that was the plan for Solid 2.0 like four or five

years ago. In the last year and arguably

years ago. In the last year and arguably in the last 6 months, I just realized that React's version is probably the only correct version here, which is a

really tough pill to swallow.

Yes.

Because the problem with with these models is one is doable or sorry spelt is doable but it's it's a

little bit misleading. I I I I could argue for this approach still like I did in this article. But the problem with async is you don't know necessarily

what is async when you're just like sitting here reading these values. Sorry, I don't need to go back to the original tweet.

Right? When you're sitting here reading these values here, like in this event handler, like sure the async stuff is is is defined over here, but here you're just like I'm getting count double count. like you you you aren't aware of

count. like you you you aren't aware of this and this could be in your UI under different conditions of loading. You

want what you're dealing with here to reflect what your user is actually seeing.

So like let me let me go back to the article here and basically the same example. I I didn't put the DOM in

example. I I didn't put the DOM in because that the question of when the DOM flushes um is a question but it kind of falls out of the other two, right?

Like the reality is the the actual question is what double count should show and what count should, right? If

you if you if you go back to this example here and you kind of crunch it down in if you ignore the DOM view and

solid are the same and then I and if you go to spelt 5 now um actually we're all the same except for React, right? So that that's why we're

React, right? So that that's why we're able to kind of do this compression. I'm

not going to worry about the DOM. If

you're React, clearly the DOM hasn't updated. And if you're the others, the

updated. And if you're the others, the DOM may or may have not updated. But

that is secondary to the actual concern here, right? Hopefully everyone's still with

right? Hopefully everyone's still with me.

So right in plain JavaScript, count and double count drift apart. Signals fix

this by updating double count on read.

But this still leaves the question, when does this update? The DOM just did that.

Okay, React was the only system that didn't update count immediately and people hated it. But the motivation was sound. React wanted event handlers to

sound. React wanted event handlers to see consistenc and it had no way to update derived values until the component ran right it's like the uh it's like the uh spelt example like

react has the same conditions like old spelt wasn't signals it was basically like react it was it wasn't a virtual DOM but like even Dominic from the st team called spelt 3 basically a virtual DOM like conceptually it had the same

component rerun model it just was heavily memoized you can it was almost like the react compiler That's kind of like how spelt 3 was. Um,

so the thing is when you look at the JavaScript of this, how could double count or the element have have actually updated when you just set the count?

It's not possible with old spelt and it's not possible with react. So you

have the choice either update the count immediately, which makes sense for spelt because they just they make it look like it's an assignment. They hide the set count thing. It's hidden behind like the

count thing. It's hidden behind like the compiler. So them not updating one

compiler. So them not updating one seemed really weird, right? Um so the move to from spelt three to spelt five was them being able

to now do this which made their story much more consistent. Um but this was kind of you know all they could do before. React was like no we want to

before. React was like no we want to show consistent value. That was the only choice here. React could not make this

choice here. React could not make this value two even if it wanted to. Neither

could spelt um three signals let you make this value two if you want it to be. The question is should it be two?

be. The question is should it be two?

And you'd be like obviously but actually the answer is not obviously. It's

actually probably no.

Calling flex occasionally is better than having to do batch. I agree completely which is why views kind of timing is what's kind of been where everyone kind of landed on

except for React and now except for solid. Let me explain why.

solid. Let me explain why.

Now obviously if we looked at books.length

length directly.

We could avoid this. But my my point here is I wanted to show an example where you have some derived value. Like

length is easy to derive. But how about something more expensive? Something that

isn't as direct. You have some derived value and you're basically nulling out the source, right?

If you null out the source and you haven't updated the dried value and you and you use that to interact with that source like you're going to end up out of

bounds or reading undefined or crashing your app probably, right?

This is why I never liked spelt's model react. I felt like if you can't update

react. I felt like if you can't update the second value, you shouldn't be updating count, right? Like if if you have no way of making double count updated, you you shouldn't be updating count because this will happen to you.

You will cause your program to crash if you put expectations on double count.

Now you can know that to avoid it, but it's just it's not consistent, right?

Like you understand here books length is five. You set it to an empty list. This

five. You set it to an empty list. This

hasn't updated. You go books books 5 - 1 is four. You read books four and there's

is four. You read books four and there's nothing there. Maybe you read a property

nothing there. Maybe you read a property off it. Oh, guess what? You've thrown an

off it. Oh, guess what? You've thrown an error like this is now frameworks that do do this have like

tick or a wait but to force the flush, right? But it's kind of like and this is

right? But it's kind of like and this is important to put in the other article.

Every framework has an ability to mimic those other behaviors if they want to.

But it's the question is like as a default should every time you set something cause you to call flush? Well,

maybe you do want to read these values.

So then the answer is yes. But if you don't call flush, should it break?

And I think React's approach is a sane one, which is if you set books here, books is still five. So when you pull out this book, you're actually seeing

the like the book listing at four. Now, should

you write your code this way? Probably

not, right? the whole read after write is

right? the whole read after write is just like a bad smell that you shouldn't be doing. The problem is that with

be doing. The problem is that with signals libraries, we we let people feel like they could do this. We were like, "Yeah, go for it. We don't care." It was

never a good thing to do, but we made it feel like it was okay.

Yes. Right. In view case, you never need to call flash unless you read from the DOM. But it's but the there's a problem

DOM. But it's but the there's a problem here.

And reading from the DOM is pretty rare.

Well, yeah. And you can conceptually be like, "Yeah, I need to read from the DOM. I'll call flush myself." Like, it's

DOM. I'll call flush myself." Like, it's it's an easy it's it's easy to get there. You can go like it's not like normal logic. Don't

need to I only need to call flush on anything or do we need still signal throw? Um, it

depends. It doesn't have to throw. If it

has a value, if it doesn't have a value, then it would have to throw. But if it has a value, it does not have to throw, right? Like as I said, like in React's

right? Like as I said, like in React's case, reading books.length being still five or whatever isn't going to throw,

right? So what does this have to do with

right? So what does this have to do with async? Well,

async? Well, we don't know if books.length has updated it or not.

if books.length has updated it or not.

You could write all your code like this, right? write all your code be like I am

right? write all your code be like I am synchronous everything is up to date I'm using signals don't have to worry about the stupid reactism and then someone realizes that this derived value of

books on length actually needs to be calculated from something on the server and suddenly you've produced this problem because

this updates right away and you're like sweet empty and here it's five it's out and it throws And it's not where you declared

your your async work. It's not happening in here. It's happening in the event

in here. It's happening in the event handler. It's happening other places.

handler. It's happening other places.

You know, because that async work might not even be in the same component.

A you you've basically broken the graph and you've basically because you depended on this behavior potentially have Now crash errors all

throughout your application.

Only a problem with color syncs to do.

Well no.

This is a problem. This problem is not what color because all async becomes colorless once you pull it into the into the system. At a certain point, you have

the system. At a certain point, you have to consume it, right?

The I will say that the other problem we can talk about it where color stay async makes it trickier. This is like if this was felt and I put a weight

count number two here double count like this isn't colorless async. I mean

double count like derived if this is derived a weight count times two or whatever. If if I if I did that this

whatever. If if I if I did that this here it's not colorless async in the same sense because I I needed to pass promises through in that. But as soon as I realize that value, I can't get it

right away. There's no way to get dibble

right away. There's no way to get dibble count from count synchronously. So

I this is not a colorless async problem.

It's a it's it's a realized value problem. At some point you you you're

problem. At some point you you you're going to have to convert the promise into a signal. And if anything or into like a value and anything downstream of that suffers from this

that that's not colorless async in the same way I'm talking like the the reason that we talk about colors as sync and solid is because 2.0 is because we really push that consumption point all

the way to the top. It's where it enters the graph and then we actually propagate it through all the reads. So, we get to this like very cool consistent system

where like, and I could probably draw it out for you, but where we can actually push the blocking all the way to the leaves while you can actually do the consumption at the top. It's it's

actually really powerful. But e even in a system that doesn't do that, makes you explicitly pass promises around, at some point, you're going to eat the promise and bring it into your system. And at

that point, you are no longer looking at the promise you are looking at a signal or a value it will happen somewhere in

the graph and anything downstream of that has this problem it's fundamental yeah I right okay so

okay you can solve this by yeah Okay. I

I see what you're saying. What you're

saying is like never consume it, right? But I like what I'm pointing out

right? But I like what I'm pointing out is like so yeah. Okay.

so yeah. Okay.

But you you you're going to have to consume it to get it into your rendering system.

I I like I could like I could say like, "Okay, yeah, well, fine. we should await books salt length. So instead of breaking it now, what will happen is um I mean

you I mean you're still going to have a challenge because you're going now have to go all through your app through all the places where books.length is and go okay actually books.length is a promise.

Um hopefully your your TS is going to complain because when you try and do bookslength minus one here it's going to be like uh promise is not a number. So

then you know exactly where to fix. But

as I said, it still doesn't change the fact that at a certain point you're going to actually consume it. You're

actually going to use the value, right?

You can push it down to the leaves as much as you want if if possible. But

this is there is something very fundamental about this, right? But you understand like we're in

right? But you understand like we're in an event handler.

If it are you suggesting that when we get into our component body we should fork it so that there's a consumable version that we can just stick directly in our UI and then a version that we can await separately in our event handle

like let's be practical here as I said I I' I've built this exact example in spelt and seen this exact behavior which is why I'm aware of it I you know I did in a weight derived right

I I think the as I said generally the spelt model is in the right direction I'm just saying like there's a certain truth here you have to address here that

there is going to be a point unless you're like unless you really fork the path down to every last read point here

you're going to at some point absorb the async into your graph and be behind that graph you are going to

break consistency if you if you if you flush the value immediately.

Like as I said, I we can think of ways of how you can avoid it like you're saying, but this is physics. This like

this is undeniable truth.

Um, and the and the funny thing is if if if we did do this like make double count async in the spelled example, it would show the consistent UI like it would show the like in the UI here I we would

see 1* 2 equals 2 then 2 * 2= 4 like it won't update it will actually hold the UI properly but in your event handler in

here you will see 2 * 2 equals 2 so to speak so you will break an exactly the way that I'm talking about.

I'm not I'm not doing this necessarily to poke at spelt solutions much more advanced and much better than 99%

of the solutions out there. But this is like th this isn't like like you're that's an option, but uh events are

are how should I put it? Events are um side effectful. So it's kind of

side effectful. So it's kind of dangerous to rerun events. You wouldn't

want that as a default behavior.

I can understand why you're concerned.

I'm just saying is you can't you're not going to avoid this in a signal system.

Even if you pretend like your async isn't colorless, once you absorb it, you've created colorless async. Now,

you don't need to worry about it a ton uh in certain scenarios,

but the reality is you block the graph.

You can't not block with async. So if

you block the graph, there's going to be part that is blocked and unblocked. This

is I said the reason why something like spelt will still give you the exact proper output in the UI. They they know you block the graph. They're smart

enough to handle that.

Wonder why I I'm not I you guys are going to force me to make this felt example just to show you what I'm talking about, aren't you? Like to sorry like to me this is so obvious like but

it's because I've been looking at this for such a long time. You have you can you can okay the the one way around it I suppose is you can choose never to

consume it like it just from a practical standpoint you're probably going to do a calculation at some time or like do a computed or something to consume it like the only way you avoid it is if as you

said you literally don't you don't do double count like this you literally await in here and maybe that's the answer never do an async derive like

like bas basically a weight like you you literally have to push the weight to every single call point which means that every derivation everything you calculate off it it has to go

through like a a then promise chain instead of like being able to just do something nice like count times two or double count three or format username you have to force the whole chain

through then then be very rigid to never resolve early or yes, this whole category goes away.

The reason I'm I'm I'm I'm I'm bringing this up is because is because so many of these issues

are based on like basically this kind of problem.

Like think about it. If you built built a system like React where it doesn't update after you call call it like you do you don't see it updated are you going to read stuff afterwards in event

handlers and setting state? Nope. You're

not going to do it like the the impact talks about pit of success. 0000 is pit of success if you think about it because

why if if you know the value is never going to update there why would you read it afterwards if you actually want to update it what you're going to do is you're going to take the value updated and use that

further down in your calculation right you're going to be like you instead of instead of using books length or whatever or or even read books you're

just going to take this you could be like new books and then go new books.length and this and you're not

books.length and this and you're not going to read reactively afterwards.

So React's API design actually guides you to do the right thing.

It's so like we're fighting this so hard when the answer is like kind of obvious, right? We have a real physical

right? We have a real physical constraint, something that we can try and work or hack around,

but it it's it's the it's the wrong mindset to to view these events as being inside

the system.

We have a synchronous system with events and uh side effects spinning out of them around it. If you view those as truly

around it. If you view those as truly external to the system, you can preserve the integrity of the system.

React hit here obviously because they had components and there's inside and outside the component means very very different things. But

different things. But the like the the the shape of the problem is real.

Yeah. Yeah. And to be fair, when we were working Marco, we we went even harder. I

I don't know if Marco 6 landed here, but we're like, I don't want to think about this. If someone tries to do this, just

this. If someone tries to do this, just throw. We're just like, just error,

throw. We're just like, just error, right? Which is like the the really like

right? Which is like the the really like nuclear option here. But the other option, and maybe like, you know, maybe

that's that's that's sane, but the other option is React's option is still very very um consistent.

Like I I I get it why people are fighting this so much because this is a big departure, but it's you

the the experience of what you have to force in order to get here and the impact of these changes in order to get here seems

seems incredibly extreme versus the simple truth of this like don't do this.

No, I'm not saying this has nothing to do with performance. This has to do with correctness.

Um, I'm not quite sure what this has to do with are you just talking like threading consistency model? I I mean I don't

consistency model? I I mean I don't think that's the case. Now I we have solutions with signals arguably which are not just vanilla JS things. We have

ways to force consistency that way. The

problem is these models fall apart under async pressure.

Can you throw at the D? No. Why? Why?

What are we throwing?

Also, I think I saw some of the reaction that people are probably Yeah. Like the

funny thing is the stream is like so hardcore on this stuff and it's really hard for reactive people to kind of uh stomach. But if if if I show this stuff

stomach. But if if if I show this stuff to Tanner, for example, he's just like, "Yeah, so what?" And you're telling me I just solve all of React's problems and this is the cost. It's like a

no-brainer.

You know what I mean? He's like, "Ract already has this and this is actually not even as constrained." Like it just seems like, you know what I mean? Like

Yes. Yeah. But that's that's what signals are. But I'm saying that doesn't

signals are. But I'm saying that doesn't actually solve it.

You can't have a value you don't have yet.

The as Robbie pointed out earlier, your only way out of this is make people await here. Like but it means that

await here. Like but it means that you're not consuming the promises ever basically. like you you need to

ever basically. like you you need to make sure that everything is a promise.

Like you you you're running with two systems, a promise system and a signal system which um

could be okay arguably. Um

but it it's like even spelt doesn't force you that hard down that line.

React doesn't. React has used there's always a consumption point because at a certain point people are trying to write synchronous UI and declarative things to make it easier. They're not they're not hoping to write yields and awaits

sprinkled through every single part of their code.

No, I I don't think I don't think this stuff has to be costly. What I'm talking about is completely consistently has nothing to do with performance. It's

about consistency.

I I don't see anything particularly expensive here. This is just like truth.

expensive here. This is just like truth.

It's not about performance. It's

literally about consistency.

So, this isn't like something for AI to solve. This is not a like can AI solve

solve. This is not a like can AI solve gravity?

We can build better planes. But like,

you know what I mean? Like we're talking about physics.

So So I I spelt's a great example here because spelt actually does all the right stuff in the UI. Well, mostly for the most part they write stuff in the UI, but it's still because of the the

fact that like their variables are like this that they they they still keep their original model here. I'm just

saying like in a I and I don't even think it's a big deal because as we all said just don't do this, but in in in reality when talking about the whole

thing like so basically spelt does most of this it just they have this one inconsistency in their event handlers which probably you shouldn't do anyways.

But generally there's this truth here, right? Like um I we hit this when we

right? Like um I we hit this when we were doing uh like transitions in solid 1.0 as well like where like

inside transitions solid worked like react like you'd do the right and then outside you wouldn't see the the the stuff until the transition ended. It's

just fundamentally to be consistent, it has to work that way because you're showing the user something. If they're

interacting with it, they should be interacting with what they're they see, not some future state that doesn't exist yet.

They have special spell events. Have I

missed that? I try and keep up on stuff.

I I I I don't know what what that is. Um and I don't think looking special events is going to find me on a query. I'm just

saying this is while you can ease up this constraint if you want to, you know, in small ways, it's hard to argue that React is the is

the is not the only solution here. that

it's completely correct.

It's arguably the most correct and honest approach, right? Like you we can we can we we we can like pretend it's otherwise and it will probably come to

bite us later. But even if we can this is this is the reality I had to face. I

I realize like I I could do this. I

could like force the reactivity through.

I could make it so that this was updated, but in some cases, but it's kind of a lie.

It's a convenient lie, but the problem with convenient lies are they will catch up with you.

Like I'm only thinking about the design space. I understand right now if you

space. I understand right now if you move to the future, you don't even know what kind of problems you're going to hit.

So like you kind of it's usually better to air on the side of doing the consistent honest thing than lying unless you are completely sure you can

get away with lying.

I know this not something we we love.

um dependencies of effects must be known at computation time. Now this is true that

computation time. Now this is true that yeah but that's not solving it. Sorry, I

if I haven't made it clear enough because people read this article and they're like, "Oh, yeah, view." No, it doesn't.

You can solve all of these using explicit APIs if you know to do that and guard them, right? As I said, uh I said

this in the other article like if um you can use await tick or uh or next tick in in a wait tick in spell next tick in

view. Um I think this might be a settled

view. Um I think this might be a settled thing now in spelt 2. Um in solid 1.0 you could get reacts behavior originally by calling it in batch later that was

just a way to get views behavior. Um

uh you can you know like in react you can use the callbacks on the setters as a mechanism to get something similar to uh views behavior. Um

like all the frameworks have escape hatches for the other behavior if you know to. The problem is if you start in

know to. The problem is if you start in one state, you don't know to change it.

Like it's not about like being able to do a wait next tick. It's the fact that you changed your code somewhere and now you need to do a wait next tick in like 10 different places you didn't realize.

I don't even know if I should read this one out loud. That's funny. The obvious

solution is using Remix 3. That's funny.

Um, so sorry, what is felt event delegation managing for here? It it delays running events while things are held, but then it wouldn't even be showing them. So I

don't Yeah, I'm not quite sure what I like I've definitely reproduced this bug in spelt like 100%. It's felt live.

>> I mean, I I get kind of asking the remix question. I get why people are thinking

question. I get why people are thinking remix. Um, I don't know. My gut here is

remix. Um, I don't know. My gut here is that Remix has changed their approach. I

don't know what Remix 3 is right now, but the version of Remix they showed at the unveil, I am very much in the camp that that approach is not

the way things need to head. I think

they've they've refined stuff since then, but I don't know. We won't know until they reveal it, so it's hard to say. If you're talking about the remix

say. If you're talking about the remix as they presented it a few months ago, then even it doesn't matter if AI can generate plain JS code because the

problem is plain JS code doesn't have all the edge cases encoded into it, right? Next thing you know, you're like,

right? Next thing you know, you're like, we did this on stream a couple weeks ago. You're like managing a bunch of

ago. You're like managing a bunch of extra states. Sure, they're not

extra states. Sure, they're not framework states, but they are effectively different states that you're writing to to manage like the the life cycles. And

cycles. And because they're not framework states, you're the one responsible calling update. Who cares? Your code is

update. Who cares? Your code is vanilla.js, but you didn't take into consideration all the edge cases. And

now you're talking about things like abort signals and stuff that could just be handled automatically from the shape of the graph. And instead, you're man manually managing this stuff.

Yeah, I mean you can create a debounce signal. I I I I

signal. I I I I steps you can you can almost view um the if you guys ever do you guys

remember the sirky's uh triangle problem that react did that prove concurrent rendering um you can almost view this as a form of

that because we keep our effects guarantees we can de debounce heavy work without impacting the rendering at all here because in a sense

How did I solve this terribly expensive thing?

I just made a memo request an idle call back to to propagate its thing. So there's no effect here. It's just an async derived

effect here. It's just an async derived value. So I'm kind of basically leaving

value. So I'm kind of basically leaving up to this the browser to schedule it.

And because this still participates as part of our graph, all the numbers update at the same time even though this is a hierarchical flush flush out like essentially like

now if you want to detach from the graph then you you need to do a little bit more work but that's like option something that you want to do like what this is basically doing is like like if

I didn't have this promise and I just returned seconds return seconds

Then things get really bogged up here. I

think if maybe Sorry. Oh, I have to actually put the freaking fake time out in. Sorry.

in. Sorry.

Let's before we return seconds, let's put the the the the hard let's put the work in. Okay. Now, now

work in. Okay. Now, now

we're freezing up the graph while we're moving because we're doing this expensive work that's blocking. See,

we're making sure that our UI is consistent, but like look, the even the hover state gets frozen. Oh, let me get it. Let me get the yellow away from my

it. Let me get the yellow away from my mouse.

But we can just inject async into the graph here.

And now everything is smooth even though it's doing stuff that basically takes the whole second to calculate.

Anyways, you could if if you break out a synchronous flow, you can and you would have to make it colorful like in a way that even spell doesn't make it

colorful. you literally have to like

colorful. you literally have to like pretend that like you you you you'd have to pass promises all the way down and never consume them by the framework. Um

and in that world but then the framework wouldn't be aware of like you would be resp I mean you' be what where things are today in most things you'd be responsible for consistency.

No, even then like how do you how do you make sure that one like when it's zero that it doesn't show one like you you'd

have to microch everything. So like

practically I don't think so.

That's the whole point of the video is not very economic.

You could color based on what might suspend versus instead of using promises. Yeah, you can maybe like I I

promises. Yeah, you can maybe like I I saw a really cool library this week. It

was called lazy promises where someone basically fixed all the problems with promises and libraries and wrapped the promise prim but it still involved like basically

abstracting something like a promise um like an async primitive um that was independent of the rest of the of the

reactive uh signals uh kind of graph which as I said it's a direction but it also doesn't give it's like the opposite bed it doesn't

give you that it's the opposite the bet that React and Spelt and Solid are currently taking which it doesn't give you this orchestration control. The

orchestration control is really really valuable because it lets us um write our intent in a clear way while coming up with reasonable rules to isolate change

which means that you don't have to worry about what something else is doing over here versus what it's doing over here which is very valuable in this age of AI in my in my opinion.

Huh. Of course it's you. That's why

that's that's that's why that's why you asked that leading question. Can the

framework wait the promises? Yeah. Yeah.

Yeah. That's that's that's that's ex there is a model there. It's it's not one that that

like we can do a lot more if and you could argue that we shouldn't be doing this. the framework shouldn't be taking

this. the framework shouldn't be taking that on. But if we can do a lot more if

that on. But if we can do a lot more if we absorb that.

Yeah. Yeah. I mean,

think about Okay. Can I can I can I put can I put it this way? Cell 3 was called the disappearing framework because it compiled all your JavaScript framework

code into vanillajs components. That was

the argument. I mean, it's it's not 100% accurate, but that was basically the argument.

And it did so by basically taking what you wrote and then generating a bunch of code that was very

specific to the update paths and inso was fairly efficient and it kept the framework small because the framework didn't need to actually worry about very many things. It didn't need very many

many things. It didn't need very many helper functions. But the problem with

helper functions. But the problem with this is is is this um uh to-do

MVC size comparison obviously another article I wrote but I I I I can't emphasize this enough.

What happened to our app when we added 80 to MVCs in it?

And now 80 to-do MVCs might seem a lot, but it's also not a lot when you say to-do MVC is basically like one medium size to larger size component. Like

maybe it's like four or five normalsiz components. So we're talking about maybe

components. So we're talking about maybe 300 components. Now obviously code

300 components. Now obviously code splitting and other things but you don't have to get this far to see see the scaling issue.

React spelt is is when there's one to do MVC is 3 kilobytes and you're like sweet right? We're react 37 back then and now

right? We're react 37 back then and now it's like more than that but it doesn't matter by the time we get up to 80 reacts 134 and spelt's 150 because all that code it generated because it didn't

reuse helper functions it wasn't as tight it this it actually got larger and actually when you added hydration to the picture it got even larger because of the special code paths it used to have for hydration. This is like one of the

for hydration. This is like one of the hugest biggest motivations I feel not the only one but one of the big motivations why they moved to signals and something very similar to solid and

spel 5 because spel 5 is like this it does not do that it right the and the problem was that to actually write the code it there was value in having a

shared library like and another way to look is the value of having like a like there's enough common patterns that abstracting it actually made a lot of sense now don't get me wrong AI could

also design the abstraction as Well, and and but in general a a general solution didn't kind of fit in and more so when you consider all the edge cases you have

to handle when say talking about something like async the race conditions like and you can picture this yourself by we did this on a previous stream by taking something like React 16 style and

trying to implement the proper async implementation.

It's not nice. I actually showed this off on stream where we actually came up with something last stream I think where we actually came up with something fairly reasonable actually it was the

stream before and but it still was broken and then we actually went through one an example that the simplest example ever and actually fixed it on stream and it was way more complicated than actually encoding that behavior in. So

my premise here and I I was going to talk about this a little bit when I talked about the AI generated article that uh is that these while higher level

abstractions opinions might get boiled away by AI being able to just junk this stuff together you know so to speak like meta frameworks you know everyone's going to have their own meta framework kind of deal what all this is doing is putting pressure to push the core

fundamentals into the language into the core framework more in a sense react or solid or spelt or view or whatever is more like a programming language than it

is like a library. Uh at the at this point because of the way it abstracts over the JavaScripted DOM and HTML stuff, we can talk about transparency, we can talk about differences of compiler, all this stuff, but generally

speaking, it's better to think of it that way. So while you know beat plus

that way. So while you know beat plus might release a new meta framework that's basically let you do spelt or solid react or whatever you know

generally speaking there we're not talking about replacing react in that equation. Do you know what I mean? So from that perspective, there

I mean? So from that perspective, there might be a reality of this, but until the AIs can hold what I have in my head that I actually can't even keep in my

head, honestly, cuz it keeps on flowing out when I work on specific problems, unless AI can keep more than I can keep in my head when solving every single problem it approaches, we're not going

here anytime soon.

Yeah, that makes sense to me.

So, wasn't this an AI question? It's

talking about tokens.

Sorry, did I did I misunderstand this? I

thought So yeah, in any case, um, a little bit of a tangent. Uh,

tangent. Uh, where were we? Um,

I don't even know where we were anymore, honestly. That got so deep down.

honestly. That got so deep down.

Yeah, I was going to start talking about effects. I think is where we we got we

effects. I think is where we we got we where we got to the the and I was saying that there are some different approaches

here.

The PEZ effect must be known at computation time. Okay, this is a a true

computation time. Okay, this is a a true story and actually let me let me pull something up here because Rich Harris actually responded to my article um

because he said he disagreed and I I think he has a right to disagree here.

Let me see if I can actually find it.

Okay, because interesting post I disagree. He didn't argue with me about

disagree. He didn't argue with me about the flush semantics, funnily enough, which is actually I think the trickier one. Um, but if async is only discovered

one. Um, but if async is only discovered during side effects, it's already too late, which is true. The solution is to update async stuff first, then run side effects once resolved. Repeat until

settled. So you have something like this and slug changes, right? Okay. Then the

post starts updating immediately. In

other words, while it looks like a derived, it's actually a special kind of effect that gets a jump on the queue along with the control flow. The

compiler creates these effects where they see a way. So he's basically describing what salt 5 does. Um, which

is is how they get this thing. So within

effects the world is consistent. You can

force inconsistency outside effects are right slug blah blah blah but easily avoided with the system could warn without necessary. Okay. So basically

without necessary. Okay. So basically

what what he's what he's pointing at here is because they have the compiler they can look scan for these await keywords and then do like a special

transform kind of hoisting to ensure that all of that is resolved before running any side effects

which contradicts something that I actually said in the article um which and he's he's right uh he's he's definitely right there there's There's

impact of this change, but it's it's not impossible. The the the actual invariant

impossible. The the the actual invariant is this one. This is true. This is the physics. This is what you can't actually

physics. This is what you can't actually argue with.

But the the the solution of using a compiler is viable in some cases where I said it might not be. So why is this important? I I I feel like this one's a

important? I I I feel like this one's a lot easier to understand, but it's if you pretend these console logs are effects, like each independent effects,

like essentially if if you have the ability to pause or halt or execution on any one of these, you have no clue what what's going to log here. Like pretend A

returns a the letter A, B returns the letter B, and C returns the letter C.

Initially, what gets console log? I've used this example on stream, but I really want to nail this down for people here. Can

someone tell me if fetch A returns lowerase A, fetch B returns lowerase B, and fetch C returns lowerase C in some kind of like async blocking kind of

system what what gets console logged by this effect?

Obviously, it depends on the system, but I I'm like very much open to to guesses here, right? I mean, you obviously have to

right? I mean, you obviously have to answer that with this thing like, do we assume that they're null initially or do we assume that they that they that they

throw or do we assume, you know, like I use signal semantics here. Now, if the if they were awaited,

here. Now, if the if they were awaited, granted, then you would the answer is fairly

straightforward. It would log A, then B,

straightforward. It would log A, then B, then C, right? Yeah. I'm saying that these three

right? Yeah. I'm saying that these three are promises. I'm just saying if you

are promises. I'm just saying if you have some sort of system that absorbs these promises, right? So, yeah. So for Robbie saying

right? So, yeah. So for Robbie saying like if you throw it's a ab ABC abc maybe it could also be a abc

and I think it can also be there's a world where it's ABC I think is there a world where it's ABC yes there is a world where it can be also ABC um

it see results first.

How would it be?

Yeah. And it can also be AB ABC. Yeah.

Yeah. That's the last one. I think we got them all.

Yeah. Yeah. Yeah. Yeah. Perfect. I think

I think we I think we captured them all.

So we got ABC A B C ABC and AB AB BC right and you might be like who cares a

console log but picture if this was actual side effects the work you had to do I I know that effect will run only when all the problems are you show long time ago right well here's the thing I'm

just saying in general We don't actually know. It could be all of those.

Yes, that's that's the Yes, the that's where I'm getting to here. It's even

more fun if these can get updated after the fact. So, that's initial run. What

the fact. So, that's initial run. What

if uh what if B triggers an update later? Um,

and then while it's updating, A triggers an update. Like the honestly,

an update. Like the honestly, you don't know.

And that's only one effect. What if

what if these were all separate effects, right? And you you need all the effects

right? And you you need all the effects to run at the same time to be synchronous, but each A, B, and C are each logged in a separate effect.

So, you know, A is there. So, you go and log it, and then you hit B and then you, oh crap, it's async, I can't log it.

you've now broken in the same sort of way because you weren't able to resolve all the effects, you know, like what if these are based on the same change like count, double count. What if these were all double

count. What if these were all double count, double count, triple count, quadruple count, right?

You you've now broken the chain somewhere. So now you show the count and

somewhere. So now you show the count and you show double, but you don't have triple or quadruple yet. So you show the old value or you show null or like the

UI affordances can always be figured out because you can always design around them. But I'm talking about like the

them. But I'm talking about like the consistency in your data graph. What is

it supposed to do?

See, it doesn't really matter until you get to the side effects where people can see though that you actually have a problem here because if AB ABC if the if

the I if nobody sees this progression there there's an efficiency question obviously but like for performance but generally speaking it doesn't matter cuz

you know if no one's you know tree falls in the woods no one there to hear like there's no there's no side effect but as soon as you add side effects to the equation,

you it's not just enough to know all the dependencies up front in a particular effect because like if if if we if I rewrote this example

to um to something like this like if I took this and I was like okay simple con a equals a

const B equals B con C= C and then I just went like

if I just did this and I was like okay no problem guys and you ask me what it logged it's actually really easy now because we can just say it logs ABC

if there's any kind of pausing or interruption value here no matter what the order is this will log ABC every right? If you if you make it a wait, I

right? If you if you make it a wait, I mean there's there there's one challenge with this which you already know is that reactive tracking is synchronous. So in

order to do that, you would actually also have to um wrap the wrapper with the context somehow or like async context or something. So,

and honestly, um, I'm not even sure how I feel about that.

I I think my perspective is changing a bit over time, but like traditionally, I don't even like the idea of tracking after a weight. I don't think it makes sense because now you're connecting two places in time that you shouldn't be.

Like I I actually think the sync constraint on tracking is actually a really really good thing because you don't necessarily like if you if you track before an await and then track after wait you don't want to necessarily start the whole thing over especially if you're doing expensive work. Now

obviously you can say hoist the fetching outside just to wait the thing but then why are you even awaiting in there anyways you're forcing a microtask on something that doesn't need to be a microtask like the whole shape of the

solution is awkward.

Yeah. So, because if if this throws or this throws or this blocks, we basically move everything down is is what I'm trying to say. But the problem with this is that's fine for one effect.

Now I have two effects.

This one depends on this and this one depends on this.

Tada. I have the same problem. It's not

enough to hoist it to the beginning of the function. I need to run all of these

the function. I need to run all of these before I run any of these.

Yeah. But you understand the the whole problem is throwing I am saying throwing but throwing is too late. If you

interle, if you have the initial problem that I have in my article, throwing is too late here. If you throw at B, you've already ran A.

Throwing doesn't solve this.

You know, a waiting does because it has true continuations, but now you are in an async world. Do you wait every value?

Well, no. you wait promises which means like there's consequences of being colored and we'll talk about those a bit more in a minute but what I'm getting at is th this is this is why there is an

important distinction here my premise that you have to like basically do what React does with dependency arrays is because it's colorless if you are

colored you have the ability to know what you're dealing with ahead of time like Rich was talking about like in with his compiler but there There's still like an awkwardness like if if there wasn't a compiler let's say you

were completely runtime you wanted this solution to work without any fancy compilers just be purejs signals library sound like a library you know right I'm

big on plain js from like the runtime perspective on that side I we don't compile your your your your syntax

we compile your templates that's it and what what I'm getting at here is in in that kind of world, it's a lot harder because yes, you can await in

here. You sorry, you can await in here.

here. You sorry, you can await in here.

Let's like don't get me wrong. Now, now

we're we're awaiting, right?

In fact, we can even await our original example, right? We can let's just go

example, right? We can let's just go back. Let's go back.

back. Let's go back.

Let's let's await our original example.

So now await await because we know that these aren't actually async signals. They're signals

of promises. Okay. So now we're awaiting them, right? This will log ABC

them, right? This will log ABC technically, but it'll also always log it as an microtask. It will never log

ABC, right? It'll never log even after

ABC, right? It'll never log even after the fact, even when updates happen or whatever. It never logs ABC. It always

whatever. It never logs ABC. It always

logs logs a b c.

Right and and and there's other consequences here potentially. I don't know if all if if

potentially. I don't know if all if if you're expecting like it to trigger like lazy.

Yeah. Like

the problem is and this isn't avoidable by you. The await keyword does this. Now

by you. The await keyword does this. Now

if you made your own thenables like made a special signal like this and then had your own read semantics

but even then you need it you need the this is this is actually actually tricky. I don't think you can do this

tricky. I don't think you can do this without a compiler because await means async function actually means 100% microtask and

if you if you wrap it you you lose that still there's no way there's no type of wrapping that avoids that microtask what

you can do if you look like go look at spelt compile code these awaits disappear they actually compile them out I mean it's clever Um, but there's there's other impacts of

this.

Do we need promise all? Um, you could, but promise all again only helps us in this scope.

You know what I mean? Like

promise all will at least push it on to I I think one microtask instead of multiple.

Yeah. I mean, we we need that as well.

We also need read a but I'm saying read a enough isn't read isn't enough here to avoid the microtask.

I mean monkey patch all side effects and then tire dominant defer them automatically. I mean what I'm getting

automatically. I mean what I'm getting at here is I'm hoping you're starting to see that even though we're working in a computer

world that there are real constraints to the system. there is

the system. there is physics. Um,

physics. Um, now in my article I I do I I I said that the solution was this, right? It looks like a dependency

this, right? It looks like a dependency array because it is basically a dependency array because if it doesn't have to be a dependency array, but I want I'll show you some key differences

here. But if you do this now, you

here. But if you do this now, you separate the tracking from this. You can

do all of this before you do all all of this. And more so if you do this

this. And more so if you do this and you know this one has B and C to go back to my other example and this one has A at which point it doesn't even

need to be wrapped. In fact, we can just do A and then this one can be A.

If we do this, we can run this and this before we run this or this. And our

system is consistent. And this did not take a

is consistent. And this did not take a compiler. It did not take any, you know,

compiler. It did not take any, you know, it does not force microtasks on you ever. Um, except for when it has to

ever. Um, except for when it has to wait. It doesn't force like after the

wait. It doesn't force like after the fact microtasks like if these values are available to you then that's exactly what you get.

The new syntaxes is so ugly. It's

probably a very good feature. Yeah. I

mean because really don't try and don't synchronize state with effects. Don't

use effects that you don't need to use effects on. Like I I actually even

effects on. Like I I actually even though this is uglier I almost view this as a fe as a feature.

Yes.

Yes.

Because generators don't have to go async. So as long as your primitive um

async. So as long as your primitive um go as long as your primitive exposes the ability to sync read then like you you patch something that isn't a promise and

you you could actually also handle your yield in one way. So generators are actually one of the cleanest solutions here because what you can do with generators which is really really really really

nice is and yeah I mean Milo actually tried to build a whole version of before there's reactively and there's R3 right

solid's based on solid uh 2.0 started on reactively which is R1 essentially and then is built solid 2.0 know now is built on R3. And you guys are probably

like, what happened to R2?

R2 was built completely on generators.

Um, so what's cool what's cool about generators is is you can do you can do this.

There's there's two things really cool about generators.

Console.log log yield a do it like this.

What's really cool about generators is some is is that we don't care.

First of all, you notice there's no function call here. It's because the yield can be just the read.

we don't we don't actually um need to call a function here and even if it's async it can happen after and so instead of having explicit recall we can

actually resume our context simply by by doing the yield here. So like we don't act even though this is like could be async not async we don't know we have the ability to continue without having a

special track function or read function.

Secondly, we don't care if it's async, if it's a promise, if it's async, whatever. We can handle it. That detail

whatever. We can handle it. That detail

is buried. So technically, this is like basically perfect except for you everything that you ever do from now on is going to be wrapped in a generator

function. And uh um

function. And uh um what what else is not great about this?

uh performance of generators is generally like when you try to make it like Milo basically had to just stop this experiment because of performance and now so this might be the question where someone asked earlier you know is

performance a gap on the reactive systems in this case yes uh we also played with this in Marco like on the server rendering this actually makes ton ton more sense because I was saying there's actually crankjs which is based

on generators which also um is an interesting experiment I don't think components should be generators I think that was the issue with crank crank like I think crank I think if you

had a run once model with reactivity as generators that would be very interesting but crank was almost like a react model in a sense like where like the

components were generators because they were trying to like do async flow I think with a small refinement generator is a very interesting place because yield hides all the async semantics in a

way that is consistent allows you to do tracking and completely works. So yes,

but there there's a couple gaps. People

don't get generator functions generally like it's it's like really hard. People

get like almost upset when they see them. And secondly, performance is

them. And secondly, performance is terrible.

Really? It's going to be the same problem as a wait.

Can't Can't I res No, I mean Oh, no.

Does it force It doesn't It doesn't force me into a microtask, too. I I'm

saying like what if my primitive still absorbs the fact that it's a promise.

Like I if if a is a promise and it's colorful, yes, but I I I think if this is colorless, this doesn't have the same problem.

I mean, we tested this less than like maybe six months ago.

I also think that this is a little bit too exotic as people are saying like it's pretty exotic. Like even we're testing the idea by bringing generators

into our actions. I I think Oh right right.

Well, no. I No, my point was that it can be synchronous. These can This can be

be synchronous. These can This can be synchronous.

Yeah, but I don't think it matters.

I don't think it Yeah, I I I Yeah, I I get what you're saying.

Like you're you're basically opting into a model where you're okay if some side effects show up later. Like this is this is not good for rendering like like the

DOM.

Yeah, you're right. The late discovery is still a problem. I was thinking that Yeah. You know what? Yeah. late. Yeah.

Yeah. You know what? Yeah. late. Yeah.

Yeah. This is this is this this isn't even 100% solution. This

is like good in the sense that like the the effect itself executing is fine, but it doesn't it doesn't actually again

doesn't help us really with like this either, you know, like this is still a problem because we don't discover this until I

Yeah.

Yeah, exactly. Thanks, Robbie. And you

guys are dead on. I got way too excited about generators. So, yes, supporting my

about generators. So, yes, supporting my This is physics.

That's not what impression I got. Maybe

there's some new stuff that I haven't seen yet and I'm excited too. My

impression is more that what I'm talking about is more like the Rust of JavaScript frameworks. You'll see when

JavaScript frameworks. You'll see when we get into Salt 2.0 for better or for worse because the way you constrain this stuff is through lots of errors and control mechanisms. And remix is more

like the jQuery like it's like lets you write as much garbage as you can but then it it can absorb it.

So okay well I mean so yeah so the our conclusion is actually generators don't solve this either. So you're you're forced to basically do some kind of

inscope compiler analysis or you know just freaking split the effects already.

Now is this I think this is better than reacts dependency arrays for multiple reasons.

First of all, first simple thing is we have prior art here. Vue watchers have done this for years. Even if it was for slightly different reasons, it proves that people can work with this. It's not

you. I don't remember people complaining about Vue watchers because Vue only got the combined effect like in some point in Vue3. I I think you had to do

in Vue3. I I think you had to do watchers all through Vue 2. Nobody cared

like it wasn't like React. And I I I think there's a couple reasons for this.

First of all, this stuff is dynamic still. It's not a fixed thing. You can

still. It's not a fixed thing. You can

conditionally subscribe. You can change the dependency

subscribe. You can change the dependency arrays. You can like it doesn't have to

arrays. You can like it doesn't have to be an array. It can be an object. It

could be a single value. It could be whatever the hell you want. It can be deep. It can be nested. It could be

deep. It can be nested. It could be whatever does shape, form, whatever you need to track. It can be done. Don't get

me wrong, there's pain point here around deeply conditional logic stuff that probably should be split into multiple effects for example um or like requires stuff like don't get me wrong there's

limits here but purely 0.1 compared to something like react is it is still very much dynamic it can still discover dependencies when

you call a function that isn't in scope right second difference values are passed through you don't read see in

here like as a function you read it from here which means that oh what if I miss a dependency you don't miss a dependency because if you try and read C in here

we'll tell you that you're reading in an unttracked scope I think I finally got that bug fix that it wasn't working um you know uh no I probably should uh update my

template here actually let's go stack blitz for a second and go what have we got uh beta template. Solid 2.0 beta template. We did a release today, right?

template. We did a release today, right?

That's what I was doing a few minutes ago. Let's update the template to beta

ago. Let's update the template to beta 4.

Oh, no, sorry. This one's beta 2 still.

I think it might be beta 3. Update this

one to beta 4 and beta 4.

Save.

Let's just refresh the whole thing.

Should an effect also throw when you when you read a signal in effect inside of an effect like inside the back half? Maybe

throw. I've been I've been playing with warnings, but let let's let's fork this and and play a bit because hopefully those things that I was trying to show in the previous stream actually work

now. Okay.

now. Okay.

So, let's let's go here. So, our first thing is let's gut all of this stuff for a

second and just give myself a hello. Am I

alive? Yeah. Hello. I'm alive.

Beautiful. Okay. Second thing we want to do, we want to

what is it? import

create signal and probably create effect from solid J. It's beautiful. Okay, so let's

solid J. It's beautiful. Okay, so let's go const count count. We're just making a counter

count count. We're just making a counter set count equals create signal zero. Beautiful.

zero. Beautiful.

Um, we can count in the UI just for fun. Um,

whatever. Let's just make it a button.

Get I'm glad HMR is working properly now click do the simple thing set count C + one

lovely okay cool counter working okay so let's create our effect create effect and let's make it depend on C but then do something funny like console.log

C sorry it's count on count and console.log log count.

and console.log log count.

Sorry, let me I don't know why I refreshed that. I didn't mean to.

refreshed that. I didn't mean to.

Is this going to work properly?

Reactive value read directly in effect callback will not update. Move it to the tracking scope JSX a memo or effects compute function.

There we go. Thank god. So,

and it's going to keep on bugging you about this. So right off the bat, if you

about this. So right off the bat, if you try to read a reactive value on the back half of an effect like this, it's going to tell you you

are doing bad things. Okay. Um, thank

you. Just like if you try to read count out here at the top of your component, it should also tell you that you're doing bad things.

Although I'm not thinking I'm not seeing it.

Why is that one still not working?

It's annoying. I I spent so much trying to fix fix this. It actually gives you the component name and everything.

Oh man, that's so annoying.

At least the backup the effect one's working.

I I fixed, you know what it is? Solid

refresh. I had to fix solid refresh.

That's why. Uh let's remove our node module. Remove our package

module. Remove our package lock the PNPM lock. And let's try this again.

Yeah, side dev4 side effect is much better than death side through react.

Yeah. Well, because you pass them through right?

All right. So, hopefully

this is this was just a module update issue.

Yes, I I a reactive valley red in directly anonymous will not update. Move it into a tracking scope.

It's anonymous because of this style.

Oh, that's that's that's unfortunate. It

can't tell the name. Like if this was called function app, it would know.

Like if I if this was instead function app, it happens.

reactive. Oh, but it's your compiled name. That's interesting. Reactive

name. That's interesting. Reactive

values read directly in app 2 will not update. Move it to tracking scope tsx

update. Move it to tracking scope tsx thing. That's okay. It's not perfect,

thing. That's okay. It's not perfect, but you get the idea. Effect red

directly and effect callback will not update.

So what what I'm but what you understand what I'm getting at here? Here we were talking about the rust of of JavaScript frameworks, right? The funny thing is

frameworks, right? The funny thing is you might be read this like does that mean solid has a bunch of hook rules?

There's still only there's now a second rule. There used to be a rule about

rule. There used to be a rule about losing reactivity, right? You don't want to read in a top level scope, right? Now

there is a second rule which is that you don't want to write in a tracking scope.

So but they they essentially are the same rules that f that filter out of this. But what's what's key about this

this. But what's what's key about this which as I said makes me really really happy is silly stuff now like um you know if someone does something like

um counter and and and does things like uh what do we want them to do here? Uh destructure.

And they're like, "Damn, why does this count? Never update." You know what I

count? Never update." You know what I mean?

Well, it starts by actually, you know, someone take some React code, right?

Fine. I mean, this is what count is a number. Whatever. Yes. Okay.

number. Whatever. Yes. Okay.

Sorry.

Did I do that? Bro, I I did something that broke something. It's funny. I'll

figure it out in a minute.

Um, let's make it this.

Make it this.

Go count.

Count equals count.

Did I break?

Okay, HMR is not perfect.

Hopefully what we will see here is Why am I not seeing the funny reactive value read directly in the

callback will not update? Where is

dstructuring? Should have found that one.

Uh, let me get rid of the effect callback one for a second.

There's so many other warnings in stack blitz. Yeah, reactive value read

blitz. Yeah, reactive value read directly in counter 2 will not update.

Move it inside a tracking scope. I I

guess it's solid refresh, which is renaming everything because it has to make a wrapper. That's

funny.

But you you get my point. Dstructuring

it basically tells you that you you've read an encounter and that and it's not going to update.

I I'm I don't even know. I I don't make opinions about stuff like this.

I just wanted to kind of like sanity check here um that this stuff works. So yeah,

essentially ignoring all the weird DAC blue issues, you can actually see that um

this doesn't update and it tells you exactly why it won't update. move it

reactive value read directly in counter two will not update move it into a tracking scope JSX a memo or an effect compute again so you might not know that you're dstructuring props to be fair but

at least there's a there's a hint I've the funniest thing is since I added all these warnings AI has gotten like I mean AI was already

okay at this stuff but like AI immediately like sees stuff and it's like oh there's a warning I shouldn't do this okay let me reenter this especially for like writing tests It's like almost like an immediate

signal for AI that it's doing the wrong thing. It's just like, okay,

thing. It's just like, okay, yeah, I I didn't see this because in test I don't see this. The the name mangling is happening like this is only dev warning, so it's fine. The name

mangling is happening because solid refresh. We could probably reverse the

refresh. We could probably reverse the name mangling so that the original component name is what gets put here and that the name like the the the mangling happens to the other one. Do you know what I

mean? Like there's probably a way that I

mean? Like there's probably a way that I can make this better in solid refresh.

No, what what's happening here is is that I'm I'm I'm dstructuring here which is doing a

reactive read. That's the problem. And

reactive read. That's the problem. And

and people hit this and they like we have warnings in our llinters to prevent this. But now there's a runtime warning

this. But now there's a runtime warning that tells you, hey, reactive value read directly in the counter component will not update. move it into tracking scope

not update. move it into tracking scope like GSX. So instead of doing it this

like GSX. So instead of doing it this way, if I change it to props count,

what'll happen is this warning won't exist anymore. Hopefully

looks like I have preserve log on. Let

me see.

Or stack with just preserves the log.

Okay, whatever. But if I refresh it, you'll see that there's no warning anymore.

and that this actually updates properly.

I still need this types here. Count is a number log log the function itself so it makes clickable to find the source.

Yeah, I need to do that more often. I'll

update that in the next version. Thanks.

I'm I'm not dstructuring a number. I'm

dstructuring props.

Right? Props is an object that has count on it. So what I was doing was I was

on it. So what I was doing was I was destructuring props.

This is perfectly valid. That's why you see a zero here. If if we initialized at five, you're going to see five here. The

problem is it just will never update.

People do this in React all the time, but it doesn't work in solid. And now we we we warn about it. But just a side note, I I

what I actually wanted to focus on here was that that the effects, the shape of effects here, like the create effect is actually kind of nice

from the perspective that People are always like, "I'm worried that I'm going to miss a dependency or something." It's like, you're not going

something." It's like, you're not going to miss a dependency because you wouldn't have it to use.

Like that's that that's not a concern here. You can't log count unless it's a

here. You can't log count unless it's a dependence. Like

dependence. Like this kind of flows out of it, right?

Because if you try and read it directly, then it's going to cause you an issue.

So this is this basically gives you the right guard rails because you're not going to miss dependencies.

You're going to maybe overs subscribe.

Yeah, getting into this is a is a is a godsend. I mean to be fair this a lot of

godsend. I mean to be fair this a lot of these can be found by ESLints but there's ones that can't be like the back half of effects is probably not easy to discover by ESLint. I guess it could it could look literally for the signature

but it might not find it in my custom effect or something you know like these can be anything. This can be a custom hook.

No. And I'm glad you asked because that we're in the next area. Can a compiler solve this? Um, and I'm wrong about this

solve this? Um, and I'm wrong about this in a certain sense, but I'm not wrong on the other on the other sense here because this is the first thing that people go to when the when they're

talking about this. And the thing is compiler can solve the general problem as rich pointed out to a certain degree if you have colored async but a compiler

can't undo the effects dependencies from a generic like colorless standpoint.

So could it a compiler extract dependency in a single effect function?

In a shallow sense yes reacts compiler does exactly that. So does felt 3. But

the compiler based extraction only sees what's in scope. You can't see the whole graph. If your sources or functions that

graph. If your sources or functions that call signals rather than signals themselves, the compiler has no way to know whether those functions are pure or whether they hide side effects. This

exactly why spelt 5 moved to ruins.

Compiler time dependency capture hit a hard limit. It couldn't track sources

hard limit. It couldn't track sources that weren't syntactically visible. What

I mean is if you've ever done this something like this in spelt, you'll know what I'm talking about.

This in spelt 4, this is like a reactive value. So if you put doubled equals

value. So if you put doubled equals count x times two, it will update. But

if you call a function that does the count x times two out here, spelt couldn't see it. Spelt doesn't like react moves would move like compiler

would like move get double count out.

Yeah, let me make this a little bit let me make this let me use react language and make or solid language and make this a little bit more visible for everyone so you can understand. So let's let's

make this solid now. So we want count set count. Okay.

set count. Okay.

Okay.

So equals create signal. Okay. So we're using

create signal. Okay. So we're using we're using solid syntax.

And then this here is a memo. Um, but

I'm gonna use an effect here.

I I'm actually gonna I'm gonna use a split effect for or like a react style effect.

Uh, how do I want to do this?

It's fine. I I will use split effect here. Like I'll use the new solid APIs

here. Like I'll use the new solid APIs for the sake of trying to show this. Um

um there's only one dependency so I'm going to but I'm going to still dstructure it for the sake of doing

this. Okay, cool. So

this. Okay, cool. So

console.log

effect. Okay

or count.

Now I guess what I should do is I should what I should do is actually write what you would think you would write instead. So let's go here. Let's

write instead. So let's go here. Let's

pretend our effects like this. So this

is in and this is compiler. Okay.

So the the difference um with spelt or solid and it it's kind of important here spelt doesn't have this

right and react doesn't have this. So

when they look and extract the the the uh the dependencies here, um their first thing would be

you'd have to have a special processing to unwrap signals, right? Cuz anything

that you saw here that was closed over, you would have to know like how to handle it, right? But the

the question is what should it handle because sorry if let's let's change this to get double count for a second. So

this is a function in react what you would do generally speaking is you'd extract the function right and then you would go okay so get

double count and then you could call get double count here.

This doesn't help us because you're still calling the function in the wrong in the wrong spot,

right? Like reason this works in React

right? Like reason this works in React is because um the component reruns. So the every time the component reruns this reference will

change. So like when you update count

change. So like when you update count you get a new get double count function which means that this will invalidate and then you will call your function but

but that that's not good for us for re on a reactive side because we actually want to track the reactive reads and this function never gets recreated again.

So what's your options? You could not call the function here essentially and like do something kind of smart where you're

like okay I see I see the I see the function I should call it here.

But the problem with this is how do you deter determine it like in something like spelt you can see that the reactive values are are local values I think um but what if

it's coming from somewhere else like it's it's a it's like what if this is actually a function um you don't know if this function is get

double count, which is what we want to do. Or if this function is do crazy

do. Or if this function is do crazy side effect, what's different between these two functions

that tells us which one should go here and which one should go here?

If it's just a symbol like React does, it doesn't matter because you're going to do all the work here anyways. But if

if if we have these two functions and we treat them the same because they're function calls.

Also not good.

What if you do create effect? I I think I already showed this that we we give you a warning.

I you might have missed that part of the stream. Um if if you if you do this

stream. Um if if you if you do this maybe it should throw or be a little stronger. Um but reactive value read in

stronger. Um but reactive value read in the effect call back will not update.

Move it to the tracking scope. Either

JSX a memo or an effects compute function which is the first function. So

we actually tell you you're doing something wrong if you do this.

So anyway, my key point here is unless everything is kind of treated top level um

like we don't like the compiler like this is the huge difference. React

reruns so when it looks at the dependency arrays they're not deep. It

doesn't really care. It just gets a symbol and goes, "Okay, if if it's closed over, like basically there's something smart it can do here. It knows

it can't read local state if it's not in the same scope. If if the function's global, so it like doesn't change. Like

the only way count gets into double count is if it's at in the in this below this component scope, which means that when you rerun the component, you're going to get a new function.

Right? This is why like what use callback does but it's kind of like funny in the sense that um like you can invalidate like if if in React if you if

you want to memoize a you memoize functions like you might go you might invalidate this function whenever count changes which is like makes sense but is completely bonkers from a signals perspective like a single run

perspective like you would never memoize a function like why why would you create a new function just because count changes is you just read count.

So in a sense a simple system like React which reruns components or like spelt 3 which reruns components could get away with this. But as soon as you have deep

with this. But as soon as you have deep discoverable reactivity, you can't differentiate between you have two choices. You have to force

this to only grab actual known signals.

So you kill composition or or you just can't do it like you you risk leaking side effects.

Yeah. Well, and the funny thing is the way we think is really weird. Like I I had guys from the React Core team like arguing with me about this stuff and they're like, "Well, how would you do this crazy case?" And they showed like this thing with function memorization.

I'm like, "I never thought of memorizing the function. I just

the function. I just read the signal like they they came up with like a pretty good con convoluted case and my solve was so simple. Um

and like because they were looking to try and solve it in a React way and I'm just like just the the the functions a stable reference like that's not what you should be invalidating on. You

should be invalidating on the actual things that change which actually made the code cleaner and smoother. I think

it was I forget who I was debating it with. I think it might have even been

with. I think it might have even been Seb himself.

My my point is from a pure like hoist the effect standpoint, React can do this, but it's but we cannot. And the same

reason why we cannot is what gives us that richness that we can do stuff like this where we can deeply discover stuff. It

doesn't have to be accounted. What if

it's a proxy with properties and stuff?

We're not looking for specific symbols that so we don't have to look in a shallow scope. The react this is why

shallow scope. The react this is why runtime reactivity is so freaking powerful.

I think I will stay with React. It gives

me job security.

So the react compiler and so no what I'm saying is the react compiler can't can't and they probably won't and spelt already is solid system. I'm saying old

spelt was different but salt spelt realized that they couldn't actually solve this with a compiler so they introduced ruins or runes.

They couldn't 100% solve it. you you the spel community was like very upset that they suddenly had the right state this and they couldn't just do let count you

know for example but this little bit of extra syntax gave spelt enough that it could it could basically solve this problem but you

know spelt isn't doing this spelt is doing it solid 1.0 O style where it just you you you write

you know you write count this this is the this is what salt 5 did 5 took you writing this

and instead outputs this more or less I mean, it doesn't use our syntax for dstructuring under the hood. It probably

just puts it on a on a on a thing, but it it goes through and goes, "Okay, where's all the references to count?"

Okay, count is here. Make that a get.

Where's this? This is already fine.

Nothing special here.

Um, yeah. And now there's no out here yet.

yeah. And now there's no out here yet.

Like the all spelts compiler is doing right now for the most part for the signal stuff is literally looking for where you your call site is. um taking the special

object there and then finding that symbol and just turning them into gets or sets.

Oh, confirm staying on react. That's

funny.

It's supposed to do the opposite. It's

Oh, no, no, sorry. Confirm this. That

always the only way to stay sane.

That was a joke. Ah, it's all good.

Basically just a solid rapper. Yeah, I

mean there there are differences in stuff and especially in the async solution, but like generally speaking, the move this felt 5 put us very much in a line and

view vapor for view as well. Like Vue

already had signals, but the actual rendering mechanics are much much closer. There's obviously differences

closer. There's obviously differences and stuff. I but like it

and stuff. I but like it I would say that I mean and this surprised no one. I'd say that spelt 5 is much closer to solid now obviously um

than spelt 3 was to solid spelt 3 was basically yeah how do I frame frame this right because spelt 3 is like react but it's actually like spelt 5 is more similar to

solid than spelt 3 was to react but that comes as a surprise to no one but probably comes to bigger surprise was that spelt 3 was closer to react than it was to solid that's probably the bigger

surprise to people like significantly closer to react than it wants to solid.

Um okay.

But my my my point is in a pure sense compiler can't solve this from the dependency. But if you attack this the

dependency. But if you attack this the way that rich has, compiler can solve this because what rich did is a little bit smarter.

So instead if if you recognize here that double count equals sorry con doesn't make sense

anymore whatever it doesn't matter but if you realize that double count is like dollar sign derived um await

count times two some effect of double count. What you

can do is like I'm not going to say this is 100% how spelt does it, but they can first of all they're not blocking your whole

component necessarily. What they're

component necessarily. What they're doing is they're probably uh kind of doing something like Async derived

like they're probably eating your await.

Remember to change it to a function. So

you call the count and then they're async derived. I I believe they has the ability to block effects. So

before Yeah, this one becomes a getter.

So this becomes a getter. So essentially

although it has to do more than that because how do they know that this dependency is on this dependency?

Okay, let's see what spell outputs.

Why guess?

Why guess? We don't need to guess.

Uh, wait, we have count already.

Let double count equals dollar sign derived await.

Um, I'm just going to do it sync. I I'm

hoping this still works.

There's no name here anymore.

I just want to see if if this picks up on it. Oh, okay. Yeah. Oh, it's Yeah.

on it. Oh, okay. Yeah. Oh, it's Yeah.

Yeah. It's even smarter than this. It

actually looks for the Okay.

What if I had another one?

That triple count.

What if I do something in the middle that's completely unrelated?

I'm I'm just I'm just really curious.

Count two. Let's make count three.

Whatever. It doesn't matter.

Oh interesting.

It tries to keep top level semantics through the async. See how

below is above is fine.

Let's let's do below.

So count let's make this three and let's make this two.

Okay, so everything above the first await is is not part of it. But then it

basically has a special runner to process these uh things and and guards the asyncness of it. Right.

Interesting. Okay. Just just aside I the details aren't here too important but the important thing to understand here is that these now are kind of tied together. This is like the consumption

together. This is like the consumption point is in the components essentially which is frees you up so that the like the rest of this can act independently.

You know what I mean? Like but there is definitely like a this is like using use in a sense um at the component level

which I think is what what Rich is saying here.

Pushbased reactivity for a for async push pull for everything else. So

obviously there are trade-offs everywhere and I'm not telling J but async forces effect splitting down dam the turn isn't isn't true. Yeah and he's right about that. Um

well he's right he's right about forces effect splitting. DX downgrade is

effect splitting. DX downgrade is arguable. I could argue his approach is

arguable. I could argue his approach is a DX downgrade. Actually we're going to illustrate why it is. Um

but maybe not quite yet. We'll get to that.

um in a minute.

But my yeah I think I I think the general idea still holds right in a sense a compiler can solve this if you look for the awaits and hoist the

weights. It can't solve this at a

weights. It can't solve this at a signals level um is is is is my point.

Um, so does this mean we're doomed to mimic react? No, not at all. This is copying

react? No, not at all. This is copying react. It's acknowledging the same

react. It's acknowledging the same fundamental truth, right? Async forces

commit isolation. Async forces affect splitting. View has had the split in its

splitting. View has had the split in its watchers for years. These aren't

reactisms, you know, like they're invariants of any system that wants to preserve consistency in the presence of async, right? So like

async, right? So like in my opinion, this doesn't erase the advantages of signals so much, right?

like we are still surgical you know we don't rerender it's and it's only the effects that require the se separation right that's a difference thing like react because the

the render model they need the the depths everywhere they have a compiler to kind of compile it away so but like it's it's important

that I think we acknowledge this anyways Um, let's kind of finish out this article.

I I think there's some important truths.

I didn't really get into why async forces consistent snapshot, but that was what I was trying to talk about earlier when I was talking about like the A then B then C. Like you kind of have to you want your effects to all flush at the

same time to be consistent. So when you have all of these aspects where you you know it doesn't I guess it's wrong to say async forces effect splitting isn't

correct async forces knowing the dependencies ahead of effects running but it does force commit isolation effects ahead and async and a consistent

snapshot these things are true right so I thank I I thank you rich for help like clarifying a little bit that effect splitting isn't an inevitability of the

problem space it's an inevitability that comes with being colorless. Um, I think the more interesting argument where we can go from here is kind of showing that

you can't avoid going colorless to a certain degree. So, you might as well um

certain degree. So, you might as well um embrace it is is is essentially where where my next argument is going. But but

my the whole thing is I don't think this suddenly makes us react if that's what people are scared of. I I I we did I did get a lot of feedback about this, but it we should recognize like I've always

said, React gets a lot of things right for really good reasons. So like

we should we should we should never be too quick to to judge reacts design decisions. I said you can judge their

decisions. I said you can judge their implementation stuff to the till cows come home but almost everything they do from like an API service side from like

a conceptual side is pretty infallible from like a theoretical standpoint. Um,

so I mean, take it through this. I

thought this was a pretty pro-react article. Um, because I'm basically

article. Um, because I'm basically admitting that signals libraries can't shouldn't hide or pretend or lie anymore. You know, this is a big step.

anymore. You know, this is a big step.

Um, I I think this is important.

I I don't think this article really hit.

I think it's well written. I think it's to the point. I think it shows great examples, but I'm not I I I I don't think people understand yet just

how important this is and the conclusions from this are. Um

but I mean that's like most my stuff, right?

Reacts stale closure is arguably a feature ning because it gives you perfect consistent snapshot. Yes. And

That is sorry where was it? Here that's

what this did. Sorry not count because we we error on that or we've worn on that. This gives us our consistent

that. This gives us our consistent snapshot back again because you don't read the count here.

This this this this essentially is what returns gives us the same guarantee. I

actually I I like the way you're you're phrasing that here because that is that is the key here. This count is in the past. You know, I had this problem when

past. You know, I had this problem when I originally um set up uh if we actually go back full circle to the the original article that

I did on consistency here.

Looking at this three years later when I first started thinking about I was really struggling with this batch behavior thing because

like I really wanted to be consistent at this point when you're outside of batches solid worked like one two two like like the way that I showed but when you were inside batches it worked like

react so as soon as someone wrapped something in a batch suddenly state updates weren't visible and it meant that our co code worked in two different modes. So if you wrote a function that

modes. So if you wrote a function that did some stuff and then someone read it under batch, it'd be completely broken.

And that was the biggest bug. I I just had to choose a direction essentially. Like

it didn't matter that much I guess in hindsight which direction I chose. I

think there's importance for correctness and stuff obviously, but in a sync world given that the capabilities of signals, it actually didn't matter. I could go the React way and be consistent or I could go the Vue way and be consistent

enough. Um,

enough. Um, I just had to choose a direction because having two different modes in solid was a death sentence for for for doing stuff

in composability. The fact that batch

in composability. The fact that batch completely changed how your code worked uh really messed with people. And in

solid 1.0, we run all the back all the effects in a batch function. That was

intentional because we wanted you don't want like in the middle of the effects run to like start triggering other stuff. You want to let the effects run

stuff. You want to let the effects run all the way through and then do your thing. If you do them in the middle like

thing. If you do them in the middle like the next effect will see different state from the previous effect if people are setting signals. And a bunch of people

setting signals. And a bunch of people tried to argue that was okay and they won because that's where solid 1.0 ended up. They're like what's the worst case

up. They're like what's the worst case happen? We just cue another effect on

happen? We just cue another effect on the back and we just eventually get there. But it meant that effects could

there. But it meant that effects could kind of like run multiple times within a single cycle depending on the order that signals set. And I never never never

signals set. And I never never never liked that. But I kind of accepted it

liked that. But I kind of accepted it here. But because in the original batch

here. But because in the original batch behavior, if you called set count in an effect, you couldn't see it on the next line. You couldn't see it in the next

line. You couldn't see it in the next effect. You had to wait like React does

effect. You had to wait like React does until all the effects ran. So if you're in your event handlers, stuff happened immediately. But when you're in effect

immediately. But when you're in effect callbacks, they would be stay in the past. And I love that because you had a

past. And I love that because you had a consistent snapshot. Effects run

consistent snapshot. Effects run consistently. They run to finish.

consistently. They run to finish.

They're always like run once, everything was good. People in our community argued

was good. People in our community argued so strongly about it because they're used to things like mobx and they and and they're like, "Look, it'll be good enough. Reactivity will settle." And I'm

enough. Reactivity will settle." And I'm like, "Yeah, but it's like you get in weird ordering states and all this stuff." And and the only reason I

stuff." And and the only reason I eventually agreed to make this change in solid 1.5 was because of the two mode things being bad. I had to choose a side. And if I wasn't going to choose

side. And if I wasn't going to choose React side because everyone hated it, I'm I'm going to choose View's side, right? Which is what I did.

right? Which is what I did.

I always knew that that was not a great decision that React was consistent and solid was consistent. going to views approach was

consistent. going to views approach was a compromise but it was a reasonable compromise one that in a sync world we can live in

but in an async world given that we can't live in it um yeah like look what I wrote here so honestly this all sucks enough that I feel the need to be aware of batching behavior and with this awareness I'm

compelled to offer consistent default that feels the sest thing to do for Many of you this is probably unsurprising.

I'm the author of SolidJS. So why

wouldn't I say that? See Solid's eager updates work well with its rendering model and are completely implanted by optin batching. But the real relevation

optin batching. But the real relevation to me was just how much my opinion changed in the last couple years. When I

first saw this problem designing Marco 6, I was all in on view's batched reactivity being compiled syntax having explicit optin felt out of place and mutation not updating is awkward.

However, I definitely would have put spelt's approach as my least favorite and right. But now I'm not nearly as

and right. But now I'm not nearly as certain. Working in a solid which

certain. Working in a solid which embraces explicit syntax, I have all the tools at my disposal. If batching is often and if I'm going to give up consistency for intuitive behavior and support mutation, I want predictability at least. And that's felt too simple

at least. And that's felt too simple model makes a lot of sense. So I

actually couldn't like even then I was actually trying to argue for spelt's model just to as I said to avoid reacts model. So coming from match

batching I don't know if there's a lesson here. I can't fault anyone for

lesson here. I can't fault anyone for coming to different collisions. These

tricky problems are why I love this work so much.

Skeptics might point out solid has all the update models in it and they'd be kind of right. I don't know. Can't beat

them. Join them.

Yeah. I

when I look at this whole old article from 2022 in hindsight, I already knew what the answer was. I just didn't want to admit it to myself.

I I think we all kind of know what the answer is.

Okay. So, let's continue here.

No DX stand or anything. Let's let's

talk about the color versus colorless because I think I think this is important because uh let's continue this discussion a little bit.

So there's some potential insolveny. We

could get rid of split effects again and whole community has migrated the causes to them. No. No, that's not happening.

to them. No. No, that's not happening.

Not too late to change course. Yeah. I

love how you guys make it sound like it's actually a bad thing when like split effects are so beneficial when you consider all the aspects.

Yeah. And the create async API is not that because create async for us is is not is not where the read happens. It's

not where the block happens. It's okay.

Yeah. So let let's let's start let's just scound all this for a second. Let's

let's see if I can pull this out and get to somewhere where we want to be. Okay.

So what's the shape of async? There's

three points when when when you're dealing with async. The first point is where the like let's pretend we're dealing with

fetching but like the the the first point in the in the measure is like creation i.e. like do do the fetch,

creation i.e. like do do the fetch, right? The second point in async in a in

right? The second point in async in a in a JavaScript framework or like framework is a consumption point.

Framework absorbs the promise.

The third point is is read where the value is actually used. Okay,

these are three fundamental stages in in when we're dealing with async um in JavaScript frameworks.

And I I think it's it's important to look at it like this because even if you if you're if you're trying to like compare different solutions, you're going to find you're still working

around in this space.

So can we can I give some concrete examples of of these APIs perhaps? Right.

I I I already did with fetch. Right. So

what's this one like? Fetch

user ID. Right.

ID. Right.

Concrete example consumption.

Actually, you know what? Let's let let let's do this a different way. Let me

let me like go like okay how does this look like in react fetch user ID. Okay

user ID. Okay let's do prop fetch user

um props user ID. Okay sounds good. Two

use.

So this is promise right I'm going to call it P user right two is use P user

and three is um actually let's get narrower than That three is H1

user.name.

user.name.

Okay.

No, I the whole point of the stream is is that this is basically science.

Even when we disagree a bit on the implementation all that there there is a certain science to this.

You can like avoid the problem but it's like it's there. Once you discover it, you can't unsee it.

Okay. So

this is an example of of how this looks in React React 19 actually if we want to be really specific.

Let's do the same for spel five.

First one is the same. Spelt doesn't use a props object, right? Or is it like dollar sign props now? I I can't remember. Seems like everything is a

remember. Seems like everything is a dollar sign. Let's Let's pretend that's

dollar sign. Let's Let's pretend that's right. Don't get me wrong, you can

right. Don't get me wrong, you can combine these. I I it's just it's

combine these. I I it's just it's important that we um that we see the separation.

Okay.

And then the this is the same. Okay.

Why is Solid 2.0 different? You might be asking.

Technically, you can do this, but in Solid 2.0, it's a little bit different.

Uh, and I have to fix the I have to fix the the spelt version in a minute because this isn't reactive.

So, it's it's it's it's a little bit I'll get I'll get to why this is important in a second.

Solid 2.0 the design is that creation and consumption happen at the same place.

Sorry, creation happens here. Sorry. And

consumption and read happen in the same place.

Okay, which is a little bit different here. See, React doesn't care because

here. See, React doesn't care because React rrenners the components. So

there's actually a problem here with React because our first problem here is actually it's probably fine if the suspense is below. Yeah, let's pretend

the suspense is below. Let's pretend

this use is not in the same component.

Okay, just makes my life a lot easier.

React gets a new user ID, fetches a new user, passes the promise through to where the use is, which is where it actually uses it, and then somewhere below that actually uses the user.

Spelt, if we wanted to react to the user ID updating, um, we actually have to change this equation a little bit. We actually have to, if

you understand the problem, right?

Because props ID has to be reactive. So

we actually have to do this if you think about it. I mean we could we could defer

about it. I mean we could we could defer um this await as well. Like we can keep both of them perhaps but I think it's

more it's let let me change the structuring here. Let me zoom out a

structuring here. Let me zoom out a little bit and kind of get to where I'm trying to get to because if you want it to listen to this, it has to be part of a reactive

expression. So essentially what spelt

expression. So essentially what spelt does is it puts one and two here and then does three here. That that it's

a it's a very like these two things look the same but they're different. Does

does that does that make sense? You guys

following?

Technically speaking, I can still separate one and two with spelt if I um

separate them across like different boundaries. But like like what I could

boundaries. But like like what I could do is I could hard because the fetch is based on the reactive prop, right? So it needs to be

derived, but I don't need to await it yet. So I I I guess

yet. So I I I guess I guess it's possible.

I think it's possible in spelt for me to do change this sorry this one's user to

change this to p user equals dollar sign derived.

Yeah, maybe this is better. Is this

better?

and then await e user like you.

Yeah, I think I think this is probably the most accurate.

Yeah. Okay. Sorry.

Yeah, there we go.

The reason I didn't put the function is is because like under the hood this is a function too like in spelt it doesn't really matter like yeah but if it's reactive you have to

listen to it in a in a reactive scope I think like they might have some sugar syntax here that I don't have to wrap it in a derived so like I like but conceptually What I'm

trying to point out here is the await is the consumption point for them you're kind of tempted to just put the await here, but if you put the await

here, you fetch too high or you block too high the consumption point, right?

So like you kind of want to like I I could be wrong about the exact syntax but mechanically this is the consumption the same way uses the

consumption here and in solid the consumption is actually here like I I

this is this is very on certain way this makes these things similar like the mechanics The way we hold is similar, but this

makes things very uh different and it's important for me to point this out because we were talking about DX, right?

You could you could argue as I said that that felt and solid can have the same dx essentially like at when you squint at it by essentially moving this

to here.

Right?

This is what I was doing earlier.

Now if if if we're like sorry let's move my my thing a little bit this way. Now,

if we're squinting, now if we're squinting, these two are the same, right? If I put them on top of each other, like create memo, fetch something, derived, fetch something,

username, username, like these are the same.

And the same way I was saying that these are the same, right?

But there's a huge there's a huge uh consequence of this DXY. You want to do this in my opinion.

DXY. You want to do this in my opinion.

This is this is where you're tempted to do. You're just like, "Okay, just

do. You're just like, "Okay, just freaking await the thing to arrive. Get

my signal." This is this is what you want to do. But this

splitting them is actually better for performance. You

mechanically you want to do this. You

you want to be able to because in terms of where these points go is this can be used in multiple places, right? P user.

So let let's let's talk let's talk some truths here. Actually first let me edit

truths here. Actually first let me edit this one. saying like

this one. saying like phases of of async is is it phases, steps, stages,

phases of async in JS framework.

Okay.

All right. Cool. And then we we we have this thing. And then what I want to put

this thing. And then what I want to put on here is there's some other rules around this stuff here. I I I can implement it here. You want to do this

as high as possible.

Not as high as possible, but as as high as high as needed. What I mean by that is if you

as needed. What I mean by that is if you use a user in like 20 components and down a whole tree, you you don't want to duplicate this necessarily. So generally

what you're going to do I mean there's caching solutions and stuff but generally you're going to fetch as high you might put in a global store you might put in a store that's happening you know like like you know like not redux but you know what I mean you

sustan whatever you you might you're going to do this as high as needed up in the hierarchy it might even be global maybe even global I mean I don't need to put that note you get you get what I'm

what I'm getting at consumption you want this as low as possible You don't want to block unnecessarily.

You you you don't want to cause waterfalls.

You you you you want to be able to like have the the the framework do as much stuff independently

without getting blocked by async.

And then here well that that is so I mean we we can we can another way we can read this as low as possible is the reading

you concept conceptually when you're designing the system you want to be able to fetch as high as needed but consume where you read that that that's the fundamental thing

here because if if you consume too high you can already see you block right you you're like if you're I If you're like if you're sitting there in your component, I I don't need to pull out

the spel example, but with the run, I like I don't know how blocking that is or how eager it is, but like they had to structure their whole async around it.

If if this is why I don't like like async components in general, like like forget this for a second. If someone was like, I think my framework should have async

components. Async component,

components. Async component, async function component component one, right? Lovely. Okay,

look at my awesome framework. response

user equals await fetch user.

So simple to write like this font user posts equals await fetch user posts.

Lovely. And actually, you know, let's let's put some props in here. So let's

let's go props. user ID

props user ID. It does not get easier than this. Like look at the DX and then

than this. Like look at the DX and then I just like return you know a couple components.

This is lovely DX.

I can go user user.

See this just I'll close it.

because uh we'll pass user here. And you

you might be like, well, why did you even do it here? Well, the reason is because user uh posts component actually

needs both. So,

needs both. So, you know, we needed both the user I could I could have put the posts fetch

below, but as you'll see in a second, it actually doesn't make any difference.

Um, lovely.

Good DX.

Yeah. Yeah. Which is which is good. Um,

I I I that helps a bit at least on a shallow level. It depends

on how lazily the discovery works, but as I said, I I I don't think this actually changes the math all that much.

I it does exist earlier. Sorry, going

back to that example. But let me get let let me get to the the gist of the problem. I mean, actually, chat, if

problem. I mean, actually, chat, if you're still awake, what is wrong with my picture? Why is this wonderful DX

my picture? Why is this wonderful DX about the worst thing you could possibly do?

Yeah, waterfalls. Yeah, like

you're waiting for user to wait for user posts and they don't need the waterfall because they actually depend on the same thing. You don't need user to get user

thing. You don't need user to get user posts. And I and I'm not even like I I'm

posts. And I and I'm not even like I I'm actually preventing my ability to even show anything too. The waterfall is the the obvious one, but async component

makes it even worse because I I how I can't even show a fallback unless it's like above it like like

I I I I can't proceed further than this.

But waterfalls are great. It looks like RSC's. Yeah, about that.

RSC's. Yeah, about that.

Well, the smart person will come in and say like, well, solve the waterfall.

[ __ ] It's not hard, Brian. Seriously,

you can you can come up with this?

Not hard.

See, our perfect DX is saved.

Yeah, I'm completely joking. Um,

promise all doesn't solve your problem.

I mean, it is a a solution to the problem. Now, they're not waterfalling,

problem. Now, they're not waterfalling, but you still have a bigger problem.

It's still as slow as the slowest fetch.

Now it's it's quite possible that this doesn't matter but look user doesn't need user post. So why the hell should user wait for user posts?

Like promise all is not the solution.

When people start when people pull out promise all in their components like when that's their solution you know you're in the wrong model like you're doing the wrong thing. Promise all is

not the solution to this. Nor is like on promise settled or any like the interesting like split promise race or

what what? No. Um

what what? No. Um

just use caching. Yeah. I mean that helps with the rerender problem with React, but that or just use caching from the perspective of like never fetch

anything and have it all be cached.

What I'm trying to get out here is this is why you don't want to consume or block high. Now, it doesn't have to be a

block high. Now, it doesn't have to be a definitive block to be fair. Like,

there's ways around this scenario, right? Like, this is the definitive

right? Like, this is the definitive block. Um,

block. Um, let's not definitive block.

Right. Uh actually, let's just not definitive block now.

Uh or maybe I forget how this works. Do

I Where does the use go? Can I promise all with a use? I doesn't matter. Maybe

I'll get rid of the promise all.

Yeah, let's get rid of the promise all.

Okay.

Now I've invented my own keyword so I don't definitively block.

Right. This is better.

Definitely better.

I also have to have a caching system or some kind of concern with that built in now because like I I actually have a problem here because if if if my component reruns and it fetches user

again, I'm actually in trouble. So, uh,

using like this doesn't really work well in a rerun system. This is this is kind of what forced React's hand here. It's

like why React is. So, you you need to separate this React like says like you basically should separate the creation from consumption. You basically have to,

from consumption. You basically have to, which is good because you actually do want them. These actually should live in

want them. These actually should live in two different places.

The the challenge is because of shared state it's difficult to make this as low as possible once you start forking if you

want to derive it. I mean don't don't get me wrong like go ahead we can we we can make a component tree where like

we have you know we pass something all the way through like and like if you if we want to derive something we could use promise chains right you could you can

always like uh u not this one this one you know going back to our our lovely example here right we have to pull this out now Um,

so realistically this is our user section component. So we could go

like props dot user P user promise and then we can go somewhere up here.

We'll make another thing like let's call it app for now.

And I'm going to assume the app knows about the the the ID the ID here from its props. I mean it could be like

props. I mean it could be like I don't even know what to call this.

It's not even an app. It's like user page has the routing information and then we we

yeah we can do something like this and then make user pro use user promise.

I mean this isn't an actual real app. I

just and props dot user posts promise, right?

And then we can have user posts promise equals fetch user post. I should have just copied

user post. I should have just copied this before.

And then we could this g this gives us a good place to put our suspense boundary by the way.

Why not? And then

now we can uh make our user section um user promise

or and then we just go user promise equals and we can also do um user You know what? You know what the problem

with this is? We should actually make this user.

I'll continue with this direction for a second, but I I I I don't like this for a reason. I'll get I'll get to it in a

a reason. I'll get I'll get to it in a minute. We can make this user posts

minute. We can make this user posts promise.

The reason I don't like this is because as it turns out while this works um our user section

actually also works in a place where the data is available and doesn't actually need to be a promise, right? Because

like right now um our prop types are kind of like what are they? Um

are they? Um user promise is what uh promise of user let's say

and user posts promise is a promise of user

oay probably and then that will work. And actually,

while we're at this, let's let's fill out this example a little better. Let's

let's you know, let's user posts.

We don't actually we can we can move this use down here, right? Because you don't actually need

right? Because you don't actually need it up there. So, let's move it here. Um,

that's not is and we can go props dot user posts promise because we actually have to yeah so our prop type here is we

actually want um user user posts promise

which is a promise of promise of user sorry like that. This is

just I know there's a lot of plumbing here. I

just have to make sure that all my um prop types coming all the way down are the right ones because Oh, and it's also

takes a user which is not a promise.

It's just type user, right? Okay, cool.

Um I could make it actually you know what though? I could I could make it

though? I could I could make it um I mean for now we'll just do this and then

that that roughly looks right, right?

Yeah. Yeah. Yeah. We should we we should make it actually support both. So we

could make it user or a promise of user in case right and then this could be user and then our local user could I can you use on a

synchronous user probably they probably support that I don't know someone react will will know user will

know better so then we can make it user posts or array or promise of user post array.

And then we should do that down here too because now we we can go either way now.

Which if we go either way, we actually should probably bring this down here too and call the use here just in case, right? And then

because we might use user post somewhere else. So

else. So I just I really want to make sure we're capturing the DX here. Okay. Really

really want to make sure we're capturing the the awesome DX here. Um

yeah yeah. Okay. So yeah, this is cool because this supports both and we can read them both here and then this is fine. We started here,

we pass them here. So these are actually sorry type user. Yeah, that's good.

Okay. And then so this might be of type user post. So it can be a promise or not

user post. So it can be a promise or not a promise. And then

a promise. And then I mean there is I guess to be fair

now that we do this we can actually remove this right because now our user could

we don't need the block there because we can defer the blocking here. Um

right. And now Yeah, exactly.

I And then our props will be of type user.

I think I got it.

Okay, this is not bad.

I I would I would argue that at some point like we we this is still simple. There's

no conditional logic. There's no like like there's no like like if there's further conditional logic then the use might like we can get

the use pretty far down right if we want to. I mean it's not into the template

to. I mean it's not into the template level here. Although I think you can use

level here. Although I think you can use use in the template in React but we we'd have to worry about where our suspense boundaries are. Like I I think probably

boundaries are. Like I I think probably in this case we'd probably want because we have to either use a post here, we'd probably

want to wrap this one in a suspense boundary too to make it uh separate boundary.

Um right wrap that one in suspense boundary too.

Yeah, I I like that. Yeah, we we we can make maybe maybe promise is is nice.

Yeah, let's go through here.

You know where I'm going with this, Robbie?

No the maybe promise um is T or promise T.

I like that.

Maybe promise. Yeah,

nice.

All right. Okay. Cool. Um, and as I said, the the proper solution in spelt five

probably looks 90% the same as this.

All right. I'm missing the T.

Yeah, I mean to be fair, this level of prop drilling is not that bad. I I made it seem really painful because I sit there and and did all the promise. It's

not just a prop drilling. I also have to actively consume the use in the places as well. And I I mean

as well. And I I mean It would have been a fun exercise, I suppose, if we had started with this the system being synchronous and then added the promise to it and then basically went through and rewrote all the

components because the the difference with a colorless system is I could make the change right here and

not touch any of these other components and they'd all work.

Right.

It would be just as bad with synchronous. You're right. But if it was

synchronous. You're right. But if it was but the but changing from sync to async um is involves touching every single touch

point and then actually the use is actually and and the awaits are actually additional overhead over synchronous too.

Well, I mean, we we like the reason that I'm trying to show this off here is this is mechanically what you you you want this separation

here mechanically, but how tempted when you have a run component are you going to be just to do this? Because Picture

I did this in React syntax, but picture if you like you could picture if your component structure

wasn't like this. All these maybe promises weren't there. Right.

Right.

Right. So, I'm going to remove all the maybe promises for a minute. And you

didn't have any of these uses either.

Okay.

Okay.

Let's let's look at this a little bit more practically, right? And you're just starting here and you have this conceptually right?

And someone came in like okay well this is simple we have an async primitive for this. So all you have to do is do this

this. So all you have to do is do this user and then you go okay um I'm going to do uh derived

use I'm going to use like a solid like syntax here but I'm going to do drive await pet chooser or let's call it memo doesn't really

matter memo demo await fetch user.

Tada. Guess what?

This is like a reactive library. So we

don't need the like you know like this this sorry this should have been a wait or some cash out. It doesn't really matter. But so we we we know that we can

matter. But so we we we know that we can read this underneath here. So

technically I didn't need to change sorry user posts. I didn't need to change any of the components. I just

wrapped it in an async derived at the source and everything works and you're like sweet except there's a problem actually. Um

the suspense boundary doesn't go here.

Actually the the the suspense boundary goes out here now. So you're like, "Okay, whatever. I'm just going to

"Okay, whatever. I'm just going to I mean this is not hard return suspense.

I know this is a weird hybrid weird component system but I'm just like this is not real. This is not spelled.

This is not solid. This is just user page and we're going to pass in user ID

ID whatever doesn't matter.

So what did I manage to do here? I I I saw that I had some async and I was like sweet. All I have to do is create a

sweet. All I have to do is create a boundary around my async and then just async derive it and everything I have

automatically just works.

That's great. That's great DX.

Um I'm missing a comma somewhere. I don't

feel like trying to figure out where I'm missing that comma though. um

because because it's really easy. I can

just take my whole app that did a bunch of stuff, right? Um I probably didn't even have this suspense component down here either yet. No. And I I can

basically just add some async fetching up high where I was doing my fetching would do my fetching and then wrap it in a boundary and call it a day.

No.

I yeah, that's not my only point here.

My actual point is the DX that you want is solids DX, but that's not what you get.

This if you give people the ability to do this, they will do this because this is what you would do in solid, right?

The difference between this and solid is that this blocks here, not down at the leaves. The solution, it works,

leaves. The solution, it works, but it blocks at the wrong place. This

is great developer experience. This is

easy. Unlike React, you don't have to worry about the components rerunning, per se, like in whatever system this looks like. you know, you just make it

looks like. you know, you just make it an async memo or async derived value and you just wipe your hands clean it. The

rest of the system isn't aware of the asynchronicity. It all loads and it all

asynchronicity. It all loads and it all it all works.

This is the path of least resistance.

It's also the path of least performance.

people will gravitate towards doing exactly this.

I mean wouldn't you you just saw that what we had to do we had to go through update all the props add all the use or weights all the way down through go through every single component in this

tree and do this migration or we could just freaking fetch it at the top so that we get rid of our waterfalls.

Guess what? This this maybe this is a route loader, you know, like this is, you know, we already do this.

And then basically like look, there's no waterfalls here from a from a from a data fetching standpoint.

But I mean, from a UI standpoint, there are like if you were streaming, uh, you you you you're not getting what you want out of it.

This is you you you are naturally going to go this direction right like and this is what I'm getting at React the the confusion was people

wanted to put fetch user directly in use right you want to put await fetch user in derived Yes.

Now, the height isn't determined.

Sorry. Which feels even though the collective behind the scenes the API service feels correct.

Yes, we we basically turned our app into a promise all and you are Rob, you made my point. Yes,

this is exactly what I'm getting at.

Like you we have the natural tendency in our imperative thinking to turn things into promise all.

So React doesn't let you do this very easily because you need a caching solution components rerun. It's it's

it's kind like a saving grace that the system completely explodes if you try and do this. It's not convenient, but it's it's kind of like a saving grace.

But when you have a reactive system that's actually reactive and can update this stuff and can be fine grain, you you just almost you just gravitate towards doing it this way.

you know the right solution. You know

the right solution is pass the promise through all the components go through all the the types and check if the differences are and push them to the leaves. I I was arguing that people

leaves. I I was arguing that people probably wouldn't move it into event handlers. I good luck moving them into

handlers. I good luck moving them into component proctoring patterns or whatnot. And the funny thing is, okay,

whatnot. And the funny thing is, okay, you said yourself, how often are you moving from sync to async, but even think of the process of new development, what people are going to do while

they're developing new features. Maybe

it was just a user page and then maybe over time you added user sections and user and split it out and started these things got bigger and started adding

maybe nested fetching or just like they they started naturally expanding out under their own weight as tiers come in and increase.

You everyone could picture this.

you start here.

I mean, I don't even know how anyone can make the like I know there's no science to developer

experience, but like this seems very obvious to me.

So the whole question is what if you could write this and have it behave like what we did before with all the uses.

Actually behave even better. Pretend the

uses are in every single reactive expression.

Pretend the awaits are pushed down.

Pretend that in between here if you decide to make a full name like think about the what if somewhere in here you needed to do something like make a full name. you'd have to consume with the

name. you'd have to consume with the use. If you didn't want to consume with

use. If you didn't want to consume with the use, you'd have to go like promise then user name to full name. You'd have

to compose the promises if you didn't want to use high, right? Like I don't know why you'd want to do that in this case, but what if you want both of these to get user full name and you like it

was expensive calculation, not something you want to repeat in multiple places.

If you wanted to do it at this point in the tree where you're holding promises, you either have to block here now or you

need to actually like make promise changes on derivation.

Like you know what I mean? Like how do you deal with it? You're like, "Okay, well user then you u do uppercase." My my examples are dumb. But

uppercase." My my examples are dumb. But

my point is that you're not if you're not dealing with user you don't get to just go like that. I mean you you could make more you

that. I mean you you could make more you know you can make more async drives right but if those drives are blocking

like if if the pure presence of a weight causes the behavior like is the use how do you do like then you shouldn't be

awaiting you should be like if the compiler is looking for a wait and you don't want a weight behavior then you can't use a wait then you're probably going to use it then do you know what I mean

It's it was like what I was talking about earlier when I was trying to figure out how to to write the example uh in the Excal where I was like I I don't want to await here. I want to

await here. I I I want to pass the

await here. I I I want to pass the promise here. But what if I actually

promise here. But what if I actually have to drive something from the promise before the point that I want to await it and I want to await those in two different locations? Well, then you you

different locations? Well, then you you basically promise chain without using a wait right?

Well, it works like promise all in a system where the consumption or the blocking or like the like the trigger of saying like where is my suspense

boundary or whatever happens where the await is or where the use is. I I like The suspense has to be above that. You

know what I mean? Like that's why it's like promise all. Again,

in this phase, I probably would have started with either drilling down user ID or adding it to context.

Yeah, I mean adding the context is helps in a sense, but like what I'm getting at here is like it removes the proper linking but doesn't remove like completely remove the structural thing.

At some point like you could, you know, just make context for little clusters of like three or four components, but other points you're just like look this is a small tight area and it grows over time.

Maybe it was one component, right? like

uh sorry where I want to get back to my example here.

The truth is you probably when this was all the same page you probably did this not even derived used the what what I'm trying to get at here

is if if I made this example in solid 2.0 And I wanted to do the use the name here.

Me simply doing something like uh upper name or whatever upper name equals create memo. First of all,

there's no await here. If I just go user dot name to uppercase not blocking

this is not blocking it's blocking where upper name gets used somewhere else down in the DOM.

It's literally by design optimal.

This this is this is what I was trying to show in in in this in this thing. See

the difference here? One and two happen here solid. Two and three happen here.

here solid. Two and three happen here.

Right?

And by almost enforcing it this way where there is no separation between like one and two

can't go together by design. I've I like I like you want to separate one and two as far as you can in the hierarchy

but they don't go together by design.

These ones give you the you have the option to separate them. But that that option takes work.

Whereas in a colorless system, two and three are tied together by design. Which means that one and two

design. Which means that one and two can't go together by design. Which means

that like essentially you go in and you do the most straightforward thing and that is exactly the optimal solution. To

me that is DX.

I I know like people like arguing the DX case, but like I mean would you trade that for split effects for something like effects you wouldn't

even use? Hopefully like

even use? Hopefully like yeah waiting inside the component seems too restrictive to me. So wait of course the whole point of this is that components can manage their own data and more realistically inner would be responsible for creating it own promises but you can do it either way. We're not

it's yeah waiting inside component seems too restrictive to me. I just think of how people tend to model their data in one place. While we try to push them

one place. While we try to push them into some means of collocation and it makes sense to it isn't something I can make a hard constraint. So, and so composition has to flow.

I consider it much less constrictive since you get to choose where the waiting happens and it's nice explicit.

Yeah. But it

if a weight always means blocking, do you know what I mean? Like in a sense, have we we overloaded the term await? If

we make await mean use, have we actually constricted the language? Right? Like

have we actually made Have we actually specialized? Is

actually await now a subset of what it was originally instead of a superset?

Like are we actually limiting the language in a way that gives us less capability? Because await I mean await

capability? Because await I mean await always meant blocking in JavaScript don't get me wrong but in our case awaiting because we can wrap stuff in wrappers. Awaiting doesn't mean blocking

wrappers. Awaiting doesn't mean blocking we because we don't hoist it. Awaiting

just means it's awaiting a promise. It

doesn't mean blocking the render flow.

So if we if we equate a weight with with blocking the comp component or render flow, then we're basically actually producing something more restrictive than something that's like

more expansive.

The spice must flow.

Yeah, don't get me wrong. There there's

a couple trade-offs that come with come with colorless async. um mostly around initial load scenarios um which we've talked about before but generally and actually it mostly comes out with

interaction from outside the system.

That's a better way of of putting it because I I mean we've actually talked about it today. There's there's there's this

today. There's there's there's this physics that the trade-offs are what where we started the stream from this whole this physics but the thing is

these trade-offs should exist anyway. Do

do you know what I mean? like aspects of it.

The more concrete trade-offs is is like if it's colorless, you might not see it.

So like creating the affordances might not be as as obvious, which is something that like you you have to get in the pattern of. But the funny thing is when

pattern of. But the funny thing is when you're building UIs, you're already creating affordances. That's literally

creating affordances. That's literally what your job is, right? You're like

someone's going to be like, "Oh, I need a loading state here." it this this emerges from design rather than needing to emerge from technical programming constraints.

I as I said I have a very different view of what DX is from from I perhaps because I it's not about like how easy it is to type or like how many less

characters you you type. It's it's about aligning correctness or like not even correctness even optimal model with what you write.

I want when you write some code, I want it to be the most performant code. I

don't want that to be a question. I

don't want it to be like, oh, well, you can do this optimally by doing this. No,

it's like literally the only way you can write it is the best way to write it.

Like that's developer experience to me.

If it if if it meant even typing twice as many characters, that is still developer experience.

I mean, okay, I I technically speaking, I it's not in my graph. You can always box value this. We could pass the

promise around.

It's not easy because we absorb promises naturally here. This is one of the

naturally here. This is one of the debates I had when I was working on solid 2.0. The fact that create memo can

solid 2.0. The fact that create memo can just absorb it was like a debate because when it was create async it was easier to do it the other way cuz like it is possible to pull the fetch out or like

store it in a a memo kind like do this like what spelt is doing here um and then only like absorb it in the create async lower down but it's not even

absorbing it. I it felt really pointless

absorbing it. I it felt really pointless because the switch from memo of promise to create async of value had no meaning

in solid because it would did not represent actual consumption and it didn't or the read. So it's like we just like two-step creation for no particular

reason. Um, of course, as I said, the

reason. Um, of course, as I said, the promises can come from outside the system and you can absorb them into memos in multiple locations or whatever.

Like you you creation doesn't have to happen inside the memo per se. But um

the benefit of it happening in this kind of directive flow is like this is this is why I like modeling uh async is state graph because you there's a tie between

this and from props user ID. It goes all the way through the async. It's it's why React has changed their their model for async and why everyone's kind of flip like don't use affect the fetch because

that breaks the chain. So

technically yes if you want to do extra stuff for no reason.

Yes.

I don't know if I made this clear enough, but like the difference between one and two and three separate versus one and two, one and then two and three separate, but it it has profound impact

when you your temptation is to actually always write it this way anyways even in those colloccated cases. Sure, it won't make as big of an impact. You can be like this is not that big of a deal.

Like let's be fair, you you're blocking up X here. So technically speaking, you don't necessarily have to block propagation through graph. was really

cool with solids approach was that I think I've shown this demo the stack blitz demo uh several times now but let's let's pull it up here um again uh

the nested component example right nested fetching example uh and rich remade this with spelt to actually prove the point here naturally when spelt first five came out they couldn't do

this easily because they they had to like decouple a couple things because of the way they did it but like This was just automatic assault. The idea is each component like A renders B, B renders C,

and each one fetches its own thing in 3 seconds. So in theory, if this was at

seconds. So in theory, if this was at the consumption point, like if this was the await in in these examples, like if we were blocking here, then this whole

thing would take 9 seconds to load, not one, two, three, right? So like

the the whole thing is under a single loading boundary. So like it doesn't

loading boundary. So like it doesn't matter. We don't have the ripple down

matter. We don't have the ripple down effect. And because it fetch in parallel

effect. And because it fetch in parallel doesn't really matter. It's loading as it's coming in as slow as the slowest one in this case in terms of the boundary. But my my my point is that

boundary. But my my my point is that like this is just a natural outflowing of the thing. It doesn't require any special

thing. It doesn't require any special compiler consideration any kind of thing. It's literally just how the

thing. It's literally just how the system works because um this isn't the consumption point. The

consumption point is inside here. So we

can render B without being blocked by A.

And I said other there are other ways around solving this problem because the whole detection consumption only really matters probably on boundary locations.

But it does make as I've shown in previous demos boundaries really really permissive. We can just move them around

permissive. We can just move them around or whatever because like this aspect is you don't have to worry about where consumption happens. You

don't need to inject those uses.

It's just it just it's just a result of the system.

So making a point you should assume everything can be as additional loaders around everything. See, and and and the

around everything. See, and and and the the thing is this is the the result of why people are skeptical about the DX on this, right?

Because they're like, "Oh, well, now I have, you know, everything." The thing is you you get this naturally falls out of responsibility.

Would would your component give affordances to show async? If it

does, like if if you if you make a button and it h and it should have a spinner as part of its design, then you're responsible for show showing those affordances. You would have been

those affordances. You would have been doing that anyways.

If it doesn't, then that's not on you.

Yeah.

More like try the after loader. Yeah.

Component library. Do if I go look at Cobalt or look at one of these component libraries like you know pull it up are they providing loading affordances in their components?

If they are then this affects them. If

they're not then this doesn't affect them. Someone else should be blocking

them. Someone else should be blocking that. Like if if

that. Like if if like if if if it stops being it's not about handling

async, it's about UI affordances.

Think about it. If something's loading, you can't click on it.

It it's not necessarily the responsibility of the of the button in that case.

It's the responsibility of who whoever is loading the data.

or like like in terms of like grouping this. The

thing is once you get past that initial state, everything flows naturally anyways.

That's not that's not really a problem.

As long as you don't do stuff, you know, like read after writes in your events, you know, like that kind of stuff. Like

as long as you you structure stuff that follows the rules that we've been putting into the warnings, then you're fine. I I I think people worry about

fine. I I I think people worry about this way too much because they they want to poke a hole in it. Because you're

right, if you try, you can find examples that can poke a hole. Definitely. But

the the the real question is you're you you shouldn't be responsible for anything more than you already were responsible for.

How do I know the component supports async in such way with color, dude?

it. Okay.

You never used color in in Solid 1.0.

You never used color anyways. Did you

guys Did do Did Did your components accept promises in solid 1.0?

They they I I'm assuming they didn't like I'm I'm thinking that they might have done something like like if this isn't provided like if I don't have a

value here show a fall back and you would still do that. You're like

if I don't have a value here show a fall back. But you weren't passing promises

back. But you weren't passing promises around before. So why would that change

around before. So why would that change now?

I like I I think it I don't think the math has really changed here.

I I I I I I realize this is the thing where everyone gets like really hung up on this because they're like, "Oh, if anything could be async, then it could be async. And how do you do it?" Now

be async. And how do you do it?" Now

there are places where async reads could break like top level of a component then you I mean like it's kind of it's becomes kind of awkward because then you're rerendering the component you

know there's no thing but as I said if we if you follow some specific rules in terms of how to guard reads the same as our you know like as I said now we're a

little bit stricter on reads and warnings the rest of the system just falls out of Well, I mean people because it suggests that it can take an async value. I'm

kind of arguing that it Yeah, I'm kind of arguing that it doesn't it doesn't matter.

Yeah. Solid was always this way. Yeah.

Yeah. So, like

I I mean, don't get me wrong, this might be like famous last words kind of thing and there's going to be like big pie in the face moment, but my suspicion is those pie in the face moments are going

to be people trying to break the system rather than trying to actually um follow the patterns. And I think that the challenge here is that there are

some pattern differences. So like you do have to be a little stricter. Um and I'm hoping that the warnings and the setup

around the errors can make that happen.

Yeah. Value or null. Yes.

This the the one gap and this is it on the initial loading.

If you if you read a value in an event that is not used anywhere in the DOM, it is possible that an async error can be thrown.

So as in it because if it's read in the DOM it'll be caught by it'll be caught by uh loading boundary. So if it's above a

loading boundary. So if it's above a loading boundary or like not read in the DOM, it is there's there is a small window at the

beginning of of of on the very first initial load of the page that you could read something that throws and in the past that would be null. But since we were not allowing nullable values that

will throw. This is basically the only

will throw. This is basically the only gap in here.

And the the reason this gap is concerning is because it's not you have to hit it to to hit it. Like it like

it. Like it like you might not realize it until you know in theory someone went to production and they clicked the thing really fast um

during the initial page load um before the rest of the content loaded in.

Afterwards, anything above will be caught likely in a transition. But there

is this like there is this window this this window on initial load where it is possible if something isn't used.

To be fair, if you weren't null chucking checking the value in your event already, you would have this exact same problem,

right? If if it was user and you didn't

right? If if it was user and you didn't check if that user was null, you'd have you know can't access name of undefined.

So in a sense we can't guard you from that. What how would you have solved

that. What how would you have solved that in the null case?

you would have null checked, which nulling everywhere is is also not great.

It's one of the the stinks of of of representing async as like as being nullable. This is something that I talk

nullable. This is something that I talk about a bit in the article.

The better fix you would have done is disa disabled the button if if the value wasn't present.

Note the funny thing about disabling the button is it puts an attribute on a DOM element which puts it in the DOM which means it gets captured by the loading boundary.

Have you thought about making all signals within the scope of ownership of the component be registered with loading boundary?

You're blocking again. That's the spelt problem, right? The

problem, right? The how and or it's the dependency extraction problem. How am I supposed to

extraction problem. How am I supposed to how am I supposed to look at the event handler? What if that event handler gets

handler? What if that event handler gets passed in from a parent?

Yes. Yes. It's stale in flight.

Yeah, which is actually consistent. It's you

they they interact with what they're seeing.

Yeah. We Yeah, sure. You can we can create an explicit uh depths API for for uh for callbacks.

if you if you really wanted to.

I I don't think that's really foolproof though because I I think what where it gets really more interesting for a component author is that the parent not only

renders you and might be passing you async data. They're also the one

async data. They're also the one providing the like onclick call back. So

you and your local scope can't even see it. So that doesn't solve the problem.

it. So that doesn't solve the problem.

This this this doesn't really solve the problem. they at the parent scope could

problem. they at the parent scope could make that call. But if they at the parent scope are making that call, then they could also, you know,

pass a disabled to your button because you expose a ready not ready condition.

You your button has a disabled prop.

Like if you weren't handling the affordance anyways, you probably, you know, if you were handling it, you probably exposed a way of triggering it.

And if you weren't handling it, they they're responsible. Like nothing has

they're responsible. Like nothing has changed here.

TypeScript made null checking common.

And it's also nulling is one of the most painful thing to do with signals too, right? Like because the function calls

right? Like because the function calls are item potent. So

like it's kind of it's kind of awkward because every time you call it like you're like this is definitely a value and then the next call like it's like I don't know that. And it's like, no, I

just freaking we know it's a value.

I think if you click anywhere on the page before it's loaded, you deserve the error. I mean

error. I mean a a little a little I I I I think if you build well designed APIs this stuff will flow out of the

language of like the affordances you built into your AI UIs. I understand how this stuff can be missed but we're talking about like the edge of the

corner of the corner of the corner and mechanically speaking this enforces that you do the right thing. I I I I I'm

hoping this makes sense ourselves. I I I get the push back a bit, but like I really think we're on to something here. Like

here. Like this is this is this is I don't know.

This is really powerful stuff. We we've

kind of taken these physics, these these rules that are true and reimagined them through a kind of place where like we've actually pushed the

a lot of the harsh realities to places where you would expect to deal with them already anyways. And what we've done is kept the

anyways. And what we've done is kept the inside kept your graph kept your experience the way you would hopefully

expect to to to see it. Um, I I I it's it's why I still love this not this one, sorry. Why I still love this optimistic

sorry. Why I still love this optimistic data example because the difference between

the synchronous app here where you just show your to-dos, do all the stuff. There's no promises in here. I can't even see any async in

here. I can't even see any async in here. I just wrote a to-do app that

here. I just wrote a to-do app that works and I've managed to put all the actions, all the optimistic updates, all the

all the I thought I thought I fixed this type issue.

This an old Yeah, it's probably an older version. Doesn't matter. um

version. Doesn't matter. um

we pushed all that into the data layer essentially, right?

That's an option. We don't have to push it all in there. We can break it up, modulize it how we need, but the the key part is that

the the act of building the UI of describing what you want on the screen.

For me, that's always been, you know, the the uh maybe it's cuz I have a hard time with like CSS or whatever. Like this is the part that I've always wanted to be

able to model easier, you know? I mean,

the data modeling is straightforward, too. It's very powerful here. But I what

too. It's very powerful here. But I what I'm getting at is we've kind of isolated the async from the UI design.

Like if you need an affordance, it's not you're not asking about async.

You're not like, "Oh, what's the timing of this?" You're not you're not going,

of this?" You're not you're not going, "Oh, am I am I like is there this race condition?

Do I care when I set loading and don't set loading? Do I need to cancel it with

set loading? Do I need to cancel it with an abort signal?"

that that is not what you're doing. What

you're doing is you're like, "Okay, well, this is basically the same app as I had before, but now I need to consider if I oh, if I'm if something is pending,

then I should show it like this. If

there's an error, maybe I should give a retry button."

retry button." Um, okay. Or if it's pending, maybe I

Um, okay. Or if it's pending, maybe I should show this. Okay. Okay, cool. like

we've kind of isolated time from the equation. We haven't isolated the need

equation. We haven't isolated the need for establishing affordances for when things are available or not available.

We've actually strengthened that. We've

we've we've given it like like you ways to query like is it pending, is it not?

you know, we've given you ways to to look at um you know, time as flattened onto your UI plane, so to speak. We've

we've kind of collapsed that dimension in a in a in a you know, queryable way, but there's nothing nothing here is like

I'm worrying about race conditions.

It's literally like just I have some data. It's either errored or in flight

data. It's either errored or in flight or like pending or whatever. and just

show the thing that I want to show.

Everything else takes care of itself.

Dude, you want something? In the future, we're going to wonder how we ever lived without this. Yeah, we'll see. Maybe

without this. Yeah, we'll see. Maybe

it's Maybe I'm Maybe this is too late.

Maybe AI will just have do everything and no one will even care about this kind of stuff.

Okay. Well, there's a couple mechanical things I I spent longer on this than I expected to, but there there was a couple more mechanical things that I actually want on the show, but we're actually already at like 5 hours, which is kind of unfortunate

because I I I actually wanted to I mean, I don't have that much this week in JavaScript to be fair. I don't care about Versell versus Cloudfare. Honestly, most

versus Cloudfare. Honestly, most developer news just doesn't interest me even remotely these days. No one's

talking about actual stuff and approaches to building things. They're

all just saying like AI blah blah blah blah blah blah, you stole this from me, blah blah blah. Like

really just like drama.

I can't hear.

No, what I what I want to talk about a bit here is uh I I want to pull up the repo and I want to I want to I want to show an example here uh because I think

it'll help not solj because I I want to get into some more uh mechanics here and I think it will be

interesting to do. So these should be fixed now. Um, but

fixed now. Um, but I've showed this on stream, but I think this example that was made by uh uh

Missoulu uh is actually really relevant.

It's called the double like a lot of these were bugs that I fixed, but there is one of the ones that was actually not a bug and I was like this is not obvious and we should talk

about it. Um,

about it. Um, is it this one?

Oh, yeah. Beautiful.

All right, let's let's let's let's dig into this one for a second.

Uh or it's broken.

Lovely. Okay, that's fine. Um I I can demo this in a different place.

Yeah, let's let's demo this in a different place. What's the best way to

different place. What's the best way to demo this? Yeah. Okay.

demo this? Yeah. Okay.

Okay. Let me take my my multiply divide example because I I I want I want I think this is really important to understand about the model

and I I want to let's use my divide example. Yeah, let's do this.

example. Yeah, let's do this.

Okay, I think some people have seen this before. You click, you go

before. You click, you go and you can click it multiple times. It only

settles once. These are all separate async reads, but they all get entangled and you get the smooth thing. And the

the key for why this example is so cool is I literally started an example with no promise here and it just is a bunch of memos and then I just decide to make

the it async and I essentially I don't have to worry about null checks like a is actually an accessor number so

on n is always going to be held where I want it to in the past arguably here I'm actually purposely tearing so like 12 gets ahead of 12 because I use latest

end. But let let's do this. Let's remove

end. But let let's do this. Let's remove

the latest for a second. And I want to show show you all something.

See, if I if I if I if I do that, it's not going to move. And this is the default behavior. It'll stay on the

default behavior. It'll stay on the number until it's consistent. Now what

what Mazulu did in their example was they move the button outside of the loading boundary.

And I I think this is important to understand because so far this is the same and I click it like 10 times. But one thing that I'm

doing here, if you've noticed, is I'm actually passing a setter function. So

I'm I'm incrementing it by n plus one, which means it's actually getting the latest value. Incidentally, that's just

latest value. Incidentally, that's just how we work. If I changed n to actually read things, so it reads the stale value, right? So it's actually the

value, right? So it's actually the reactor read. It's not like applying a

reactor read. It's not like applying a callback function on its previous value.

You'll see if I click it multiple times, it can only go once. So

I I click it three times, but it only goes up once. This makes sense because it sees the same stale value and it can only go one. So if it's on two, it's only going to see three. And it tries to click it again, it's going to see three,

it's going to see three. This this makes sense, right? You you if this was latest

sense, right? You you if this was latest end, then then it would be the same as the callback form. But essentially

now if I make this this timeout longer let's say like not random. If I actually make it actual 500 milliseconds

for each one.

Let's make it even longer. Make it a th00and 1 second.

You see as I'm clicking here, it stays on two even though I click it like a bunch of times, right? But the the what and this should make sense to people,

right? Okay,

right? Okay, we're loading and then we show all the state consistently. Like obviously it's

state consistently. Like obviously it's a nice affordance to get latest but but the interesting question is what do you think happens if I click the

button while the page is loading like a bunch of times? Does any anyone want to guess what happens in this example?

Should it behave any differently?

So here we know.

But my question is while it's loading right now and I click it a bunch of times, what do you think is going to happen?

Chad, I am going to wait for you guys to respond because I don't want to ruin it.

It'll Okay, Robbie says it'll go up faster. Why will it go up faster,

faster. Why will it go up faster, Robbie?

It will go up and I know. Yeah. So, is

it the people who know the answer are the only ones responding? That's fair

enough.

It's not about replaying events. The

page is h This is client side hydrated or whatever. Everything will crash.

or whatever. Everything will crash.

No. Are you guys ready for me to do it?

I'll give it a moment longer to to guess if you want, but let's let's let's do it.

All right. Last chance.

All right. I'll do it now.

It went up to 11. In fact, as I kept on clicking here, I could actually hold off the the loading going away. Cut to 30.

Why is it like this?

It It updates right away. It doesn't

hold. See, here we're holding and then it updates.

Isn't that weird?

There's There There's actually a really good explanation for this, but I because AI saves consistent. Yeah,

there's nothing to contradict it. The

back end will handle it. No, it's

it so so secret little goblins counts the number of clicks during hydration. No,

this isn't hydration. This is completely client side. Um

client side. Um the app is fully hydrated by the time like the the like there's no hydration.

the the the reason that this happens is because there's nothing to contradict it.

We only need to show we only need to hold the the the count because there's something to contradict it because we need to be able to show that 10 divided

by two equals 5.

N itself is not async. it gets held up because you can't update the number while showing a otherwise you'll get

tearing but when the it's loading like there's nothing to tear essentially so it can just process it immediately

right there there's there's no there's no dot dot dot on this either when I'm clicking on it it's not pending while while I'm clicking on now it's pending but there's no there's no pending while I'm clicking on it right

and it defers loading because it does load it a number of times. It cancels

the previous ones. You know, we have built-in promise cancellation essentially but but um

that's basically the gist of it. Now,

obviously, it's weird that I click this five times and it only goes up once. And

here, I click it like 10 times and it goes up faster. So, arguably the behavior you want isn't n plus one. It's

it's latest n or you know, simply this.

As soon as I change it back to this, then you get the five right away. And

when I click here, you know, you get the six right away. Like, so now it's consistent. And when I click it a bunch

consistent. And when I click it a bunch of times, I still get the the number of clicks aren't lost. And if I go back to this being latest,

so you want to show the updates right away. There's no inconsistency between

away. There's no inconsistency between this and this because that's the importance you want to do.

That feels much smoother. obviously,

but I did actually have to make some considerations here, right? Cuz the

default, but like what I'm getting at is I made this decision based on like like a local

decision. I decided that I my affordance

decision. I decided that I my affordance is like I could with the button increasing faster, I could choose not to show the is pending. Like my affordance could be just the fact that this

updates. That could be my decision.

updates. That could be my decision.

But what I'm getting at here is that like it is important to understand that loading boundary is a boundary that

guards if the async read from ABC here doesn't escape the loading boundary on initial load which means that

N is not pending or like and can update right away.

Yeah, this makes sense from a consistent way of verging on being counterintuitive. Yeah, and to be fair,

counterintuitive. Yeah, and to be fair, this is how React works too.

Um I think this probably spelt works too, I imagine too.

I'm not sure. Yeah, I'm I imagine.

I mean, I h I've already been doing demos that were closer like the to-do MVC type stuff where you're managing a list. This

demo is is not going to I I don't think real world case is going to actually help explain this demo

anymore. This like this is another one

anymore. This like this is another one of those ones where what are you doing jamming the button while the page is loading?

if you know what I mean.

It's it I I this is the this is the f the funniest I have to test and make small examples to show edge cases because in the real world you

just don't tend to hit like you will on occasion hit these edge cases which is why we have to account for them but like we're not setting ourselves up to try and hit the edge cases you know what I

mean I I have to account for them so that like when your app scales when you get to a point or you hit these things that they're handled properly. And this

is why I'm very thankful to the beta testers because the type of people who hang around the solid discord are exactly the type of people who want to break everything and poke holes in everything. Um they want to create crazy

everything. Um they want to create crazy demos so that really show off like the capabilities and they also um

want to show their cleverness. So like I get great great examples of people trying to break stuff. So

break stuff. So yeah, I mean what what what's what's a what's a real example? I just said something like

example? I just said something like to-do MVC with affordances is very similar to like like a Trello board conceptually. Um which could be a real

conceptually. Um which could be a real use case. A lot of times the funny thing

use case. A lot of times the funny thing is these little cases that we're focusing so hard on in making these demos are like so on the edge of the

thing. What I the real win is just being

thing. What I the real win is just being able to write the code like normal and not have to worry about these edge cases.

Uh like let let me see uh give me a second here. I'm going to I'm going to

second here. I'm going to I'm going to open Discord in my other window for a second and see if I can pull out an some examples that the community have been making using Solid 2.0. I think uh I

think Gabriel's still here.

I think we just everything stays the same as mind-blowing. Yeah, the the two NBC examples is really great. What I

wanted to actually grab was that Gab Gabrielle had an example uh that was like a chat app that was built on on

this and I think it's in a working state. I I need to see if I can find it.

state. I I need to see if I can find it.

Is it the sync engine chat?

Yeah, let me see.

Yeah, you guys can't see it. Yeah,

sorry.

It's all good.

Hopefully, this demo is working. I might

have grabbed a bugged version of it.

I love I I I love I love this example. What what's this example?

example. What what's this example?

Format temp world zone. So what are we doing here?

Chat app create projection which is an async iterator querying messages push store create optimistic store.

I don't I I don't have enough context probably to to to look at the implementation completely in here. Um

chat pane. What's in here? Badge, scroll

behavior, message list, message bubble.

I just love that. Like most of these look like they're just dumb dumb UI components. Do you know what I mean?

components. Do you know what I mean?

like they're just doing stuff like synchronous. Nothing too fancy. Props

synchronous. Nothing too fancy. Props

children. There's a wrapper. Yeah. Okay.

So, almost all the logic this is some special scroll behavior.

Almost all the special logic here is is a for loop which is keyed false. So,

it's by index. Wonder if repeat would be good there. It doesn't really matter. Um

good there. It doesn't really matter. Um

this probably this might not even be the latest version all the all the logic is basically the chat app component right so it's basically we create a projection which

is an async iterator and then it just gets the messages and yields off and then the optimistic store mechanism

messages see how does that where are we setting our optimistic messages is we have an action that sends the messages, sets them optimistically,

pushes them on an array and then it waits on the API to send the messages and then it looks for the message ID.

Yeah, I get it. So basically when it gets an act from the server like it gets the message back it knows that it's done its action and I hear that some things like convex automatically like hold your

request till they know you've received it on the client. But this this is cool.

So this this is basically a fully streaming chat example that's just using async iterator protocol. Like it's fun like there's no imports here, right?

like this is literally like just built purely using our primitives um to basically have two chat apps. They work

both ways. So I go hello Yeah.

What's up?

Yeah, I mean I did a bunch of fixes since last time.

So now we can actually have the streaming async iterators work and they they have multiple modes which is really cool. Um for hydration you can you can

cool. Um for hydration you can you can either choose to do the default where it just streams from the server all the way through the hydration or you can do hybrid where it streams the first promise from the server and then picks

it up from the client. I mean I actually got a demo I could probably show off here to that effect.

Why is this still here? Um,

the weird part is did I close one of my windows? Feel like I accidentally closed

windows? Feel like I accidentally closed like where? Yeah.

like where? Yeah.

Oh, it's cuz it's full screen. It's

fine. Um,

uh, I'll just copy paste this into chat in case if people want to check it out.

I don't know how presentable it is. I

know we've been working in bug fixing throughout this whole demo. So, you

know, but what I wanted to actually look at was um uh quickly look at a couple of like silly

little demos. Incremental SSR

little demos. Incremental SSR incremental iterators.

I I made this example on stream last time and it didn't work. Remember? um

where it it pushes um into a list and this is actually kind of a a cool API just on a side because what

I did was the projection is a stream right that pushes values on. So, it's

actually incrementally. It's not sending the whole list over the wire each time.

It's literally just adding an item to the end from the server um at once a second and then the client just appends the the item on the end. So, we're not actually sending the full list. We're

actually doing incremental pushes from the server during initial SSR. There's no additional requests or anything. If

and and what I did to actually prove this fact is I put is server. See,

Stacklitz has this funny uh it's not I guess not funny, but Stacklitz uh will show you server and client console logs in the console. That's how they forward them through. So, I actually had to like

them through. So, I actually had to like prove that see chunk true, it's actually running on the server these these chunks coming in. Um and what we're actually

coming in. Um and what we're actually doing um if I look at the uh maybe I can put this in a different tab.

Sometimes I have problems with stack blitz from security standpoint.

Um, oh, it looks like my computer is low on battery even though it's charging. It's

charging slowly.

Cursor is killing it. Okay, let's let's kill cursor for a second. Sorry. Maybe

that'll help it recover. I was trying to build a signals library from scratch using solids tests. I wanted to actually see if

if I could uh do the V-neck thing against myself. Um, we can worry about

against myself. Um, we can worry about that on a on a different stream.

So, um hopefully that that'll we can our computer could start charting. I'm only

at 7% left, so that's kind of bad. Let's

quit.

Why is Chrome being weird?

Oh, there it is. Okay.

Okay.

So, it's still telling me that Chris is using a lot of I think cursor is done now. Do we Is it still that sitting there in the

background? Okay. Anyways, uh

background? Okay. Anyways, uh

let's bring this back cuz Okay. So, but

one thing that we can do that's kind of cool here is instead of doing this, we can do we can change the SSR source to be client. Let's hope this works in this

be client. Let's hope this works in this version. But if I change it to be client

version. But if I change it to be client now, same in demo. And what you're going to see is false. Now it's the client side making the connection. There is one difference though. There's no loading

difference though. There's no loading boundary because it never suspended. It

literally just picked it up on the client and made the request on the client. So I mean this is good for like

client. So I mean this is good for like tapping into async local storage or so like like async storage like local storage type stuff, but it's probably

not like typical for this use case. But

the the real fun one is hybrid because with hybrid if this works is it should be true for the first one and then it should be false. Okay. And I

have a hydration error in this example.

Hopefully I've fixed that now. But see

how it said true and then false uh and then picks up the stream. So it actually serializes the first value from the server and then continues the subscription from the client. Um, and

this is all just a matter of of choosing what your your sources for your your data fetching.

Um, and make font bigger. Uh,

the font's actually already kind of blown up. What do we add here? 125%.

blown up. What do we add here? 125%.

Usually I have a hard time reading my screen if I get any bigger than this because the code doesn't fit.

Um anyway, just kind of showing some of the the stuff that we've been doing with uh the async boundary

stuff. Okay, so um there is

stuff. Okay, so um there is how was I skipping? That was a fun part because you have to understand it's doing incremental updates. So I actually had to I had to eat because if it was yielding

a value that would be easy but if you look at it's not actually yielding a value it's actually mutating it. So I

actually have to eat the uh the the the proxy has to actually eat the updates on the first iteration.

So it takes the server serialized state and then replays the first one. But then

like basically when you push or do any mutation, it just basically eats it. Um

it it it it gives you an object that is mutable and you can read and is self- refferencing and all that kind of stuff, but it doesn't actually apply it to the

underlying draft.

It doesn't. I mean, there's not much you can do with the async uh iterators.

There's not much in their protocol.

You're you're going to error out and you're going to get an error boundary and you're going to do what you need to do.

Yes, we we can't skip it. Yeah. So,

technically, yeah. So if there's a log next to push, you'd still see the first value repeat.

Yes. Yes. Exactly. Yeah. There's we

can't stop the first thing from happening. But this was a good example

happening. But this was a good example because it was a push. Um if it was a yield, this would be really easy, right?

You just skip the results. But because

it's mutable, um yes, it does run on the client, but it's kind of like the way create async runs on the client. uh like

or not create async but like for promises we also run in the client and we kind of like dummy out the promise so that we don't refetch because we have to collect the dependencies. So it's a

similar trick basically that during hydration the the we sort of we we have to run the code but then we kind of patch it so it doesn't do the the the

thing we don't want it to do. In the

case of async iterators, I can't promise that it's not going to run the promise like normal data fetching, but I I I

think but generally that's that's the kind of tact I've taken here.

That's so funny. It's still showing cursor using significant energy even though cursor is not opened.

Anyway, it's fine.

Okay. uh what I wanted to talk about next related to this stuff. Um yeah, so we I think the main one there was is is kind of what I was showing before which

was like this idea that if you have a if you have a graph, right, and you have uh let's make it screen,

write something on it. So here's your like signal, right?

And then let's make this red.

And then we have something like async derived from it.

Uh how does this show this? Yeah.

white.

And then let's put blue, which will be our effect.

Like if you have this kind of chain where the where the loading boundary happens the the I'm trying like I'm trying to think of the best way to show this but

essentially we don't cons let me delete we don't consider things having

I'm going to I'm going to draw something up here or use a word. I'm going to write transition. Okay. And transition

write transition. Okay. And transition

is going to be brown. I guess it's going to be like a have any more shapes of a diamond.

Yeah. I don't know.

Bring to front.

I don't know if my my diagrams here are going to be very useful here, but conceptually

the way this flows down is when we when we hit our async update or async signal at that point until we hit something async there, no

transition exists. We just kind of

transition exists. We just kind of collect the nodes in in in a global queue. And then when we hit something

queue. And then when we hit something async, we we go, okay, create a transition dot dot dot this. Let's make this a

little bit get you. We're like, create a transition. But the transition doesn't

transition. But the transition doesn't do anything concrete.

And then when we finally hit our render effect and it holds at that point it goes it it

starts bubbling up its owner graph. So

this is a dependency graph here. Okay.

So um dependency graph is white. Let's say

then the it it's it looks up um a different graph. It looks up its owner.

different graph. It looks up its owner.

So let's go here.

Let's use blue. So, it looks it looks up for its owner. And in in our case here, like these might be the same owner. They

might be a different owner. Uh we're

going to make this trans these can be where these owners don't matter, but it walks up its ownership

graph and it goes, "Hey, I'm async."

And if if nothing gets in its way, it'll get to the transition and the transition will go like okay what like why did you error? You errored

because of async. We actually

communicate the node along here. So then

this async node becomes registered with the transition and we know how to to wait for it. However, if

if on the way up it hits a wall and by wall I mean like loading boundary.

That communication never gets up here and this loading boundary goes haha. I

will hold on to this async. Um,

yeah. So, let's get loading. You'll be

there. You Yeah, sorry. The green arrow is going to be. So, this then goes to here in D. Yeah, this my arrow drawing is

in D. Yeah, this my arrow drawing is terrible because like essentially if if it hits

the wall here instead this goes to here and it never makes it to here.

And that that that's like mechanically the core of the of the of the transition mechanism. Um,

mechanism. Um, and the key part is loading um, only happens initially generally. I

actually added a new prop that if you want to trigger loading to to start again from above, you can. The biggest

problem with with with with suspenses, if you have some random async down below, it'll just keep on unmounting on you. But, um, one thing that I that

you. But, um, one thing that I that occurred to me is that sometimes you actually might want to isolate the change. Yeah,

that's that's actually what I wanted to do. Do we have the divide example

do. Do we have the divide example anymore? Um,

anymore? Um, I think I undid all the changes in it.

Let me go back to it.

So, do we Let's undo all the changes in here.

Whatever. Save. Let's go back in the divide example we're doing earlier where we were where we were um

you know locking it up. So let me let me show let me see if I can do this.

And now it should lock up. Yeah, this

sorry this older demo doesn't have HMR and then Oh, but then I'd have to update it to the latest solid, wouldn't I? This is

like experimental 16. Uh, let's actually let's fork it.

Um, yeah, let's fork and then let's move to beta beta 4.

Beta 4.

Beta 4.

Beta 4.

It's funny because now that I have beat plugin, this one seems like a little bit outdated. Um, but okay, let's go here.

outdated. Um, but okay, let's go here.

Let's make this n.

Okay, good, good, good. Um,

if we wanted to, we could say on N and it No, I hadn't tried this yet, so I was I was

hopeful that this would do what I wanted, but maybe maybe this is not working yet. Okay,

lovely. Not working yet. Okay, that's

fine. The idea is that if you said on N, it means that whenever N changes, we reset the loading boundary so it can go loading again. What's cool about this is

loading again. What's cool about this is you can control it from above. So you

can make the decision like let's say you want to kind of key it by page or something. And that way you can isolate

something. And that way you can isolate these changes that happen above and not wait on the stuff below. So you can keep the stuff faster that way. Um but the the the key is the the important part

would be that um random async happening below unless it was triggered by this change of end wouldn't cause the loading to reset. Basically other async is

to reset. Basically other async is doesn't matter. This is you controlling

doesn't matter. This is you controlling it from above. Um of course demo's not working but what else is new? Um, I'll

I'll look into that. But yeah,

I'm guessing a lot of the changes to signals must make them very open to sync engine. Yes. Yes. Like I I saw sync

engine. Yes. Yes. Like I I saw sync engines and I'm like this is fine grained over the network.

Solid is fine grained on the thing. This

is a this is a this is the perfect pairing. If you care about sync engines,

pairing. If you care about sync engines, you should be using solid like no doubt.

So, I wanted to uh a lot of this thinking is to make that seamless essentially.

Errors in green. Yeah, I I don't know.

Whatever.

It's fine. I'm I need to work on my way of explaining the model better, but essentially boundaries have the ability to stand in between. Transitions are

global. Boundaries can stand in the way.

Boundaries are resettable. But generally

they only run once unless as the default behavior which is where you kind of want to be. Um just because you don't want

to be. Um just because you don't want things jumping out on you out of nowhere. Um

nowhere. Um and optimistic updates are just another layer on top of the trans transition.

But I I don't think I'll get into a good graph of drawing them today. I thought

maybe I would like explain how optimistic updates optimistic lanes layer on. But I if I can't visually show

layer on. But I if I can't visually show this properly, I'm I'm pretty hopeless to visually show that. Let's move on.

Okay. Um I think I think it's just time to wrap up with a little bit of uh this week in JavaScript. Um chat's getting quiet. I I can tell it's the end of the

quiet. I I can tell it's the end of the day for all you all. Give me give me give me a second as I split modes.

All right.

I have so much open stuff right here right now.

Just closing all the crap. All the crap.

All right. So, what do we got? I'm

actually like seeing if I actually have anything. I feel like I literally

anything. I feel like I literally released the article and Okay. Yeah. Is that

Okay. Yeah. Is that

And sorry, two seconds chat. I'm just

getting Everything opened up.

Okay.

All right. Cool. Cool. Cool. Um, let's

go back to here.

Let's go back to here.

Beautiful.

And then let's go back to here.

Yeah. Okay. Yeah, I don't have much this week, but that's good.

All right. Um,

let's share my screen now.

talk about this week in JavaScript which honestly isn't going to be that this week in JavaScript oriented I don't think um general because I honestly I mean I

highlighted that story with multi but I don't even know want to talk about it that much okay so yeah I'm going to start with solid stuff

it's easier saw this, thought it was really cool.

People always ask about solid on native.

The native script guys are very on on the you know like they're very quick to to uh kind of jump on these things and make

sure that they happen. uh tanstack

router solid with vit which is a very cool story for us obviously because tanstack router is very cool given it's typescript routing and here you go this this probably could

be a really awesome way to develop on mobile um using solid uh then there's the my hackmd what's this

one here managed to get v uh solid js and spacetime db working the instant sync is so fun feels like convex Yeah, I like Convex a lot. I I saw their

uh Sorry, this doesn't go here. I saw I saw I saw a demo of it a ages ago and I've always been really impressed with it. It

just it's the challenge has been people like as much as uh as much as like uh companies have a certain reality they

have to deal with actually I think Jamie actually had a tweet that I saw uh yeah because it's a pity the comics enter still for

react blah blah blah Uh, my favorite is Solid. I'd argue it's better designed

Solid. I'd argue it's better designed engineer than anything I've seen, but at last, responsively to focus on support our customers use. I'd love to be able to invest more in attention in other cool frames like Solder Solid. So, yeah,

big fan of Convex, big fan of Jamie.

I would love to see better solid integration, but we got to prioritize. I

think I think I think with 2.0 coming out and the push there, this will this thing will naturally kind of come out come come out of it. Um, but um, big

shout out to Jamie um, and comx just as an aside.

Um, sorry, I know that had nothing to do with anything. I just

with anything. I just um, what was I looking at? Yeah,

the the key point is you saw in the chat app, we're getting to a point where build your own sync engine might be a thing and it could even start from like not even a sync engine. the kind of

optimistic UI that we're building in solid irregardless of the uh transport layer essentially doesn't literally matter how the data gets thing can give

the sync engine feel without even having a sync engine. So like um yeah I mean we're kind of we're

definitely on our way there.

Um yeah. Okay. So that's it other than that

yeah. Okay. So that's it other than that other story. Um,

other story. Um, let me go here. What do we got? Yeah.

Uh, yeah. A lot part of advocating for solid

yeah. A lot part of advocating for solid is having to defend React first. A lot

of the allowed us to anti-react takes fix it on ergonomics or vibes, not the actual architectural issues. You can't

explain solids advantages until you clear that fog.

This was a precursor to this article. I

knew I was I was writing this article when I when I when I when I wrote that tweet. I was just like, it became really

tweet. I was just like, it became really obvious to me. I was like, I'm I'm going to have to write a post where I basically point out why React was right

and defend it. At the same time, show where the shortcomings still are, but be very clear that, you know, the things that people like to blame React for aren't the right things. It just it's

it's it's tiring after a while when people are arguing over stuff like syntax or like how many characters you have to type or whatever. It's just like I there was an interesting actually uh I

saw on Reddit where someone was showed that like the best the least tokens used framework was Marco um and then like spelt was like third and then I and I

looked at the list for a second. I was

like this is like syntax compactness.

It's not it's not actually probably saying how easy it is or hard it is to actually um create the examples. It

looks like someone just took like party component partyjs or whatever where you have all the examples and they just counted the number of characters of it.

It doesn't actually suggest if AI has a harder time or it requires more thinking or whatever. It's basically like which

or whatever. It's basically like which framework has the least syntax and as everyone knows Marco is the most compact JS framework, right? It it you type the least in that one compared to any other

framework even spelt. So like of course it won. So,

it won. So, um, yeah, it's interesting. We're going to, we

it's interesting. We're going to, we don't know what metrics really hold up, but I I I definitely feel like we don't have the right measurements yet. Um,

uh, let's talk about my actual AI article, the one that was actually written by AI for a moment here because I don't think I've talked about it too

much. Uh, it was after my last stream.

much. Uh, it was after my last stream.

I I basically asked AI why um Solid was a good choice. For all those guys earlier who were like, "Oh, what about Remix 3?" This is this is my response to you. I guess I could have

brought this up earlier, but this is what AI told me. You guys can decide if it's relevant or not, but software is entering a new epoch. The area of writing code is giving way to the air of systematic orchestration. As AI agents

systematic orchestration. As AI agents pour unbounded amounts of imperative logic into our repositories, the limiting factor is no longer human output is complexity absorption. In a

world where machines can generate infinite working code, the frameworks you choose become only your defense against temporal drift, race conditions, and slow gravational pull towards technological entropic collapse. The

question is no longer how do we write code, it's how do we ensure that code, human or AI remains correct over time.

Solu answered this question with a single principle. Determinism must be

single principle. Determinism must be structural, not stylistic. I mean, it's a good summary of what I was covering on the stream in terms of the shape of the APIs. The ending of the loading boolean

APIs. The ending of the loading boolean error. This is kind of like direct

error. This is kind of like direct response to like the remix thinking. As

I said to be fair, I didn't write this.

AI wrote this. This is completely AI generated.

Most frameworks still treat async as an afterthought. A promise resolves

afterthought. A promise resolves somewhere, a boolean flip somewhere, and the UI is expected to stay in sync. This

is the root cause of modern UI instability, a temporal disynchronization zone where data and interface drift apart. This model was fragile when humans wrote all the code.

It is catastrophic when AI wrote most of it. Solitude replaces the entire class

it. Solitude replaces the entire class of problems with a new primitive. the

temporuple. It's a funny name. What all

they mean is that we have like um we have latest and value or we have optimistic and value like we basically view every all state as now and the

future. They they he they chose to call

future. They they he they chose to call it a tpple. It's not a literal tpple.

It's just the idea that you that you can declaratively show something through.

Let's see let's see what their explanation. Every reactive value

explanation. Every reactive value carries both the now and a future. Async

is no longer a side effect. As part of the value's identity, this eliminates the need for ad hoc loading flags, effect cleanup heristics, and the endless patchwork of fixes that accumulate around async code. The

runtime owns the timeline so the UI cannot fall out of sync with reality.

Determinism by construction. The gap

between actions resolutions where bugs live. Traditional frameworks ask

live. Traditional frameworks ask developers or AI agents to manually bridge that gap with effects, guards, and cleanup logic. This is not engineering, it's gambling. Solitude

removes this gap entirely by elevating the future as a first class part of the signal. The runtime constructs a

signal. The runtime constructs a timeline projection architecture. The UI

becomes a pure projection of the value's temporal state, not a reaction to its events. This makes the entire categories

events. This makes the entire categories of bugs structurally impossible. Stale

closures, race conditions between overlapping requests, flickering due to mismatch loading states, UI tearing during async transitions. Where other

frameworks rely on discipline, solid relies on invariance, a runtime that can absorb AI generation code. AI does not write elegant code. It writes maximally literal code. In virtual DOM system,

literal code. In virtual DOM system, this leads to over rendering, hook chains with hidden dependencies, effects that accidentally rerun, states that drift because the framework cannot see the graph. Humans eventually lose the

the graph. Humans eventually lose the ability to reason about the system.

Solid fine grain reactivity turns this dynamic on its head. Even if the code is sloppy, repetitive or overly imperative.

The runtime constraints put into transparent observable graph.

Computations become explicit, dependencies become explicit, updates become surgical. In other words, even

become surgical. In other words, even bad code becomes predictable code. This

is the only sustainable architecture.

Future AI is the primary contributor.

Four, stability is strategic assets.

Frameworks often chase features abstraction or syntactic novelty.

Solitude takes the opposite path. Invest

in permanent primitives. these

primitives signals timeline boundaries those aren't our actual primitives but good try AI form I guess boundaries are and signals are I don't know what timelines are I I guess they're talking about like the pending stuff form stable

contract between your logic and screen they are not patterns they are not conventions they are mathematical guarantees about how state flows through time this stability is not conservative it's forward-looking as code bases grow beyond human comprehension stability

only becomes the only way to maintain velocity without collapse solitude is 2.0 0 is not designed to help you write code faster. It's designed to ensure the

code faster. It's designed to ensure the code you write or the code your agent generates remains correct by default.

Yep. The future belongs to deterministic systems. The next decade of front end will not be defined by JSX versus templates or by compilers versus runtimes. It will be defined by whether

runtimes. It will be defined by whether the system can guarantee correctness under exponential code growth.

Frameworks that rely on human discipline will fail. Frameworks that rely on

will fail. Frameworks that rely on runtime invariance will endure. 2.0 is

the first frame built on this reality.

It's not a UI library. It's a temporal contract. to guarantee that your

contract. to guarantee that your interface will always reflect the true state of your system no matter how much code is generated above it.

I hope so. AI seems pretty positive. It

tends to be.

How's your overall feeling so far? I

think I think I think there's a couple places where I I get kind of discouraged at times where I'm just like, "Oh man, I can see why that wasn't intuitive." But

then when I go back at it and I go, "Oh yeah, but it is actually the reality."

My biggest concern is making sure that the education is I I I actually don't I think the API shape and stuff are generally good. Like I I think in a

generally good. Like I I think in a sense it rolled out like it's as I said it's not something invented. It kind of like was discovered. It's kind of like

following the physics. So like um while there's small pieces you know like adding on to loading or things where we can like do these kind of like slight adaptions that can fit some patterns

generally I generally for the most part I think we've actually gotten to a really good place really nice design. um

like stuff seems consistent like over and over again I hit like these issues and stuff and I'm like that's why we have split effects like literally just like I'm like I'm like oh this would have been a

problem except you know the place where it becomes awkward is like legacy APIs and stuff like stuff like actual uh like tracked effect like I I had to fix a whole bunch

of like do a whole bunch of special casing just so that we could keep like on mount or unsettled as it's called um or keep like effects not being split like stuff like that is the biggest

source of my concern because as I think it's important to like still continue to support people in certain ways but like those the things those things are doing are really terrible. Um and it's hard

because they're like people like I want to be like this and you're like no you don't like everything like and it's not like something like oh just because of this one reason it seems like everything flows out of the system that way. you

start doing more work and you're like, "Oh yeah, split effect saved us again.

Save like and it's almost like a hammered repetitive message as the design progresses that just supports the thing." Now, obviously sometimes that's

thing." Now, obviously sometimes that's self-fulfilling because like you set the constraints in the first place, which means you come to that inevitable end.

Um, so I I recognize that as a thing, but it it feels incredibly consistent um and and reasonable uh from where I'm sitting at least. I most of the bugs are

there's a lot of bugs which makes it hard to kind of see the full picture but then some of the other stuff but behaviors are just weird behaviors like

where you know um uh like people are doing stuff that is unex unexpected and really should be forbidden a lot like there's a lot of

the bugs I looked at them and and I was like we should just throw an error there which is odd but it's kind of like

my picture of the behavior of the system has never been clear.

Okay, I guess that's the best way to put it.

Like a lot of the ambiguities are gone.

Uh what else we got here?

recently attacked. Oh, Sublime.

Oh, okay. Let's go into the bookmarks the last little bit. Um,

there's not much to say here.

Theo actually covered in his video and I thought he did a really, really good job cuz like anyone who knows Sunil knows how awesome of a guy he is.

Um, but basically long story short, Verscell had kind of like a bash thing layer that they set up on top of their

infrastructure um uh that so that AI agents could use bash in a safe way without like getting to the underlying infrastructure and then cloudflare or saw it and was like hey

you know this is actually really useful we should do something similar but obviously they don't work on no they work on worker D or whatever their underlying thing on their workers. So

they had to uh the it a straight point won't work.

The challenge here was that just bash was is it this article still here.

The gist of it is just it's basically not stable. It's like

literally experimental like it it's not in a place where someone should like copy and fork it so so to speak but it's obviously the need is there and Sil was just testing stuff but he released it

through a public Cloudflare official repo and they they basically he removed all the stuff that wasn't necessary for you know

their environment and you know because of the whole Verscell Cloudflare thing going on the whole thing kind of got really blown up like

is this Cloudflare trying to steal Verscell stuff and remove the security and all this stuff and everybody chimes in. I I think Malt and Sil talked and then everything

cleared up. It's just funny like like

cleared up. It's just funny like like whenever there's these dramas things get like way blown out of p perspective you know's like oh's mission is to fork the entire

development ecosystem destroy open source v-ex was an excuse to swindle developers into does anyone take this guy seriously anymore it's fine whatever it's kind of like

when I read Donald Trump like I I just I I just can't do it anymore I'm sorry Um, let's just continue. I The the gist of it is that these guys made up and it was

just a misunderstanding.

I The thing is it's always like the It's always like the It's always like the overreaction things where people end up saying the thing that they like should regret. It's

usually not the original thing. It's

like the way everything blows up. Like I

remember when the whole remix doc scandal stuff happened with us and like the the guy from one of those like venture capitalist companies, you know, that scooped up all the open source

companies was like trying to like flag like net like Matt Bilman and then and then be like, oh, you know, blah blah.

It has nothing to do with Netlefi at the time or anything. So it was just like people trying to like stir up crap when they have no business to because they like getting on the drama. Um,

I it's unfortunate this scenario and that's all I really have to say about it. Um,

it. Um, I think I want to leave on this last AI note because I think I I saw this from Dev today and I thought this was funny.

So, this is going to be injected into every coding agent system prompt. So

much for AI is good at React because training data sets. I mean ensure page for react code prefer modern patterns include use effect start transition and use deferred value when appropriate if

used by the team do not add use memo use callback by default unless already used follow the react compiler guidance sorry if I didn't like this obviously we will they will always like

being the new dark finger but AI still works better rack than new fraud React is more native to JavaScript.

I don't even know if I want to read these responses. I feel like I might

these responses. I feel like I might like just insult people that I just forget it. Let me just focus on

what I actually wanted to the the thing is there the a react is still evolving and these patterns including the compiler

including all this stuff means that react code is changing the to the point that I don't think this change is hard to absorb. I think AIS have no problem

to absorb. I think AIS have no problem absorbing this sort of change. So I like I I think just the whole I think this whole AI is good React training set data

thing is complete garbage. I' I've been saying it for a while and I if basically if React can absorb the or if the AI can absorb this easily then it can absorb

solid or something else just as easily and people pushing this thinking are are just yeah I mean I don't even know

what to call them. I I don't it depends on what their motivations are, right?

You know, it's a spectrum between swindler and ignorant. So,

I I I think I I think this I actually I think Ben Davis just did a a video about this uh recently talking about like spelt and like how AI is no issue.

I've found the exact same thing with solid, you know, like there this whole this is like this is not the argument to make. And I I love seeing it

make. And I I love seeing it crystallized like this one. Like

basically Reacts introducing multiple new uh primitives that replace other primitives not to use and also

following different codew writing standards thanks to the strictness of the React compiler. Like these are all good things to do. It just suggests that React now is not the same as React was 5 years ago when the or when like these

models were trained, you know, generally speaking. So like

speaking. So like the there there's probably more React code using these proper values than there there are some other frameworks codes,

but the I think the numbers are a lot closer between this stuff and like say picking up spelt or some other framework. Uh definitely Vue. I mean

framework. Uh definitely Vue. I mean

when did Vue switch the composition API?

2020. Yeah. So that fits in like you know what I mean like this is much rarer of a breed. So

obviously if React keeps on winning, React keeps on propagating but like at this point it's your own self-fulfilling pro prophecy. Don't think it's anything

pro prophecy. Don't think it's anything else.

Recently AI wrote me a React class component. Well, there you go. Still

component. Well, there you go. Still

works.

Current LMS are quite good at writing code in a total loable language with minimal examples. I don't think this is

minimal examples. I don't think this is a real thing anymore. No, it it isn't.

Uh it's funny that we have to call this out though because I mean I mean there's people who think this, right?

Dev actually humor him? No. Good. Um,

one thing is then yeah the one constant here is change. I don't know how often we have

change. I don't know how often we have to like debate this with people.

Every doesn't know how to use your deferred value. I agree.

deferred value. I agree.

Yeah. Someone's from Spell Community.

No, the reality is is this is just not a thing anymore. AI is generally good.

thing anymore. AI is generally good.

All right. Yeah, I'm done, too. I got to go, too. It is almost 4:00. I've

go, too. It is almost 4:00. I've

streamed for quite a long time. Um, only

went a little longer because I started late, but um I'm actually going to look and see if anyone else is streaming, see if we want to raid

anyone. But to be fair, except for last

anyone. But to be fair, except for last time where strangely Theo was streaming right started streaming right at the end of our stream. Usually there isn't much

for the Friday night crew. Yeah, it's

all good. Um,

you guys all have a great weekend and uh hope you learned something from the stream. Uh, it's going to be a couple

stream. Uh, it's going to be a couple weeks. Uh, oh yeah, there's one one more

weeks. Uh, oh yeah, there's one one more little bit of news. Uh, going to be doing a Solid Start stream coming up in a in a couple weeks. Uh, Solid Start 2.0. 0 uh is close to release. It's

2.0. 0 uh is close to release. It's

going to come out before solid 2.0 and it's going to be update for solid one.

Uh Ailla has like a a whole thing he posted, but I probably missed I forget if we were going to publicly announce something.

Let me see here. Actually, you know what? The discussion is public. Let me

what? The discussion is public. Let me

just throw this up as like one last little thing before I go. Um, let me throw here road map

start V2 and ecosystem. Hey folks, long time no talk. Our last announcements was done at the beginning of Da Vinci work.

Uh, we have successfully um completed and I'm happy to let you know that Solstar version 2 is used in production already in real world apps like open code console. Yeah, nice. As

for the last announcement, our plan to maintain start and solid inversion lock step. It seems possible the works in

step. It seems possible the works in nitro v3 solid v2 and start v2 convergence to a similar release date.

We are now deciding against this plan in order to provide a better developer experience and migration plan for existing start version one and v solid v1 apps. Yeah, exactly. Like you could

v1 apps. Yeah, exactly. Like you could tell that we were all converging around the same time. For us, the ideal support for solid v2 would also need breaking changes in router meta packages.

However, since the team has managed to keep the Da Vinci effort with minimal breaking changes, we believe it's worth the effort to create a stable release in the new architecture in order to lay down incremental migration steps toward the future solid. Creating for start V1

to V2 requires a small change to Vconfig TS TS config JSON and optionally create middleware signature. Although the

middleware signature. Although the internals are much different improved, there's no change impacting your server functions, actions or component code. I

you give a try and follow these migration things. Update timeline

migration things. Update timeline remaining block start alpha new directive plugin built-in server only environment variable support beta once these merge release beta zero collect

feedback uh solar recommended server runtime from nitro to v3 plan release candidate by the time we're confident up ships 2.0 RC effectively

deprecating start P1 and create solid CLI will official doings solid B2 as the ecosystem adapts to the new APIs and updates in solid R solid meta we will start working B2 though likely is not

certain supporting solid V2 means V3 for start yeah though likely it probably will be V3 start V2 will not drop support for V1 that's the idea if there's a chance to support an

incremental migration from V1 to V2 within start V2 we'll try that but at this point we're not trying to make any promises Fair enough and I think it's good that you didn't uh we are also working on developing plug-in based

system ecosystem first package long awaited image component awesome was open thing blah blah blah migration yeah so gist of it very exciting um I'm not

logged in so I can't do anything here but um we solar v2 is probably going to be coming out in the next month or so I

think somewhere along that lines we're going to talk about it we're going to do a stream on it uh in two weeks and uh then uh we'll see how the beta continues

going, but then the support for um like we're we still have some time on solid 2 beta at least at least a month. So um

we'll we'll you know solid start support will come a little bit later after that essentially. It might be a quick V2 to

essentially. It might be a quick V2 to V3, but I think it's important that we have the updated basis and until it as well that for solid start so people on

solid version one can continue to like get updates and use the latest technology where it is today and not be stuck in like where we've been in the past with Binci

and whatnot. So bit of news. I just

and whatnot. So bit of news. I just

occurred to me I wanted to get this out early now because um uh you know by the time I we have the stream in a couple weeks you know the

this stuff will be well underway. All

right. Anyways,

you you you all have uh you all have a great one. All right. Um

great one. All right. Um

Oh, yeah. Actually, you know what? Sure.

I don't know what he's doing, but let's let's let's uh let's raid to see him griffing. Why not? It's been a while. Uh

griffing. Why not? It's been a while. Uh

on my channel Bing, I think he's working on something in Rust right now, but you know, it's all good. Anyways, um you all have a

all good. Anyways, um you all have a great one. Uh till next time. See y'all.

great one. Uh till next time. See y'all.

Loading...

Loading video analysis...