As a person developing in react for the last 5+ years, I have to say it seems solidjs does have superior features/capabilities to react from this demonstration
Facebook programmers made vdom a thing and then tried to make things work around it and big companies adopted it and we're asked to know how it works to use it correctly, what a hell of a world 😆 good job Ryan.
Solid presentation Ryan. And very humble of you not to give the performance numbers of SolidJs vs React. You said that performance can always be optimised but I think that React dug itself into a hole and that only a breaking change can take it out of. Looking forward to see you explore the design space of resumability! In my opinion JavaScript has become too complicated, and we may benefit from a new high level language designed with DSLs in mind (a Lisp??) so that we do not need the huge compilation toolchains of today.
Timestamps - 12:39 Slide with `createSignal` and `createEffect` implementations. An opportunity to understand how reactivity on SolidJS works. - 16:19 Reactivity with vanilla javascript show up. - 16:33 Apply JSX syntax - If there is a function in JSX component, then SolidJS compiler wraps that component into `createEffect` - 18:02 Make it a component: Counter. - 20:22 Ryan shows that Counter function called only once! And update happens due to effect that updates only `h1` tag text. Counter is not actually a component, it is actually a function. - 20:54 Another evidence of Count is just a function and called just once: using `setInterval` inside and call `setCounter` in timer. - 21:49 Two Counters on same page. - 22:21 What about global state? You can do it, it is just your functions and closures, you can architect as you want. - 22:53 Props drilling example. - 23:45 There is a little bit more than you showed me before. If compiler see function call or an expression - it wraps it into effect. Laziness. - 24:30 Map to DOM nodes. Controlling the flow. - 27:13 - components run once - no hook rules - no stale closures - templates compiles into real DOM nodes - most importantly state is independent from components - 28:56 Component need their Javascript even after server rendering. This is known as Hydration. If we can get rid of runtime components, we can also eliminate hydration.
I love these control flow components! This is one of the things which I like more in angular than react ( even though these here in solid are much more powerful!). Now that this is fixed, and with all these other benefits (I have tried for years to make my angular apps fully reactive!), I can gladly retire Angular. RIP 😄
Unfortunetely, I feel like there are not many people who will understand how wonderful is this library. I remember the day when I first put my hands on React, after 10 years of experience in js I was writing a junk code that was in a recursive never ending loop and I couldn't understand why at that time. Then I realize that component functions in react always runs over and over again on props change....That never make any sense for me. Another weird thing on react is relying on props change. Javascript is a language that you can't rely on object comparison without compromising performance...In the world of javascript vanilla and browser everything works really well with events... If that event happens, then I know that I need to refresh or update something. To make any update looking for some change inside a object structure is just a bad idea. Maybe some day we're gonna wake up from this stupid fantasy... But it's alright for hybrid mobile app development... only because there's nothing better yet.
React's rule is that UI is a function over state (UI = F(S)) which is why it makes sense it would re-render when state (e.g. props) changes. This is how functions in JS works, too. Hooks may seem counter-intuitive until you releasize that they are effectively just event listeners that can be synchronized with state, only calling them when its state dependencies change. Solid's components are a bit harder to reason about, because it's not immediately clear that there are boundaries between initializing code and the reactive UI. For example, in the default SolidJS playground, adding a conditional render (e.g. if (count() > 5) ? : {count()}) will not work as expected because the first condition is only called _once_. Looking at the compiled output, you can see why this is the case. This is because just calling the signal's getter is not enough to track its changes. This makes it hard to debug and unclear for the average JS developer that is not familiar with Solid's inner workings. Btw, this is not to dig on Solid. I love Solid, and I think it has really good concepts that React could learn from (especially the primitives it brings and its signals). I was just explaining why React is more true to JS than Solid.
@@dealloc Yeah, you're right in that case. Perhaps a way out of that is to return a function in the end of the component function, that takes props as arguments, so that part could rerender many times... idk. I do understand the UI = F(state) Idea, but I believe that makes sense only for UI. It's not so different than we used to do, using handlebars, mustache or template strings. React works different internally but the abstraction is the same for the end user. It's about sending a js object and getting an updated view. The issue I see in the React code design is that components does not have only UI as a concern, they are in the most part Controllers. They have to deal with event handlers, state managment, subcriptions, api calls etc. By making those parts rerender just like the view will get you in situations where you have to think to do something that should be obvious and straighfoward. I don't like Angular either, but I believe they have a better component design, you know that contructor will be called just once. Maybe it's hard to think in a better alternative because people can only see the React way of doing things... But look at this prototype for example: stackblitz.com/edit/async-in-jails?file=app.ts The only function that get called many times is the onclick handle function. So the rest is static, only runs when component mounts. So you can do the other things like ajax calls with async/await and everything without worry about other issues... useEffect is not needed in this world.
@@O_Eduardo Agreed that React components (well components-based architecture in general) does more than just UI nowadays, but that is inevitble-any rich web app will have to introduce side effects (events, async IO, etc.) One could argue that re-rendering the components when state changes is desirable to keep UI in sync with the state. The only rules in React you need to know is rendering happens on mount, setState and passing new props to a component. Of course there are cases where you only care about the UI changes that shouldn't be based on state, in which cases you can manipulate the DOM directly without triggering re-renders, but those are mostly for animations and highly interactive components (drag and drop, virtualized lists, etc.). It's a hard problem to solve, because side-effects are complicated in general and you have to deal with them in different ways based on context and requirements. useEffect is a low level primitive in React and ideally you should use use a library to handle async operations, caching and state. In the example you post it does more than just call "onclick"; it also mutates the entire DOM. According to the impl. it just replaces everything in the template when state updates. Not sure if this is an oversight but doesn't seem right.
@@dealloc Yeah makes sense your thoughts... From my point of view, is not like we are doing more then UI nowadays, in fact, for me front-end chalenge is about dom update and not the html rendering. But React mix the both concerns and its part of the things that stays in the way, it´s trade-off... ( You are kinda stuck on JS even on server side because that coupling ) You could render all your application with server side rendering or using static generation boilerplate with some node template system, and you´ll realize that some parts of the application is in fact dynamic...not all of it ( SPA´s is an exception ) The example I showed uses diff dom internally and gets html from the custom element and compiles it, so it´s not an innerHTML, it has diff dom in it context the other parts of the app will not be mutated or it will not have any diffing. It relies on Island architecture, because in practice your site is dinamic but you rarely need to update all components in the page at once, you just have to update some parts of your application.. So I use a state managment library to do those comunications and ui sync or sometimes I just use a pub/sub pattern which is simpler. Part of the bad design for me in react is that you have to think in performance all the time, by making several assumptions, like you did in the example, so you shouldn´t have to worry about, because the library and the way it work should address those issues. useMemo, useCallback, useRef, how to use context without updating several part of components tree.. etc... all these things just exists because you are stuck on React world. But There are no such thing as silver bullet and perfect world. React does a thing that would be impossible in the way I´m proposing, which is write the same code that can be rendered in server side and its the same code that will be executed in clientside... sometimes its very convinient.. but you pay a high cost for the other 99% of the scenarios which could be fine to separete that rendering html from js logic... You won´t be able to integrate with other template systems, server side frameworks in other languages, and have to wait for some React-like UI library because it doesn´t integrates well with vanilla UI solutions, so its about React community, not JS community... Idk... it´s been 5 years I´m working with complex apps using js without React now.. I feel like I prove empiracally for myself that those things has value, but... 99% of the times.. not necessary...and if it was, Angular, Ember, Vue, Lit, Svelte, all of them would need to use the same principles or you wouldn´t be able to build complex apps with those frameworks, which is not true.. But at this point we are in modern tech, is all about taste and marketing...Maybe Astro will lead us to a different way in the future, idk, but I like what they are doing in order to integrate the most adapted framework.. I like new things and different ideas, I feel like we are trapped in the react for a long time..
Setting the record straight - single page apps built on reusable components was a flash novelty, not a react novelty. Flash did this in the late 90's / early 00's expertly.
React started out as a great idea, but with hooks and functional components it just seems that every project I join (or write) ends up an incoherent soup. I never know when components update without reading and understanding every hook. My components are littered with memo, useCallbacks and refs. I'm mainly a React Native dev so it's important to not leak event handlers or have native code run callbacks that don't exist anymore.
I think that one really important aspect of it is how this can be ported back to react and preact, as signals did. Preact's approach is the bets of both worlds where it keeps the vdom but encourages using signals instead of hooks, so that the vdom render typically only happens once, but it also avoids needing the component since that part can still be handled by a real VDOM (if you are memoizing DOM nodes, you have a VDOM regardless of whether or not you admit it).
I think Facebook had an extremely unique set of problems that most people don’t have. You can’t be so simple minded to think that one framework can rule it all.
I have a library that does this without a compiler :) and can be built by pure esbuild (no plugins, just pure esbuild compile speed). I named my loop component Loop and not For :D. Instead signals uses proxy to watch state changes.
@@internet4543 that is mathematically incorrect. To disprove your moronic statement it is enough to find at least one person that knows me and the lib.
This is the best JS presentation I've seen for a long time. SoldJs is definitly the best thing JS world has seen for a long long time.
As a person developing in react for the last 5+ years, I have to say it seems solidjs does have superior features/capabilities to react from this demonstration
Facebook programmers made vdom a thing and then tried to make things work around it and big companies adopted it and we're asked to know how it works to use it correctly, what a hell of a world 😆 good job Ryan.
Solid presentation Ryan. And very humble of you not to give the performance numbers of SolidJs vs React. You said that performance can always be optimised but I think that React dug itself into a hole and that only a breaking change can take it out of. Looking forward to see you explore the design space of resumability!
In my opinion JavaScript has become too complicated, and we may benefit from a new high level language designed with DSLs in mind (a Lisp??) so that we do not need the huge compilation toolchains of today.
He's such a humble guy. I think he's great
Ryan throwing shade at React in React event :) . love this.
Dude, @ryancarniato love the talk, and LOVE the Sliders reference
Wow, I didn't expect it to be this good😍
Having the opportunity to work with Ryan on solidjs would be great
I absolutely love this ryan! What a great talk 😄!!!!
Timestamps
- 12:39 Slide with `createSignal` and `createEffect` implementations. An opportunity to understand how reactivity on SolidJS works.
- 16:19 Reactivity with vanilla javascript show up.
- 16:33 Apply JSX syntax
- If there is a function in JSX component, then SolidJS compiler wraps that component into `createEffect`
- 18:02 Make it a component: Counter.
- 20:22 Ryan shows that Counter function called only once! And update happens due to effect that updates only `h1` tag text. Counter is not actually a component, it is actually a function.
- 20:54 Another evidence of Count is just a function and called just once: using `setInterval` inside and call `setCounter` in timer.
- 21:49 Two Counters on same page.
- 22:21 What about global state? You can do it, it is just your functions and closures, you can architect as you want.
- 22:53 Props drilling example.
- 23:45 There is a little bit more than you showed me before. If compiler see function call or an expression - it wraps it into effect. Laziness.
- 24:30 Map to DOM nodes. Controlling the flow.
- 27:13
- components run once
- no hook rules
- no stale closures
- templates compiles into real DOM nodes
- most importantly state is independent from components
- 28:56 Component need their Javascript even after server rendering. This is known as Hydration. If we can get rid of runtime components, we can also eliminate hydration.
I ❤ Solid js
Solid js is the first real framework I've used since jQuery and it's great. Seems like the obvious choice.
Great talk
Amazing .., talk!!
I love these control flow components! This is one of the things which I like more in angular than react ( even though these here in solid are much more powerful!). Now that this is fixed, and with all these other benefits (I have tried for years to make my angular apps fully reactive!), I can gladly retire Angular.
RIP 😄
9:20 Please, the first line of every explanation on Reactivity should be how it differs from the Observer Pattern.
Unfortunetely, I feel like there are not many people who will understand how wonderful is this library.
I remember the day when I first put my hands on React, after 10 years of experience in js I was writing a junk code that was in a recursive never ending loop and I couldn't understand why at that time. Then I realize that component functions in react always runs over and over again on props change....That never make any sense for me.
Another weird thing on react is relying on props change. Javascript is a language that you can't rely on object comparison without compromising performance...In the world of javascript vanilla and browser everything works really well with events... If that event happens, then I know that I need to refresh or update something.
To make any update looking for some change inside a object structure is just a bad idea. Maybe some day we're gonna wake up from this stupid fantasy...
But it's alright for hybrid mobile app development... only because there's nothing better yet.
React's rule is that UI is a function over state (UI = F(S)) which is why it makes sense it would re-render when state (e.g. props) changes. This is how functions in JS works, too. Hooks may seem counter-intuitive until you releasize that they are effectively just event listeners that can be synchronized with state, only calling them when its state dependencies change.
Solid's components are a bit harder to reason about, because it's not immediately clear that there are boundaries between initializing code and the reactive UI.
For example, in the default SolidJS playground, adding a conditional render (e.g. if (count() > 5) ? : {count()}) will not work as expected because the first condition is only called _once_. Looking at the compiled output, you can see why this is the case. This is because just calling the signal's getter is not enough to track its changes.
This makes it hard to debug and unclear for the average JS developer that is not familiar with Solid's inner workings.
Btw, this is not to dig on Solid. I love Solid, and I think it has really good concepts that React could learn from (especially the primitives it brings and its signals). I was just explaining why React is more true to JS than Solid.
@@dealloc Yeah, you're right in that case. Perhaps a way out of that is to return a function in the end of the component function, that takes props as arguments, so that part could rerender many times... idk.
I do understand the UI = F(state) Idea, but I believe that makes sense only for UI. It's not so different than we used to do, using handlebars, mustache or template strings. React works different internally but the abstraction is the same for the end user. It's about sending a js object and getting an updated view.
The issue I see in the React code design is that components does not have only UI as a concern, they are in the most part Controllers. They have to deal with event handlers, state managment, subcriptions, api calls etc. By making those parts rerender just like the view will get you in situations where you have to think to do something that should be obvious and straighfoward.
I don't like Angular either, but I believe they have a better component design, you know that contructor will be called just once.
Maybe it's hard to think in a better alternative because people can only see the React way of doing things... But look at this prototype for example: stackblitz.com/edit/async-in-jails?file=app.ts
The only function that get called many times is the onclick handle function. So the rest is static, only runs when component mounts. So you can do the other things like ajax calls with async/await and everything without worry about other issues... useEffect is not needed in this world.
@@O_Eduardo Agreed that React components (well components-based architecture in general) does more than just UI nowadays, but that is inevitble-any rich web app will have to introduce side effects (events, async IO, etc.)
One could argue that re-rendering the components when state changes is desirable to keep UI in sync with the state. The only rules in React you need to know is rendering happens on mount, setState and passing new props to a component.
Of course there are cases where you only care about the UI changes that shouldn't be based on state, in which cases you can manipulate the DOM directly without triggering re-renders, but those are mostly for animations and highly interactive components (drag and drop, virtualized lists, etc.).
It's a hard problem to solve, because side-effects are complicated in general and you have to deal with them in different ways based on context and requirements.
useEffect is a low level primitive in React and ideally you should use use a library to handle async operations, caching and state.
In the example you post it does more than just call "onclick"; it also mutates the entire DOM. According to the impl. it just replaces everything in the template when state updates. Not sure if this is an oversight but doesn't seem right.
@@dealloc Yeah makes sense your thoughts...
From my point of view, is not like we are doing more then UI nowadays, in fact, for me front-end chalenge is about dom update and not the html rendering. But React mix the both concerns and its part of the things that stays in the way, it´s trade-off... ( You are kinda stuck on JS even on server side because that coupling )
You could render all your application with server side rendering or using static generation boilerplate with some node template system, and you´ll realize that some parts of the application is in fact dynamic...not all of it ( SPA´s is an exception )
The example I showed uses diff dom internally and gets html from the custom element and compiles it, so it´s not an innerHTML, it has diff dom in it context the other parts of the app will not be mutated or it will not have any diffing. It relies on Island architecture, because in practice your site is dinamic but you rarely need to update all components in the page at once, you just have to update some parts of your application.. So I use a state managment library to do those comunications and ui sync or sometimes I just use a pub/sub pattern which is simpler.
Part of the bad design for me in react is that you have to think in performance all the time, by making several assumptions, like you did in the example, so you shouldn´t have to worry about, because the library and the way it work should address those issues. useMemo, useCallback, useRef, how to use context without updating several part of components tree.. etc... all these things just exists because you are stuck on React world.
But There are no such thing as silver bullet and perfect world. React does a thing that would be impossible in the way I´m proposing, which is write the same code that can be rendered in server side and its the same code that will be executed in clientside... sometimes its very convinient.. but you pay a high cost for the other 99% of the scenarios which could be fine to separete that rendering html from js logic...
You won´t be able to integrate with other template systems, server side frameworks in other languages, and have to wait for some React-like UI library because it doesn´t integrates well with vanilla UI solutions, so its about React community, not JS community... Idk... it´s been 5 years I´m working with complex apps using js without React now.. I feel like I prove empiracally for myself that those things has value, but... 99% of the times.. not necessary...and if it was, Angular, Ember, Vue, Lit, Svelte, all of them would need to use the same principles or you wouldn´t be able to build complex apps with those frameworks, which is not true..
But at this point we are in modern tech, is all about taste and marketing...Maybe Astro will lead us to a different way in the future, idk, but I like what they are doing in order to integrate the most adapted framework.. I like new things and different ideas, I feel like we are trapped in the react for a long time..
Damn man 💯
Setting the record straight - single page apps built on reusable components was a flash novelty, not a react novelty. Flash did this in the late 90's / early 00's expertly.
React started out as a great idea, but with hooks and functional components it just seems that every project I join (or write) ends up an incoherent soup. I never know when components update without reading and understanding every hook. My components are littered with memo, useCallbacks and refs. I'm mainly a React Native dev so it's important to not leak event handlers or have native code run callbacks that don't exist anymore.
I think that one really important aspect of it is how this can be ported back to react and preact, as signals did.
Preact's approach is the bets of both worlds where it keeps the vdom but encourages using signals instead of hooks, so that the vdom render typically only happens once, but it also avoids needing the component since that part can still be handled by a real VDOM (if you are memoizing DOM nodes, you have a VDOM regardless of whether or not you admit it).
I think Facebook had an extremely unique set of problems that most people don’t have. You can’t be so simple minded to think that one framework can rule it all.
I have a library that does this without a compiler :) and can be built by pure esbuild (no plugins, just pure esbuild compile speed). I named my loop component Loop and not For :D. Instead signals uses proxy to watch state changes.
Microsoft i see you.
@@internet4543 that is mathematically incorrect. To disprove your moronic statement it is enough to find at least one person that knows me and the lib.
hh,good
Great talk