Struggles with SolidJS (from a ReactJS dev perspective) #1042
Replies: 5 comments 5 replies
-
We acknowledge we are nothing like React. And I think trying to force it was basically the source of everything that happened afterward. It is difficult to even really argue against these points because they aren't wholly relevant when using Solid as intended. Rather than wasting time on the details for the moment, it might be easier to summarize your post as: "Solid makes re-rendering components really hard and inconsistent" You attempted to use Solid incorrectly and then complained that it didn't do good stuff. Half of that is on us and documentation, but the other half is on you trying to work around it. If you are interested in learning Solid in earnest I suggest just working through the tutorial for a bit. Almost everything you brought is addressed there. We wouldn't be super performant in real applications if we didn't have solutions and best practices for the things you encountered. We can do structural stuff without elements all being replaced, you can do incredibly dynamic things without re-running components. And that responsibility on the designer isn't even much of a consideration when you just use the primitives as intended since they will just behave that way. And if you have questions come by the discord. Strongly recommend it. Tons of people are willing to help. I think if we get you on the right mindset you'd be amazed how different and powerful Solid's approach is for doing exactly the type of heavily graphical stuff you are interested in. |
Beta Was this translation helpful? Give feedback.
-
Hey, thanks for checking out Solid! It's my job to improve the documentation and the onboarding experience. Your points are incredibly valuable for us as we work to rebuild our docs. And to be clear, that's how I view your points here: nothing you've laid out is a problem with the framework itself, but difficulties in teaching it. Will it be helpful to you for me to address each of these points directly? From my perspective, it makes more sense to direct you to specific resources and gather your feedback on them, because it seems like there's a more holistic gap here. Our rendering and state system work completely differently to React, and your experience and expectations from React present a block to learning Solid. Luckily, this is a block that we have a lot of experience helping people overcome. If your goal is to learn Solid, check out:
You title the post "struggles with SolidJS." I'm saddened that this has been a frustrating experience for you, and I'm committed to helping you learn the framework. That said, you also seem to be framing this as an argument. And you title your example "critics of SolidJS." If your goal is to argue against the framework, I'm afraid I've got nothing to add, but this is the kind of debate that happens regularly on our Discord in the #off-topic channel. I hope to see you there! |
Beta Was this translation helpful? Give feedback.
-
Other than what Ryan said, I want to point out that it seems like you are judging Solid mostly based on surface level mechanics. I personally think that if you don't come from React, and you have the right resources to learn Solid (the docs can still use some work IMO), Solid is way more intuitive than React. People who use vanilla JS and never used a framework (even most people who did use a framework) are much more likely to work in vanilla in an approach that is more similar to Solid, because of Solid's intuitiveness and mental model of "create direct reactivity, create a piece of DOM, hook up the reactivity to the DOM, attach to the rest of the DOM" is the most intuitive and simplest approach to doing frontend with JS. Also as for those higher level mechanics, while you might not like that a JSX expression automatically creates a reactive computation (it creates a render effect with the function createRenderEffect), the simplicity of Solid compared to the complexity of React, in combination with fine grained reactivity, creates a lot of benefits for high level mechanics as well which in practice matter more than you having to get used to Solid's compilation strategy and reactive model. Hook rules are only one example, but Solid is overall significantly more composable than React, doesn't create constant complications in your code like React does all the time, especially if you try to optimize things, and doesn't promote further complexity with the model like React does. Porting React code to Solid is often mostly about just removing React stuff that is unnecessary with Solid, cause Solid just makes you do less stuff, less fiddling around with reactivity, once you get into it, it mostly just works. It's not like React where even if you don't care about perf, the moment you start doing more complex things it just gets more and more about fighting with React. It's really hard to judge it before you learned it seriously and tried getting used to it. It's true for every framework, but for other frameworks usually it's easier to find obvious drawbacks. With Solid it's much harder, while the drawbacks you have mentioned might seem obvious to you, you are kind of assuming that the patterns don't work well in practice. You aren't really mentioning anything that is very obviously bad like bad performance, huge amount of complexity like in React, or anything that is very obviously weird like some of Vue's shananigans with quotation marks in attributes or Svelte's |
Beta Was this translation helpful? Give feedback.
-
Thanks for not hating me for what seems to be my fault of not understanding solidjs well enough. I'll try to first learn solidjs property and then rectify the problems I encountered. Thanks |
Beta Was this translation helpful? Give feedback.
-
I had two issued arousing and need some clarification on the used practices on solving them. Issue 1 (resolved):The I made a design pattern that does use the see: https://github.com/KrischnaGabriel/critics-on-solidjs/blob/main/solid-app2/src/App2.tsx Issue 2 (solved, but maybe not in a way I am supposed to)When updating a single property on a object that is accessed trough a signal, all instances where a property of that object is accessed will be updated/rerun, independent of if the used property actually changed.
When I now update just the property "a" Why would it need to work with nested objects? A parameter to a component may have subobjects, when describing complicated structures and my graphing module is one such cases. The graph can have multiple axis, multiple grids, an axis can have a label which in itself has a object defining it's layout and properties etc. All this data is best represented with nested objects. My solution to that is a selfmade hook called "createSignalObject". It takes a object and assigns signal setter and getter to each and every property (nested objects too). See App3.tsx for a simple comparison and My question is, is using this selfmade hook acceptable or is it a goddam hell spawn to which there exist a better solution/approach in SolidJS. |
Beta Was this translation helpful? Give feedback.
-
Disclaimer: I'm used to using German punctuation so sorry if this text thus reads a bit weird.
Prestory:
I started a new Project and for the front-end I wanted to try out using SolidJS, instead of ReactJS, as working with React showed some design pattern that i dislike like how hooks must be called always in the same order and I wanted to see how other frameworks / libraries check out.
The first part I started building is a graph drawing module from scratch. While creating this, I learned Solid.
All the weird issues I ran into are documented here.
Here a link to the SolidJS app and also a ReactJS app. The React app is there to compare functionality between SolidJS and ReactJS.
https://github.com/KrischnaGabriel/critics-on-solidjs
To initiate the dependencies
npm i
must be run in both apps.I will be referencing files of these apps in the upcoming points. It‘s recommended to have a IDE in split view open with the mentioned files.
Points of argument
rerunning of functions that use signals
Solid‘s documentations claim that all functions using a signal will be rerun.
(https://www.solidjs.com/docs/latest/api#createsignal)
but that is false. Only functions that provide a value to a JSX-element get updated.
Example
See /solid-app/src/test/SignalUpdates. Focus on line: 45-51
In this example the Main function uses a signals value to return a JSX component.
Upon clicking the button the signal value gets updated. Purpose is to observe if the main function gets called upon a signal update.
Relevancy in real projects & components.
Components that use the value of a signal and dynamically create, arrange and/or modify HTML-elements need to be called/rerun when the signal's value gets updated.
A example would be my graphing module, where the entire graph needs to be recalculated when the dimensions of the containing element changes (these size changes are being observed by an ResizeObserver, that calls a signals setter with the dimension values).
Result:
In the first three ways/methods of returning the elements from the Main function, the signal getter that is wrapped inside a parameter (the "children" property) of another component (a div element), will update upon a signal update.[see "incomponent"]
The first return method does not cause the function to be rerun upon a signal change.
Fair enough, (https://www.solidjs.com/docs/latest/api) defines a "tracking scope" as
A simple function call is not a JSX expression nor a hook, so it's technically compliant to the specs, but it definitely is non-intuitive.
The second return method is a JSX expression, but still the method does not get rerun.
What the hexk!
Only the third option, where the return-value of the Main function is used as the "children" value of the fragment JSX component, the function will be rerun upon a signal change.
This inconsistency is a great way to introduce bugs, caused by unexpected behavior and to ruin a persons common logic.
About the results of 4 to 6 (calling the signal getter and giving it's return-value to the Main2 function as an parameter, instead of calling the getter inside the function itself), I don't even know what I expected here.
hooks
React has some hooks that i don‘t use and don‘t know, but solid,...
i tried reading and understanding the hooks, but i had big issues understanding what they actually do and what they are useful for.
Maybe it‘s just me so don‘t take this argument too serious.
Solids not smart way of rendering & updating element constructs
React has a virtual DOM to which the new elements get compared.
Even when inserting elements ReactJS does a good job at tracking them and only updating what's needed [*see upcoming example].
Solid does an even better job which theses atomic changes from signals, EXCEPT if you need to construct complex element-structures dynamically. There, SolidJS falls face first on the ground.
When dynamically created content should be rendered (aka put onto the DOM), it does no comparisons to the existing DOM and replaces everything.
SolidJS makes the task, of optimizing to prevent unnecessary updates, the designers responsibility.
Relevancy in real projects & components.
This would not be too bad, (just results in bad performance) except that when replacing the entire DOM struct also all references to elements are cleared (as those elements are now replaced).
I encountered this in the form of a bug in my Graph module, where a ResizeObserver holded a reference to a, on the next render, not anymore existing element.
Example:
This behavior is shown in */src/test/ElementReferences by having a function that conditionally gives out different amounts of elements (as a simplified metaphor for dynamically created elements). To prove the replacement of the element, I take a reference to a element and change the innerText, after the first render. (Such practices are not recommended in both SolidJS and ReactJS. It is just to prove or disprove an override of the original element.).
Result:
In ReactJS the text of the element remains the newly set value even when rerendering the element, proving it‘s the same element. Also when changing the order of elements React keeps good track of which elements it needs to add, replace or can leave unchanged.
In SolidJS upon a rerender all elements are replaced, as if there was no attempt of optimizing the rendering process at all. Proven by that the text element gets it's initial value "blank", when a rerender occurs.
Positives about solidJS
SolidJS is really fast. When comparing the time it takes to start the app in development mode, of ReactJS and SolidJS, SolidJS with a time of under a second crushes React (about 5s).
Also when hot-reloading, SolidJS beats ReactJS greatly and also the app size of SolidJS is super small too!
But these speed and size differences are unfortunately also the only good things I can name about SolidJS.
All in all, I'll likely switch back to using ReactJS, not because it's perfect, but because it does a lot of thing right and is as such the lesser evil.
Beta Was this translation helpful? Give feedback.
All reactions