[HN Gopher] Solid.js feels like what I always wanted React to be
___________________________________________________________________
Solid.js feels like what I always wanted React to be
Author : jamghee
Score : 509 points
Date : 2022-03-01 02:26 UTC (20 hours ago)
(HTM) web link (typeofnan.dev)
(TXT) w3m dump (typeofnan.dev)
| samrocksc wrote:
| It's cool, I like this methodology a lot because it can piece
| together functionally really well.
| reactopinion wrote:
| I prefer the very explicit first React example. While I'm not a
| web dev, on a larger project with a larger team, implicit stuff
| generally makes things harder to understand and more error-prone.
| I don't see the boilerplate as a negative, I see it as
| documentation.
| alephnan wrote:
| This is the same code in Svelte.js
|
| # Counter.svelte
|
| <script> let count= 0 setInterval(() => {
| count += 1 }, 1000)
|
| </script>
|
| <div>The count is: {count}</div>
| ryansolid wrote:
| What does a reusable (ie import from another file)
| `useAutoCounter` look like in Svelte?
| alskdjflaskjdhf wrote:
| Probably the equivalent would be a custom store, something
| like this: <script> import { writable
| } from "svelte/store"; function
| autoCounter(interval, initialValue = 0) { let {
| subscribe, update } = writable(initialValue);
| setInterval(() => update((n) => n + 1), interval);
| return { subscribe } } let counter =
| autoCounter(1000); </script> <div>The
| count is: {$counter}</div>
| ryansolid wrote:
| Yep. Looks sort of like the Solid example in the article.
| It's basically my auto-response to Svelte syntax. Once you
| do anything in Svelte it is more or less the same thing.
|
| Just different priorities. In Solid you can take that code
| as is in the component and hoist it out to a function above
| and presto.. store. It's all the same thing everywhere.
| Same patterns, same usage, same building blocks. No new
| APIs, no new syntax.
|
| It is nice when first learning not to worry about Svelte
| Stores and use the convenient syntax. It is also nice to
| learn something once and use it everywhere.
| egeozcan wrote:
| I find Solid.js a "better" React as well. In a new project that
| needs to be used by a lot of team-members, however, I still chose
| React.
|
| Why? Because of the ecosystem! Do I need accessible, headless
| components? Use React-aria from Adobe! Do I need state
| management? There are many _established_ ones, I just need to
| follow their best practices. Everything supports React, every
| hire speaks React, and it works, not like "just works", but "...
| works" and, disappointing to the engineer inside me, this is not
| something I can trade in big projects.
| activitypea wrote:
| Isn't this just the Vue composition API dressed up to look like
| React? I haven't done frontend in a minute, so apologies if this
| is ignorant.
| ryansolid wrote:
| Mostly except there is no VDOM, the reactivity applies right
| down to the DOM binding. And it predates Hooks and Vue's
| Composition API.
| dkthehuman wrote:
| For anyone who wants a thorough understanding of how to think
| about React hooks in the context of things like setInterval, Dan
| Abramov wrote a great piece breaking it down in detail several
| years ago: https://overreacted.io/making-setinterval-declarative-
| with-r...
|
| This post helped hooks "click" for me, and once it did, I've
| absolutely loved them and now thoroughly enjoy writing custom
| hooks that greatly simplify my code.
| code_runner wrote:
| I just dove back into react after a while in vue and deep in some
| backend systems.
|
| I love the new ergonomics (hooks, useEffect, redux tools) but I
| definitely hit the exact issue OP mentions almost immediately.
|
| I don't feel that the solution react provides is too out there,
| but agree it could be better. The react ecosystem still makes it
| worth the one or two "could be betters" for me.
| bayesian_horse wrote:
| You may need to think about how you implement asynchronous side
| effects. Declaring them with useEffect quickly gets annoying.
| Look for things like thunks or saga. Or when not using Redux,
| at least think about using async functions.
|
| In general I want to keep async logic out of my components as
| much as possible. I also don't want the component rendering to
| drive the async logic.
| code_runner wrote:
| have you had any success using the useReducer hook totally
| outside of redux? I feel like its bulky for certain
| operations but I still haven't found that "perfect" use-case
| for it yet that makes it click for me
| prea wrote:
| I worked in React for a few years, although not enough to ever
| feel like I was an expert. This article resonated with me because
| I also got off the bus because of React hooks.
|
| I've been using Lit.js for about a year now and something about
| it just clicks. I just wish it were more mainstream.
| atom_arranger wrote:
| One of the most compelling things about Solid.js is that it
| integrates some of React's most important (IMO, probably aside
| from the central idea of UI as a function of state) ideas for
| writing applications, Suspense, ErrorBoundary, useTransition.
| prohobo wrote:
| I'm proficient with React hooks and functional components, but I
| will never bullshit anyone by pretending that they make any kind
| of intuitive sense.
|
| Classes may have been more "code" but were clear to understand. I
| don't dispute that functional components are probably more
| efficient though.
|
| Anyways, I've never had this problem with React hooks. I've been
| building complex dynamic UIs for years, and maybe I've grown to
| get around these kinds of things, but it seems like Solid.js is
| solving a niche problem at the cost of making hooks even less
| understandable?
| imtringued wrote:
| They literally don't. For some reason the developers think that
| storing state in hidden global variables (linked list indexed
| by hook call order) is a good idea. You know, they could have
| at least defined useReducer inside the class. Of course that
| would sort of break the pretentious ability to define hooks as
| global functions that access component state. After all, you
| would have to pass the current component as the first
| parameter, imagine the horror!
| valtism wrote:
| I've used React for ~3 years, primarily with function components
| and hooks. I think that hooks were a wonderful addition and I
| think the framework has made smart choices with checking object
| equality to decided if components re-render.
|
| That said, I think that easily the most difficult aspects of
| react revolve around how re-renders are triggered. Maintaining
| referential equality to stop unnecessary renders gets tricky when
| you are passing functions or objects. Suddenly you need to be
| using `useMemo` and `useCallback` and passing dependency lists
| that all have to be primitive values unless you want to memoize
| them as well. It can become such a headache that the official
| line around it mostly seems to be "make the render fast, don't
| worry about unnecessary re-renders" - good advice, until you hit
| a use-case where you need to worry.
|
| Solid takes these problems and just vanishes them. UI state knows
| what its dependencies are automatically and only updates when
| they change - even in a sub-component level!
|
| To be fair, I've never used Solid in anger, and moving to it
| would be a big ask when there is such a good ecosystem built up
| around react. That said it is easily one of the most exciting
| projects on my radar, and the developer Ryan Carniato seems
| extremely knowledgeable in the area.
| emerongi wrote:
| Agreed, after 6 years of use, my gripes with React come down to
| the re-rendering and lack of syntactic sugar for commonly used
| things. Hooks can get messy, but complicated components were
| complicated even with the class syntax.
|
| What React has going for it, is that it is predictable. That is
| an extremely important part of any tool.
| brundolf wrote:
| > Solid takes these problems and just vanishes them. UI state
| knows what its dependencies are automatically and only updates
| when they change - even in a sub-component level!
|
| I haven't looked at Solid but I've used MobX extensively, and
| this sounds a whole lot like it. It integrates well with React,
| so you might give it a look if you've got an existing React
| codebase.
| branko_d wrote:
| I second that! MobX + React is a good way to scale your
| codebase, not just performance-wise, but understanding-wise
| as well!
| stocknoob wrote:
| For the other Americans, "used xyz in anger" means "used xyz in
| production".
|
| https://english.stackexchange.com/questions/30939/is-used-in...
| LAC-Tech wrote:
| Weird. I'm not British by I say "used xyz in anger" because I
| read lots of other programmers saying it. Had no idea it was
| regional, thought it was hacker lingo like "grok".
| madeofpalk wrote:
| Australian living in England as a dev for 5 years. Never
| heard of "used in anger" in any context. Weird.
| branko_d wrote:
| Serbian living in Kazakhstan as a dad for the last 4
| years. Heard it plenty of times before, but never in the
| context of computer programming. Weird. :)
| josephg wrote:
| Australian living in Australia for most of my life. I've
| heard "used in anger" lots of times. I can't remember
| when, or by whom. But its certainly a thing I've heard
| people say here.
| Tade0 wrote:
| I'm not an English native speaker and today I learned that
| I misinterpreted a lot of what was said to me in the past.
| marcus_holmes wrote:
| Had to explain "used in anger" to my German gf last week, as
| her boss had used it and she was confused about why he was
| angry with her code. It's surprisingly hard to explain the
| nuances of it.
| mst wrote:
| Speaking as a british programmer, if a given piece of
| software hasn't made me yell expletives at the screen at
| least once, I probably haven't done something sufficiently
| non-trivial with it to count as "used in production" yet.
|
| But then again even by british standards I am unusually
| sweary when writing code.
| throwamon wrote:
| I always assumed it was something like "I got so angry with a
| certain solution that I gave in and tried this other one".
| lgvld wrote:
| Thank you! ;-)
| [deleted]
| bayesian_horse wrote:
| Use `reselect`!
| tempouser23 wrote:
| "UI state knows what its dependencies are automatically and
| only updates when they change" - you should check out
| [valtio](https://github.com/pmndrs/valtio).
| ryansolid wrote:
| There are a lot of React state libraries that do similar
| things with Proxies. I think the part that is not as
| emphasized is how that reactivity extends to the view.
| Instead of re-rendering components it uses that knowledge to
| directly update portions of the DOM. So while MobX, Valtio,
| Jotai, Recoil etc localize change in React, they still feed
| into the whole VDOM React cycle, instead of just updating
| exactly what changes. It's not a characteristic of these
| libraries but the fact they feed into React.
| tempouser23 wrote:
| Though you can use smaller components to minimize the
| changes. Valtio i feel is one of the simplest of those. But
| yes they are no way compared to solidjs. Of the numerous
| frameworks in recent years solidjs has the only which has
| interested me to pick up and use it. Though still not in
| production.
| mst wrote:
| Solid very much seems like "what would happen if somebody
| took the way I usually combine react + mobx and built
| something designed for that from the ground up".
|
| The only thing it doesn't obviously do better is the JSON
| Patch generation stuff that I get from mobx-state-tree and
| I use the word obviously because it would not at all to
| surprise me to discover that solid already does that and I
| simply didn't RTFM hard enough yet.
|
| The sheer level of ecosystem (and the "nobody ever got
| fired for" advantage that results) may keep me using react
| but solid is a bloody impressive piece of kit and whether I
| ever end up using it myself or not, "bravo, sir" applies.
| parhamn wrote:
| If theres one React recommendation I'd make is: use Mobx.
| darepublic wrote:
| I'm used to react and hooks,and right now I can't do any better.
| Doesn't mean I like it. The solid example here seems to have a
| similar complexity and implicit knowledge as hooks just a
| slightly different syntax
| rglover wrote:
| There's light at the end of the tunnel. Don't fret, traveller:
| https://github.com/cheatcode/joystick.
| simon83 wrote:
| I've been using React since around 2016 and when Hooks were
| introduced I played around with it but didn't like it at all
| exactly because of the reasons mentioned in this article. Sure it
| reduced quite a bit of boilerplate code that came with class
| based components and enabled better code re-usability outside of
| class inheritance or mixins but the disadvantages were too big
| for me personally to really consider using Hooks in a
| "greenfield" setting.
|
| In my current project I'm using Vue with Composition API which
| gave me the exact same "aha" moment the author of this article
| had with SolidJS. Vue + Composition API is way more similar to
| SolidJS in principle than React + Hooks.
| mst wrote:
| Pure function components in React with MobX for state
| management rather than the hooks system has worked out quite
| well for me.
|
| I do, however, keep finding myself wondering about jumping to
| Vue and VueX instead.
|
| Ask me in five years, I guess.
| preommr wrote:
| I swear we're just going around in circles because people only
| have a surface level understanding of these front-end frameworks,
| and the challenges with building at scale.
|
| react isn't about 'hooks', 'jsx', 'top-down-state', or
| 'component-driven architecture'. All these frameworks are
| component-based, can have top down state only (or do bottom up in
| react), can use things like jsx/hooks because it's just syntactic
| sugar (vue has jsx support).
|
| react is fundamentally about 'inputs changed, render this'. This
| got rid of a lot of issues with poor code because frameworks had
| crappy DX (angluar 1 scope nonsense, and overengineered DI
| concepts), and people were bad at tracking side effects because a
| lot of people just wanted a search bar with some cool features
| and not everyone was building sophisticated products.
|
| That setInterval example is fundamentally against what react is,
| and is basically svelte/vue/(react + mobx).
| ricardobeat wrote:
| That's not completely correct. React is, and has been from the
| start, a UI rendering library. Its fundamentals are component
| abstractions, the component tree, lifecycle, the virtual DOM.
| We had other declarative frameworks before React (Ractive.js,
| svelte's spiritual grandfather, being the most popular one).
|
| The 'inputs changed, render this' paradigm (and by this I mean
| reactivity, not the declarative model) has been around for much
| longer and is exactly what this post is about - React doesn't
| really do that, since it relies on _you_ to explicitly tell it,
| via dependency arrays or setState calls, when to re-render. It
| is not fundamentally different from `.on( 'change',
| this.render)` code we were writing back in 2010, just a lot of
| syntax sugar on top.
|
| That React managed to sell itself so well, while not actually
| delivering on the reactivity or performance promises, is the
| surprising part. I'm excited for the future as we finally move
| on from this era.
| mst wrote:
| Hrm.
|
| "React as Schelling Point" ?
| KronisLV wrote:
| > All these frameworks are component-based, can have top down
| state only (or do bottom up in react), can use things like
| jsx/hooks because it's just syntactic sugar (vue has jsx
| support).
|
| Honestly, the boon of React is just how easy it is to create
| components, or at least how simple things were back in the day
| - it is exceedingly _composable_ , moreso than AngularJS,
| Angular or Vue have been, at least in my experience. In React,
| your component can fit within a single file, containing simple
| syntax, especially for when you're making a pure functional
| component with no side effects or hooks. And even when you need
| to add something more complicated, you just have a method or
| two to change, essentially "progressive enhancement" for your
| code.
|
| Though admittedly state management, or at least our current
| approaches to it ruin everything with endless boilerplate
| (Redux, Vuex etc.) to address an issue that may or may not be
| easier to represent, though some libraries certainly try (MobX
| comes to mind).
|
| Of course, my experience leads me to agree with the article, in
| how React in combination of hooks sometimes is problematic,
| although in my case that was primarily because of render loops
| and how the stack traces are akin to JDK 8
| NullPointerExceptions, where you couldn't see exactly what's
| causing you problems:
| https://blog.kronis.dev/everything%20is%20broken/modern-reac...
|
| I'm probably wrong in liking class based components since those
| have other issues and Vue/Angular both feel a bit less
| productive in comparison, even if sometimes easier to reason
| about, with different tradeoffs to them. Maybe i should check
| out Svelte some day, but i guess it's all just one long slog of
| finding what works for you and what doesn't, much like it is
| with back end programming languages or even relational DBMSes.
| cehrlich wrote:
| Zustand has solved the complexity of state management for me,
| although getting {employer} to adopt it is of course a
| different problem altogether.
|
| It's really bizarre to me how poorly useContext works, in
| contrast to how good everything else in React is for the most
| part. Having a good, "official" global state management
| solution that requires little boilerplate would be a huge
| benefit.
| mst wrote:
| I am currently most fond of mobx / mobx-state-tree which is
| a substantially different style but I am very much
| impressed by zustand as "take the redux style and do it
| really well".
|
| There are enough different takes on how to state management
| that I am ... ambivalent ... about whether having a single
| official solution would in practice be better than the
| current situation. It's inevitably going to be a trade off
| and the react team not wanting to pull the trigger on such
| a thing until they're -really- sure is probably a good
| thing overall.
|
| As a side note: I agree that useContext is weird, but
| jamming what (at least according to the mental model I use
| when working with it) is dynamic scoping into a language
| without native dynamic scope is probably always going to be
| at least somewhat weird.
| ConsoleTVs wrote:
| Wait till you realize Zustand does not work on React 18's
| Concurrent Mode and istead must use Jotai (same author) ?
| cehrlich wrote:
| Zustand 4 already works with Concurrent Mode. Still in
| beta, but so is React 18.
| VaxWithSex wrote:
| I enjoy React+MobX with class-based components, because they
| are nearly as nice as Seaside was, back in the day!
| branko_d wrote:
| > In React, your component can fit within a single file
|
| Furthermore, a lambda local to a function can be a full-blown
| component (visible in DevTools etc.).
|
| So if you need a component that is used in only one other
| component, you can neatly encapsulate it and make it
| invisible from the outside, which can be useful on occasion.
| rk06 wrote:
| The thing is that While react is against side effects,
| javascript is not. Which result in these impedance mismatch
| where what devs want is against react itself.
|
| Vue/svelte/solid do not fight against js, hence they do not end
| up in similar situation
| riwsky wrote:
| React lets you build DOM with normal JavaScript loops and
| .map; solid requires its own For element. How do you define
| "does not fight against js"? Because the above feels likes
| solid fighting against js.
| peferron wrote:
| Fully agree.
|
| With React, "plain JS" works just like I expect it to. If I
| have an event handler that does `x = foo` then I don't
| expect my component to re-render. Why should it? I'm just
| changing the value of a local variable. If I want to re-
| render, there's no way to express that in plain JS, so I'll
| use React's API and write `setX(foo)` instead. Now it's
| clear that it's not just changing the value of a local
| variable, but using React's API to do something else.
|
| With Svelte, writing `x = foo` doesn't just change the
| value of a local variable. Maybe it's going to run a bunch
| of magic to update a piece of the DOM instead. Or maybe I
| need to prefix it with `$: ` which in plain JS is a label
| for a continue or break statement, but here doesn't mean
| that at all and means reactivity instead.
|
| Oh, and to conditionally render an element, instead of
| writing idiomatic JS like `condition && <Element />`, I now
| have to write `{#if condition} <Element /> {/if}`.
|
| WTF. What looks like plain JS is now magic, and what
| _should_ look like plain JS such as conditional rendering
| and lists are now some contrived templating constructs.
|
| And almost everyone here is telling me that I should find
| that simpler somehow.
|
| It makes zero sense.
| egeozcan wrote:
| Sorry for the "+1" chain but I want to express my
| agreement as well.
|
| Especially when I compare it to Svelte and Vue (not
| solid, solid.js is just... good), if I look at a
| component, with react it's way easier to say what's going
| to happen.
|
| Aren't there gotchas? Yes, but sometimes it's just stuff
| JS lacks, and so does React.
|
| I'm very excited about Records and Tuples in JS to help
| with the immutability, for example:
| https://github.com/tc39/proposal-record-tuple
| benatkin wrote:
| Don't forget about having to pass _key_ to each element in
| React. The simplicity of using map() is an illusion.
|
| SolidJS splits it between <For> and <Index>. <For> is
| equivalent to passing the object as the key and <Index> is
| equivalent to passing the index as the key.
|
| https://www.solidjs.com/tutorial/flow_for
| https://www.solidjs.com/tutorial/flow_index
| ihateolives wrote:
| > Don't forget about having to pass key to each element
| in React. The simplicity of using map() is an illusion.
|
| That's one of the design decisions I don't fully
| understand. It knows that there should be a key there so
| why just not put it there silently and let me override it
| when I need, instead of screaming at me when I omit it.
| yazaddaruvala wrote:
| It's a performance pitfall. The warning is trying to make
| sure the dev correctly tells it how to and when not to
| re-render.
|
| Could it silence the warning? Yes. However, the React
| devs choose not to. I think it's the correct default, but
| likely needs a more educational warning message.
| wonnage wrote:
| The purpose is well-documented here:
| https://reactjs.org/docs/reconciliation.html#recursing-
| on-ch...
|
| And it also goes into why index is a poor key (it's
| basically the same behavior as with no key).
|
| Using object identity to detect inserts doesn't work
| either, because the map function is returning new React
| element objects on each render.
|
| Practically speaking if you know your items won't change,
| then omitting the key or using index is fine.
| ihateolives wrote:
| I know, I've read it. I'm still not convinced. React
| could just as well generate and insert missing key on
| build instead of asking me to do this:
|
| _... you can add a new ID property to your model or hash
| some parts of the content to generate a key._
|
| It is just plain wrong to ask me to change my data model
| because of this. This is part of the housekeeping that I
| expect the framework -- pardon, library -- to take care
| of for me.
| ryansolid wrote:
| It can't. Not in a consistent manner. When diffing user
| provided immutable data you need a user provided key.
| Otherwise it can't tell the difference between a new list
| entry and a nested update. You could treat every nested
| update as a new item but that is incredibly wasteful as
| it throws away all descendants. This is something all
| non-fine-grained rendering libraries have to deal with be
| it React, Vue, Svelte, or Lit.
| mwcampbell wrote:
| How does Solid avoid the need for user-provided keys? I
| thought it also had to diff the underlying array. Does it
| check object identity?
| [deleted]
| ryansolid wrote:
| It does. Just referential check. Our reactivity is nested
| and we don't want blow out everything so even though
| there is read/write segregation and immutable interfaces
| the internals are mutable. In so sorting looks at
| referential equality, and nested updates don't even
| trigger list diffing.
|
| Now this does require special process for intaking
| immutable or big data snapshots where we can't do
| reference comparison. So we do have a data diffing
| capability in our nested reactive stores to propagate
| only what changes. But for the most part common actions
| like partial updates highly optimized. As well as simple
| list operations like sorting.
| benatkin wrote:
| So SolidJS has this solved elegantly? It lets you choose
| between object identity and index, and it doesn't have
| that caveat for object identity because it knows what's
| going into <For> and not just what's coming out of it.
|
| Don't omit the key in React unless you want warnings.
| intrnl wrote:
| i'm finding a hard time articulating what you said, if React
| is against side effects then useEffect wouldn't have existed
| and we wouldn't have data fetching.
|
| React is unique in that everything in the component is within
| the render path, while the rest of the frameworks (that
| you've mentioned) doesn't.
|
| you might be mistaking "side effects during render is bad"
| for "side effects is bad", the two statements are not the
| same.
| rk06 wrote:
| I mean side effects from a functional point of view. Let me
| explain in more details
|
| React's philosophy is View = F(data)
|
| I.e. view is a pure function of data. By "pure", we mean
| F() does not do console.log, ajax calls, date time and
| other stuff which is not consistent every where.
|
| This assumption is ingrained in React. You see it when you
| are told that react can overrender and your code should
| handle overrendering. And react works well when user code
| is pure. However, real world does not work that way. So,
| there is a need to handle side effects, so that "side
| effects" works well with pure function assumption of react.
| This "handling of side effects" is the over head introduced
| by react.
|
| Other js frameworks (svelte, solid, vue) do not assume full
| immutability or pure functions, hence User code does not
| need special handling for these cases
| benatkin wrote:
| > View = F(data)
|
| That's just how templates are meant to work.
| Underscore.js templates don't allow making an AJAX call
| before calling render() either.
| https://underscorejs.org/#template
| rk06 wrote:
| Consider following scenario:
|
| User is entering an account register form. When the user
| has entered a value in nickname, your app must check if
| it is in use and display error message if the nickname is
| already in use.
|
| Sounds good, and ubiquitous right? Well, that also
| require an ajax call to server for validation, so it
| breaks the pure function assumption right there. Now, you
| what do you do?
| kevinmcconnell wrote:
| > so it breaks the pure function assumption right there
|
| There's no pure function assumption being broken here.
| React is a framework for rendering UI from state _and_
| coordinating updates to that state. That 's why we have
| things like `useEffect`, contexts, and so on. The only
| part of React that is expected to be free of side effects
| is rendering.
|
| Put another way, given your example, React just says that
| you shouldn't issue your Ajax call in your rendering
| code. Instead, you should do it in response to an
| appropriate action, such as a change event on your form
| controls.
| benatkin wrote:
| The template's render function doesn't make the AJAX call
| - not in React, and not in Underscore templates.
|
| When you display the error message, yes, React provides a
| way to do that without re-rendering the input box and
| while keeping the contents, but many react devs are
| skipping the traditional React way of doing that and
| using react-hook-form instead.
|
| I get what you're saying about the component's data
| updating the state of the DOM in a way that resembles
| pure functions, but I think AngularJS did it before
| React, and that Backbone was not far from this vision.
| Certainly there are a zillion JavaScript frameworks that
| do this now, and only React has you jumping through silly
| hoops like "className" and "htmlFor".
| https://preactjs.com/guide/v10/differences-to-react/#raw-
| htm...
| https://www.solidjs.com/tutorial/bindings_classlist
| LAC-Tech wrote:
| > React's philosophy is View = F(data)
|
| Yeah internal component state throws all of that out the
| window.
|
| That's lit-htmls philosophy, not react. React is all
| about bundling the view and state and then marathon
| profiling sessions to figure out why everything is re-
| rendering all the time.
| toomanydoubts wrote:
| I fail to see the purity in react with all that useState,
| which obviously by the name is tracking state outside the
| scope of the function(eg: it's actually View = F() and
| data is coming from outside when calling useState). It's
| not pure at all. I really would like to see something
| more akin to Elm, where all your state is explicitly
| passed into the component, and you have commands that
| update state and trigger the view again, making it
| actually "functional". I guess this takes the form of
| redux in react, but I'd like to see it ingrained in the
| components themselves.
| imtringued wrote:
| Yes it's var View = F() and var
| hidden_global_variables_for_hooks;
| MiddleMan5 wrote:
| Slightly dismissive, but I agree the setInterval function was a
| little misleadingly contrived.
|
| The transition to functional components was to reduce the
| coupling between abstract functionality and DOM-related
| lifecycle events.
|
| React hooks are mostly about expressing where and when you want
| to memoize a value, with the default being not to.
|
| Once you learn what to look out for, and properly designing and
| review codebases at scale, these trivial issues don't happen
| all that often. Additionally, being able to specify memoization
| parameters explicitly brings extra flexibility and some
| additional design patterns.
| stupidcar wrote:
| What are you talking about? The setInterval example is
| completely idiomatic React hooks. It is literally given in
| the React docs:
|
| https://reactjs.org/docs/hooks-faq.html#what-can-i-do-if-
| my-...
| MiddleMan5 wrote:
| Reading it now, the language I used was inappropriate.
| You're correct, the stated problem is common with
| registering and triggering self-repeating and timed loops.
|
| That was really my point, don't do that.
| jimmont wrote:
| This is about "feels like" and me too--the little newsletter
| popup and lack of substance shows this. React became obsolete
| over the past few years as browsers increasingly adopted the
| mix of web components features (eg componentDidMount vs
| connectedCallback). Just using React, and the explanations for
| why a technology is and isn't used in an organization speaks to
| the level of practical knowledge and detritus in projects. That
| products survive this long with React illuminates how resistant
| the community is to... reading and doing work in the easiest,
| pragmatic way possible. Like why bother writing an article like
| this?
| toqy wrote:
| I've been maintaining a web component library with Lit for a
| while. Web components overall don't feel ready for primetime.
| Just making a custom input field and have it work with a
| <form> is chore.
|
| Just look here at how much overall code is needed to do it
| right: https://github.com/ing-
| bank/lion/blob/master/packages/input/...
|
| After you get through all the inheritance and mixins it's
| thousands of lines
| jimmont wrote:
| I only have this generalized experience to respond with (at
| the moment): For the private project i work on full-time,
| the few dependencies related to ING and Lion were the most
| problematic and the first to get ripped out. I have no idea
| about the specifics of your dependency, and will not review
| the work you're mentioning in detail. However, ING, based
| on my limited experience, is nothing to base any
| assumptions on. Based on my limited experience, ING and
| Lion appear to be distinctly inferior examples of work done
| with Lit and web components. That was my first and last
| time working with anything Lion and ING related.
| toqy wrote:
| That's just one example, and the issues with form
| associated components are not limited to ING. The
| Microsoft FAST form components also have a fuck ton of
| code to achieve what <label> + <input> can do in any non-
| webcomponent framework.
|
| There are proposals for this and most of the other issues
| I have with web components. But they all feel like issues
| that could have been covered from the beginning.
|
| Also if you go all Lit on an app with many nested shadow
| doms it becomes fairly painful to test with tools like
| cypress.
| JoeyJoJoJr wrote:
| That is a big call regarding web components. I did some
| looking into web components for a recent project and React is
| just way ahead in many areas. You could use a framework like
| Lit to help smooth things over, but that just speaks to the
| underlying standard being somewhat cumbersome to use. I
| totally want web components to succeed and be the new way of
| doing things, but I get the feeling that is still a while
| away.
| spankalee wrote:
| I think calling web components "cumbersome" belies the
| intention of the APIs, which is to enable custom HTML
| elements, encapsulation, and interop - fairly low-level
| concerns.
|
| Lit takes care of templating and reactivity. Web components
| don't have those, it's expected that you use other methods,
| including what you already use, to create DOM and react to
| state changes.
|
| The DOM may eventually add templating and reactivity, but
| that's a pretty big question given how many approaches and
| syntaxes there are. Until then libraries are fine and allow
| for multiple opinions.
| jimmont wrote:
| Only a clarifying point to add about Lit: tagged
| templates provide templating and have native support, all
| Lit does is provide API extensions for reactivity, ie
| state management. So when a portion of a template is
| associated with an object, only that part is updated due
| to how the libraries work. And this is fundamentally all
| the it provides (unless I've misunderstood something).
| Lit-html provides functional state+template views while
| LitElement provides the OO/class oriented lifecycle
| approach--collectively now rebranded as "Lit".
| https://lit.dev/ Please call out corrections as needed.
| jimmont wrote:
| Big call? I suppose there's a point where having done
| enough work in projects affords some perspective. Whenever
| anyone gets the feeling to do something else the docs will
| probably be there, as they were the past few years.
| drewcoo wrote:
| > react is fundamentally about 'inputs changed, render this'.
|
| The actual article acknowledges that when it's read: "React
| isn't truly reactive."
|
| And the author also claims to love React and to think it made
| things better.
|
| You're arguing with phantoms.
| seanmcdirmid wrote:
| React was about bringing a more immediate mode UI programming
| model to the web, as opposed to retained UI programming models
| are a PITA to work with. Retained doesn't work well in games,
| it doesn't work for productive UIs either.
| [deleted]
| mst wrote:
| The original angular worked perfectly for me, but that's
| because I loaded the source code onto my tablet and read the
| entire thing top to bottom over a few evenings in a pub beer
| garden with a cigarette and a pint to keep me company.
|
| Newer frameworks are absolutely better for anybody who isn't
| sufficiently batshit enough to do that, but much though I enjoy
| react + mobx (especially react + mobx-state-tree) I've never
| got to the "I have the core source code in my head and can
| mentally dry run it as a desk check type operation when
| debugging" stage with them like I did with early angular so -
| with the level of jank inherent in its scope nonsense entirely
| acknowledged - I still occasionally miss it even so.
|
| (this is mostly me being nostalgic, I think, the newer stuff is
| absolutely better but that was a fun few evenings and for its
| era damn but I could make that thing sing)
| lhorie wrote:
| > react is fundamentally about 'inputs changed, render this'
|
| I mean, pretty much all frameworks these days have that
| fundamental declarative model, react wasn't particularly
| innovative on that front (e.g. the declarative model already
| existed in angular, knockout, etc)
|
| What the setInterval example highlights is that newer
| subsystems in React like useEffect and Suspense are bolted on
| top of earlier iterations that weren't originally designed to
| support these kinds of semantics, and the dissonance between
| API design iterations has become noticeable. This is a pain
| point that is relatively unique to React.
|
| The growing popularity of Svelte and Solid are largely because
| their API designs align naturally with how people expect
| features to work, without people falling into pits of failure
| like stale closures and incorrectly wired dependencies. React
| is popular and it puts bread on your table and all, but
| pretending it doesn't have warts doesn't do anybody any favors.
| DougBTX wrote:
| > react wasn't particularly innovative on that front (e.g.
| the declarative model already existed in angular, knockout,
| etc)
|
| React was absolutely a breath of fresh air when it was
| released.
|
| Knockout was similar to Solid.js in that they both have
| functions that you call which then log a data dependency,
| then when the data changes the UI updates. This led to lots
| of pain, because instead of a plain value, you have functions
| which return values, and you need to be very careful about
| when those functions are called, otherwise the data
| dependency might not be tracked properly.
|
| Angular had a similar issue, as its state-based observation
| relied on special scopes. Updates in the wrong scope could be
| lost or delayed.
|
| React's approach of only diffing the rendered UI rather than
| trying to drive updates based on diffs of the input data was
| vastly simpler, it was much easier to understand the data
| flow through explicit state and props.
| lhorie wrote:
| React also requires that you call functions to trigger
| rendering (be it via setState or `[, setFoo] = useState()`)
| and it definitely has warts that trip people up too (e.g.
| semantics of calling setState twice synchronously). The
| dependencies array in useEffect is also conceptually the
| same mechanism you claim causes pain in Knockout.
|
| IMHO, historically, the bigger pain point with the reactive
| model was data marshaling/unmarshaling (e.g. updating some
| subtree of data and then needing to send the root of the
| data tree to the server while maintaining reactive bindings
| across a large app and being careful not to fragment source
| of truth). Ironically, React can also end up in this
| predicament, because the encapsulation model of its `state`
| mechanism means extracting the actual state of the
| component tree is non trivial unless you're using a third
| party state lib to avoid it altogether in the first place,
| or at least use useReducer, which is a relatively new
| addition to React (and even then, it's kinda jank).
|
| These days, React is a hodge podge of many different
| implementation approaches. Yes, there are props, but
| Context also exists - and is used extensively in the wild -
| precisely because props get clunky, and then there's data
| diffing happening to support `memo`, on top of the virtual
| dom change tracking. Suspense basically requires _your_
| code to adhere to semantic restrictions, i.e. you 're not
| even in control of _when_ your component function is
| called, which leads to having to tip-toe around that scope
| w / extra closures, which in turn leads to all the issues
| that the article touches on.
|
| The hodge podge issue isn't specific to React; Vue is also
| seeing pain points from having so many ways of doing things
| now that they're trying to push a v3 and realizing
| ecosystems tend to slog.
|
| To your point, yes React _was_ relatively simple when it
| came out, but as I mentioned, it wasn 't the first to take
| a stab at the declarative model, nor the simplest. It just
| benefited greatly from the popularity wave of the golden
| years of Facebook OSS engineering. And from a practical
| perspective, it doesn't really matter what React was.
| Idiomatic usage is a thing, and React development today
| isn't like React development 7 years ago.
| ricardobeat wrote:
| We also had ractive.js, we had mithril, intercooler.js (now
| htmx), we even had (fab).js as far back as 2010 with
| functional rendering. A 'breath of fresh air' pretty much
| depends on what you had been breathing.
| mst wrote:
| React wasn't exactly innovative as such so much as it was
| a very carefully designed (I don't mean they didn't make
| mistakes, mind, only that they clearly put effort into
| making new and exciting mistakes) implementation of the
| model that successfully broke into the mainstream.
|
| The phrase "an idea whose time had come" springs to mind.
|
| (this comment is intended to read as professional
| respect, not fanboying - the extent to which I succeeded
| in that intension must inevitably be left as an exercise
| for the reader)
| [deleted]
| joeyjojo wrote:
| This is just iteration on the awesome groundwork that React
| laid, and shows that things can still be much better. React has
| some very peculiar patterns that don't really jive well with
| javascript as a language, or its ecosystem. If the setInterval
| example is fundamentally against what React is, then IMO that
| really hammers the point the author is making. I have a few
| React projects under my belt, and often times still find myself
| confused by hooks or the mess that I create when I use them.
| bryanrasmussen wrote:
| In my personal opinion when there is a lot of complicated
| state in a component and there is no real benefit to
| splitting it up into smaller components then hooks are
| inferior to the older lifecycle methods (in creating
| understandable, maintainable code), however in my experience
| whenever I come to place nowadays this would be considered
| heresy and everything needs to be in hooks even if you have
| 10+ and growing number of hooks to make everything hang
| together.
| progrus wrote:
| "Long lists of generic hooks" is a symptom of devs not
| having climbed the difficulty curve a bit further, to where
| they are writing custom hooks, and using fewer in each
| component, IMO.
|
| It's understandable to stumble into this difficulty though,
| and a bit of deceptive marketing on the part of the hooks
| folks. They should be upfront that using hooks well in a
| real app requires a lot of careful thinking of the kind
| that many "typical" programmers do not have much practice
| in, and then the maintenance of whatever code comes from
| the effort. The functional-programming-mindshare situation
| seems to be improving slowly, but still.
| seer wrote:
| Maybe, but in my experience whenever I encounter an
| incomprehensible mess of hooks it usually ends up because
| devs were not using all the tools that react provides.
|
| For example a flurry of setStates could be wrapped up in
| one single state. If it gets too complex - into a reducer.
|
| Components that don't benefit much from splitting up could
| have their business logic wrapped into a context, and let
| the view code be just jsx without all the interweaving of
| code and templates.
|
| Maybe the one benefit of classes was like it forced you to
| think in business logic, then render. React still has that,
| you just need to dive a bit deeper into its toolbox.
|
| The result usually turns out much more flexible - contexts
| neatly wrap business logic for all of its descendants,
| classes don't.
|
| I think this was maybe because react actually allows you to
| write messy code, and it's still performant and works. But
| in the end it just kinda postpones the inevitable
| maintenance burden.
|
| I guess solid.js from the looks of it might postpone it a
| bit more. I just worry that solid looks more like magic,
| and some invariant somewhere will just break and I wouldn't
| know what sequence of reactions actually led to that
| infinite loop that crashed the page. Haven't tried it
| myself though, might more understandable in the end...
| ricardobeat wrote:
| > For example a flurry of setStates could be wrapped up
| in one single state. If it gets too complex - into a
| reducer
|
| You've just deoptimized your app, and your whole
| component will re-render on every change.
|
| > Components that don't benefit much from splitting up
| could have their business logic wrapped into a context
|
| You did it again. More unnecessary re-renders.
|
| > it's still performant and works
|
| True that 'it works', but it's usually not as performant
| as you think - we just have really fast computers and
| phones now.
| littlecranky67 wrote:
| Why is performance always argument No. 1? The true rule
| is, code must be readable and maintainable first. THEN,
| if there are performance issue with the code (no
| theoretical ones, you HAVE to have a real-world profiling
| report of YOUR code in your hands when you argue about
| performance), you can refactor for performance.
| ricardobeat wrote:
| That's a straw man argument - I did not say it's concern
| #1, just pointing out that React forces that specific
| trade-off. Balancing complexity, maintainability, AND
| performance is really hard with hooks, the lack of built-
| in reactivity and inefficient baseline behaviour. It's
| rarely a matter of "just combine it into one reducer".
|
| On top of that, profiling and optimizing a real world
| application with a dozen hooks in every component is
| pretty painful.
| mst wrote:
| A thing I remind myself of regularly: Avoiding worrying
| about optimisation up front too much is not avoiding
| caring about optimisation at all, it's reserving the
| number of hours you can expend on optimisation until you
| have enough working to have a profile available, because
| you are inevitably going to be wrong about which part is
| actually slow until that point so your optimisation hours
| budget will be better spent with a profile in hand.
|
| There's a parallel here to "no, you did not find a bug in
| the compiler". Yes, ok, once every five years or so I
| actually did find a bug in the compiler, but assuming you
| aren't that smart is still a far far better default
| approach.
| imtringued wrote:
| >You've just deoptimized your app, and your whole
| component will re-render on every change.
|
| If you have 3 useState each of those will use 3
| useReducer internally (every hook is implemented on top
| of useReducer), If you consolidate them into one
| useReducer then you will end up with the same thing
| performance wise. Maybe even better. Whenever an event is
| pushed into the hook's queue it marks the component as
| dirty. The next call to useReducer will then reduce all
| unprocessed events into the current state. It's entirely
| possible that having less hooks and therefore less
| metadata in the background can improve performance more
| than avoiding the theoretical cost of rerendering a
| component that most likely would have to be rerendered
| anyway.
| jsmith45 wrote:
| Not all hooks are implemented in terms of reducers.
| `useMemo`, `useCallback`, `useRef` for example are not
| based on reducers, (or effects). Obviously the effect
| hooks are based on effects not reducers, and some like `
| useDeferredValue` are based on both.
|
| But you certainly are correct that useState is reducer
| based. I'm pretty sure one is only avoiding rerender via
| using multiple `useState` if they don't implement the
| reducer in a way where it returns the original object
| when there was no net change. If you are able to
| implement the such that it only returns a new object when
| there really is a change, then a single useReducer call
| is strictly more efficient than multiple useStates. (This
| might require more complicated code, as returning a new
| object every time is often the easy way to implement
| reducers.)
| Scarblac wrote:
| When you have multiple hooks in a component it usually
| makes sense to put them in a function with a good name - a
| custom hook. It's easy and almost always usually gives
| simple code.
| dnsco wrote:
| a benefit of custom hooks is that you can test complex
| state logic isolated from the view
| bryanrasmussen wrote:
| sure, and sometimes it still would be simpler with the
| older lifecycle methods. Not saying it is always the case
| but for some reason it is assumed it could never be the
| case.
| onion2k wrote:
| _hooks are inferior to the older lifecycle methods (in
| creating understandable, maintainable code)_
|
| If the lifecycle methods you're referring to are things
| like componentWillReceiveProps or getDerivedStateFromProps
| then the React blog covers why they were problematic
| https://reactjs.org/blog/2018/06/07/you-probably-dont-
| need-d.... It was _very_ common for developers to make
| things that would repeatedly rerender when other parts of
| their app updated. Hooks make that far less likely to
| happen.
|
| That said, I agree that a getDerivedStateFromProps method
| is more readable and much clearer than useEffect(()=>{ //
| stuff }, [big, list, of, props]);
| bryanrasmussen wrote:
| that a particular way of doing things was problematic for
| the community as a whole when measured across all usages
| does not invalidate the observation that there were some
| usages in which that particular way seemed better.
|
| when, as I often encounter, organizations mandate all
| hooks all the time they are not throwing the baby out
| with the bathwater, but they are maybe throwing out the
| baby's rubber duckie without considering that might be
| useful to have around at times.
| pjmlp wrote:
| I keep my sanity by ignoring all of them, focusing on mastering
| pure Web standards only, and delving into such frameworks only
| when I am required to collaborate with Web FE devs.
| norman784 wrote:
| I recently started to look at native web components (custom
| elements), at first I thought I could replace {insert your
| framework here} with it, but it seems that it doesn't solve
| the issue, you still need some kind of framework built on top
| of it to achieve the same goal.
|
| If you have some recommendations or want to share your
| experience with working only with web standards I want to
| read them :)
| pjmlp wrote:
| Easy, Java and .NET SSR frameworks (which support
| components for two decades now), + vanilaJS for Ajax like
| behaviours.
|
| Loads fast, easy to debug without tons of layers in the
| middle.
|
| And yes, I also do manually make use of script and vendor
| JS libraries.
|
| Naturally it only works when doing side gigs on my own, on
| big Web projects where my role is mostly BE/DevSecOps, I go
| with the flow.
| leonardopainter wrote:
| That isn't a solution. Everybody moved away from this
| approach for web applications for good reasons.
| pjmlp wrote:
| The craziness of SPA frameworks running headless
| browsers, rediscovering SSR as if they are inventing
| something that no one else thought about, proves
| otherwise.
| stickfigure wrote:
| Having been on this ride since before HTML was a thing...
| I'm going to make a prediction: JS SSR will be a brief
| flash in the pan. In another ten years, we're going to
| look at it the same way we look at JSF today. "What were
| we thinking?"
| imtringued wrote:
| I agree, I am writing some apps like that and we still
| want some minimal level of interactivity that is suited
| to react. E.g. a file uploader.
| leonardopainter wrote:
| Well, I think when they moved away, they also increased
| the complexity of their applications as well.
| jillesvangurp wrote:
| I think for progress you need to look outside the js world.
| Fundamentally, people keep repeating the same mistakes there.
|
| I'm having a lot of fun lately using Kotlin-js for example. We
| use the Fritz2 framework, koin for dependency injection
| (popular on Android as well for good reasons), and fritz2
| relies on kotlin's co-routines and StateFlow for state
| management. It makes for a surprisingly concise code base. For
| example, the counter example from the article with that would
| look something like this: class CounterStore :
| RootStore<Int>(0) { val koinCtx by lazy {
| GlobalContext.get() } // handler that you can bind
| events to or invoke directly like below val inc =
| handle { old -> old + 1 } init { //
| launch co-routine to keep on incrementing the counter
| GlobalScope.launch { while (true) {
| inc() delay(1000) }
| } } } val koinCtx by lazy {
| GlobalContext.get() } fun
| RenderContext.counterComponent() { val counter by
| koinCtx.inject<CounterStore>() h1 { +"A Counter" }
| // react to changes in the counter counter.data.render
| { currentCount -> p { +"Current
| count: $currentCount" } }
| pushButton { icon { arrowUp } events {
| clicks handledBy counter.inc } } }
| fun main() { startKoin { modules(
| module { single {
| CounterStore() } })
| } render("#target") { counterComponent()
| } }
|
| There's a lot going on here that I can't explain here. But
| having co-routines means having a proper reactive framework
| that you use to react to events and update stores, which is
| where you keep your state. counter.data is a so-called
| StateFlow; the render function maps updates in that flow to the
| dom. In the example I have both a button and a co-routine
| updating the store via a handler lambda function.
|
| Using koin here, just means keeping glue code out of places
| where it doesn't belong. It's technically optional but makes a
| lot of sense in larger applications. Because components are
| extension functions on RenderContext, I use a global variable
| to get to the koin context. That allows me to inject my
| dependencies into components with a minimum of fuss. Where
| Fritz2 gets fun is with more complex state using data classes,
| lenses, validators, routers and a few other things. And they
| also take care of styled components and they even have a nice
| component framework that you can use. Not for everyone and
| there's a bit of overhead in terms of download size. But great
| if that less of a concern.
| ohgodplsno wrote:
| >GlobalScope.launch { ... }
|
| I can't begin to express how sad that makes me. Your
| component should have its own scope that it destroys when it
| gets destroyed, otherwise your coroutine leaks to the outside
| world when your component is gone from view.
| jillesvangurp wrote:
| Sure, but I wasn't going to fit a whole lot of boiler plate
| in a comment on HN to do that. Using Globalscope in a demo
| is perfectly valid; a lot of co-routine presentations do
| that as well. Normally, I'd use some named scope and life
| cycles associated with e.g. koin modules or a web worker.
| This is just something that I quickly knocked out that
| actually works. Also, this is not Android. There are not a
| whole lot of life cycle events beyond "page loaded".
| mst wrote:
| The way mobx-state-tree uses generators as a coroutine-like
| affordance is worthy of study.
|
| I would not at all be surprised or troubled if, having
| studied it, you still dislike it, but there are definitely
| ideas in there that I consider to be at worst -interesting-.
| fuzzy2 wrote:
| Slightly OT: I'm always amused coming to discussions like this
| one, where people are (basically) complaining about the Virtual
| DOM and its implications. It's bad for performance at scale,
| updates aren't minimal. And other stuff: SFC are hard to wrap
| your head around, I don't want to write explicitly reactive code
| and so on. Some framework solves this by looking (somewhat) like
| React but in the end doing something entirely different.
|
| May I interest you in Angular? It certainly isn't cool and I
| _really_ do hate it. But especially since the AoT compiler has
| been implemented, performance is quite good. There's templates,
| which some folks seem to love. Angular keeps in-memory references
| to all dynamic elements in a template so they can be updated with
| high efficiency. It has class components. It has a lifecycle
| method that is called _OnInit_. So maybe give it a whirl.
| awr wrote:
| I've been using Angular in production for 5+ years. There was a
| year where things were confusing, state updating all over the
| place, and general frustration. But once I grokked pure
| components, and embraced "data down, actions up", it all
| clicked and just made sense [0]. I find React obtuse in
| comparison.
|
| Angular front-end, Nestjs backend has fast become my stack of
| choice. It greatly minimises context switching by having such
| similar paradigms across frontend and backend.
|
| [0] - blog series I wrote detailing Angular best practices that
| I learnt along the way: https://link.medium.com/ncYgWgnK2nb
| ramoz wrote:
| The whole "I hate angular" is a bit old at this point. The
| latest versions are really quite simple/powerful. We act like
| it's still 2015 and we're jumping from angularjs 1.x to React.
| The jump was nice, yet turns out production-grade engineering
| in React was not so nice.
| fuzzy2 wrote:
| I don't like the separation between template and code, I
| don't like the developer experience (slow and often
| malfunctioning VS Code extensions and slow builds, bad in-
| browser debug helpers), I don't like how creating "ad-hoc"
| components is basically impossible.
|
| I think Zone.js is insane.
|
| I know Angular very well. That's why I'm confident I can
| create high-performance applications using Angular. I firmly
| believe Angular has far too many pitfalls for inexperienced
| developers.
|
| So yeah, I hate Angular.
| ramoz wrote:
| `Angular Language Service` is the only domain specific
| extension I've ever needed and its never been an issue. The
| template separation, as well as (s)css, I like
| organizationally compared to the chaos you end up in with
| large jsx-styled applications.
| mst wrote:
| If you can't hate on your major dependencies confidently
| and at length, you probably haven't used them long enough
| yet.
|
| I generally spend much of my day writing perl. It
| absolutely works for me, but every time I encounter
| somebody who wants to -attack- perl I find myself
| disappointed by how short their list of reasons to hate it
| is compared to my own.
|
| (one of the most complicated JS codebases I work with on a
| regular basis is in angular, and the learning curve is a
| fucking cliff but yeah, once you get to the top, I agree
| with everything you've said about it)
| brendan-csel wrote:
| We've used React with Mobx in commercial apps for 5+ years now.
| React has been good for us BUT Solid is so much cleaner (and
| leaner).
|
| Porting most React code to Solid is pretty easy - mostly involves
| deleting things that are no longer required (useCallback, useRef,
| etc) and moving prop access into the JSX to enable just those
| specific attributes to be updated when state changes.
|
| It has come to the point where I really begrudge going back to
| working in our React code. Unfortunately those apps will still be
| around for a long time - but we won't be using React for green-
| fields projects.
| mst wrote:
| As somebody who's quite enjoyed mobx I would encourage you to
| write up your experiences.
|
| I would hope that while -me- reading any such blog post is
| almost certainly going to be irrelevant, it might pay off
| enough in recruiting/marketing/pure nerdery to be worth the
| effort to write it up.
| TekMol wrote:
| What feels like complete insanity when it comes to React is that
| it needs compilation to work: render() {
| return <div>The count is: {this.state.count}</div>; }
|
| This is not Javascript and it will need to be compiled into
| Javascript before it gets executed.
|
| But you can do the same in Javascript: render()
| { return `<div>The count is:
| ${this.state.count}</div>`; }
|
| Using regular Javascript makes my life a thousand times easier
| than having to go through a compiler to make things work in the
| browser.
| mst wrote:
| You might find this interesting:
| https://github.com/developit/htm#readme
| orenelbaum wrote:
| This is another area where Solid has an advantage over React.
| With React you could use Hyperscript functions so the above JSX
| would be
|
| React.createElement('div', null, `The count is:
| {this.state.count}`).
|
| With Solid you get the choice, you could use JSX, Hyperscript
| functions or template literals like in your example. Solid does
| recommend using JSX because there are some tradeoffs to using
| template literals without compilation, but it still maintains
| almost all of its qualities AFAIK and in the big framework
| benchmark Solid with template literals is the fastest template
| literals implementation.
|
| With Solid you don't even have to use any templating languages,
| you can take care of rendering yourself using the tools that
| the framework gives you. Solid at its core is more of a capable
| state management library similar to MobX but designed to be
| used as the only reactivity engine unlike MobX which is usually
| used on top of React.
| leonardopainter wrote:
| Using template literals to represent html is a security
| issue. If the state comes from the user, they can add script
| tags into the html. People try to solve this with tagged
| templates, but then if you forget the tag, you have a
| security issue again. Lit checks for this, but the fact that
| it has to check means it is less secure than not using tagged
| templates. There are libraries on github for creating sql
| using tagged templates which have the same security issue.
| The problem is that if your function works with both tagged
| templates and plain strings, when you forget to add the tag,
| you will never know.
| TekMol wrote:
| If the state comes from the user, they can add
| script tags into the html
|
| How is that different with React?
|
| And how is it a problem? A rendering engine would set the
| html of some element to the html I think?
|
| This ...
| document.body.innerHTML='<script>alert(1)</script>';
|
| ...does not execute the script.
| leonardopainter wrote:
| <img src='x' onerror='alert(1)'>
|
| https://developer.mozilla.org/en-
| US/docs/Web/API/Element/inn...
| TekMol wrote:
| True.
|
| But the same issue with reacts way.
| leonardopainter wrote:
| In terms of the placeholders in JSX, no they are escaped.
| yulaow wrote:
| Doesn't that make an hard life for the linter that now has to
| decide which template string represents a (complete) element
| and which is just text/whatever? I prefer the first solution
| because it's much simpler to parse
| aryehof wrote:
| As with any new JS framework technology, it will feel great until
| its flaws, warts, deficiencies and limitations are inevitably
| discovered as complexity rises, and which are then addressed in
| the next JS framework.
| torginus wrote:
| I wonder if there's an immediate mode framework for Js, in the
| vein of IMGUI for C. If people are wondering what that is, it's
| basically this: function renderGui() {
| label('hello') if(button('click me')) {
| console.log('I have been clicked') } }
| antihero wrote:
| This seems like a huge step back from declarative UIs, any
| reason why you would say it's preferable?
| torginus wrote:
| Performance, for one. This method can easily avoid allocating
| an object for every div (since it turns into a method call,
| not something that needs to return an object), compared to
| React's render() method.
|
| Another scenario outlined in the article of rendering a row
| of buttons, each with it's own click handler, that needs to
| allocate a lambda for each button every render.
| Alternatively, using map() and filter() also allocates
| lambdas and temporary arrays.
|
| All this can be replaced with a simple _for_ loop like:
| for (item of items) { if(!item.isClickable)
| continue; if(button(item.name)){
| console.log(item.name) } }
|
| Compare this to the React-ish pseudocode:
| items.filter(item=>item.isClickable).map(item=><button
| onClick={()=>console.log(item.name)} >{item.name}</button>)
|
| Readibility-wise, it's sort of an acquired taste, I'm not
| saying it looks better than JSX (but it's a hell of a lot
| readable than _React.createElement_ , so some syntactic sugar
| might be put on top of it).
| mst wrote:
| I suspect that the nature of the DOM means that being able
| to do that in the first place would actually require a
| virtual DOM w/diffing assuming you're targeting browsers.
|
| However that's probably obvious, so: Assuming you're
| considering greenfield / blue sky thinking here, it's worth
| noting that v8 has had so much money and engineering hours
| sunk into it that the react-ish pseudocode probably doesn't
| make nearly as many allocations as a naive reading of the
| code might expect.
|
| (a good friend of mine was very surprised to discover that
| v8's JIT is good enough that naive javascript code was
| basically competitive with FFI-ing out to C++ just because
| the node FFI layer introduced sufficient overhead that the
| JIT managed to catch up ... I am not a compiler wonk so
| please don't take this as a remotely expert pronouncement
| but "it is, in fact, quite difficult to overestimate v8
| these days" seems to be a solid heuristic)
| torginus wrote:
| >the react-ish pseudocode probably doesn't make nearly as
| many allocations as a naive reading of the code might
| expect.
|
| Who knows, if V8 manages it to turn it into a for-loop? I
| don't, but after a quick googling, as of 2018, it
| certainly didn't: https://github.com/dg92/Performance-
| Analysis-JS
|
| The problem with JS is that the execution model is so
| nebulous, that performance advice basically boils down to
| - trust in Google.
| epidemian wrote:
| i think an immediate mode UI library would make sense if you
| want to render to a canvas or a similar "backend". maybe for
| things like games, or some interactive graphic things
|
| but if you want to render to the DOM --and you want to use the
| DOM if you want to have decent accessibility, or not have to
| reimplement all the complex user interactions that the browsers
| take care of-- then i think an immediate mode framework might
| have a great impedance mismatch with the DOM, as the latter is
| a retained mode GUI model
| [deleted]
| kkarpkkarp wrote:
| and the same in Svelte:
| https://svelte.dev/repl/767f2d2fefc34bb6ae0b54b5aec5e947?ver...
| progx wrote:
| As a svelte developer i could really not understand the problem
| of TypeOfNaN.
| e-dant wrote:
| I am fundamentally skeptical of anything that needs a runtime for
| anything other than security and profiling.
|
| I am extra skeptical of any framework that needs 50mb memory
| baseline.
|
| I am triple skeptical of anything that uses brand-new packages
| and components like legos.
|
| *Iterations on React are welcome.*
| ajkjk wrote:
| Well, you can be skeptical, and the enterprise front-end
| engineers are going to go right on using that stuff because it
| scales to large codebase.
| e-dant wrote:
| Yes, right up until said startups and enterprises 1. cannot
| afford the outrageous cloud expense or 2. Need to scale to
| low-power devices (such as wearables) and to customers who
| are security conscious
| ajkjk wrote:
| Don't worry, they're doing fine. Anyway, we were talking
| about React, to which none of those objections apply.
| AtticHacker wrote:
| This reminds me a lot of Clojurescript's Reagent https://reagent-
| project.github.io/ (link also has a counter example)
|
| I've tried using bare React in the past (after using
| Clojurescript), because I wanted my project to be more
| approachable for outsiders. But I couldn't really handle the (to
| me, and the author) unnecessary complexity that's added.
|
| I would even say the Reagent version is even simpler than the
| Solid.js version, because you're using Clojure's Atom API rather
| than creating read / write functions. For the adventurous hearted
| I'd definitely recommend giving it a try!
|
| Edit: Someone posted a Reagent counter example on codepen a few
| days ago: https://codepen.io/Prestance/pen/PoOdZQw
| dhucerbin wrote:
| Imagine if we could have runtime characteristics of solid, dsl
| of hiccup and simple semantics of clojure atoms and refs!
| knubie wrote:
| It should be possible to build an idiomatic cljs layer over
| solid. Solid's compilation step can be implemented with
| clojure macros.
| mst wrote:
| I am already far too nerd sniped by other things to try
| building it myself but that does absolutely sound like fun.
| schwartzworld wrote:
| I love solidjs, but the similarities to React are the hardest
| part for me. The semantics are so similar, but the mechanics are
| the polar opposite.
|
| In react, everything is a function and all your code runs on
| every render unless you specifically tell it not to. This really
| encourages a certain style of writing code and provides a lot of
| guarantees about safety and scope.
|
| Solid is literally the polar opposite, your code runs once, and
| only the parts that you specifically make reactive are reactive.
| This allows for much finer-grained updates and performance.
|
| The mental models are so different because they are optimized for
| different things. React allows for developer sanity (cue all the
| people who worked on one lousy react app telling me that it
| doesn't) and Solid optimizes for speed and simplicity.
|
| Solid is very well designed though. One of the features I loved
| is that Ryan specifically built it to work as possible to vanilla
| html/js so you can copy old stack overflow answers.
| christophilus wrote:
| I had the same problem: spending time trying to figure out why
| something didn't paint. You also can't use restructuring the
| way you might expect. It's a cool library, though. I think you
| just need to keep a different set of nuances in mind when using
| it.
| schwartzworld wrote:
| Agreed, and typescript is essential. I'm still new enough to
| the patterns used in solid that I can't always tell whether a
| prop is a value or a signal, but with TS it's trivial.
| deepstack wrote:
| and Solid JS runs very close native JS speed! Any one making a
| Reactive Native Connector for solidjs? Vue Native was already
| using that connector. with that, Solid JS will be ultimate
| isomorphic lib to use.
| lawrencechen wrote:
| The author of Solid.js (Ryan Carniato) also does weekly
| livestreams about a range of JavaScript topics:
|
| https://www.youtube.com/c/RyanCarniato9
| e-dant wrote:
| I hate the whole javascript ecosystem to the core.
|
| Hey I just finished my progressive web app with these 10 cool
| react components I found on NPM which fit surprisingly well into
| our startup's cloud-native Vue interface.
|
| I tried to put the code up on GitHub but it wouldn't let me
| upload a 10gb repository (and that was _without_ our proprietary
| fork of mysql :)
| EMM_386 wrote:
| Too much snark.
|
| We are running an enterprise-scale Angular 13 "SPA" that blows
| the prior platform out of the water.
|
| It just depends on the team and the goal.
| [deleted]
| pl0x wrote:
| Me too. TypeScript is a disaster.
| smt88 wrote:
| This is interesting because it's a bit like Svelte, but it
| doesn't use the Svelte "language" (which looks like JS and HTML
| but, in some crucial ways, sometimes _isn 't_).
|
| It's a little disheartening to see that it's 3+ years old and has
| only had a single significant contributor though[1].
|
| It's impossible to avoid single-contributor projects in the JS
| world, especially with Node, but the alternatives (React, Vue,
| Angular, and even Svelte) are orders of magnitude more popular,
| so it's one area that we can play it safe if we need to.
|
| 1. https://github.com/solidjs/solid/graphs/contributors
| armchairhacker wrote:
| solid.js may only have a single contributor but i believe it's
| been battle-tested and used in some larger projects (don't have
| any examples off the top of my head though)
| jamghee wrote:
| I have no idea if it's in the creator's interest but I'd love
| to see Solid get backed by a company the way React, Angular,
| and Svelte are. That might make people take it more seriously
| as an option but, as-is, it certainly feels like a risky option
| to use professionally.
| lhorie wrote:
| FWIW, the author joined the Marko core team at eBay a while
| back.
|
| But from what I hear, he's still pretty responsive on Github.
| ConsoleTVs wrote:
| Solid is sponsored by Vercel, Cloudflare and Netify
| ryansolid wrote:
| I'd also look at other repos. Admittedly for the core code it
| has been mostly me. I think there is an intimidation factor.
| When you create a library this performance oriented it is hard
| to get people comfortable working on the core.
|
| But things like the site, docs etc.. are much more contributors
| making more substantial submissions:
| https://github.com/solidjs/solid-site/graphs/contributors
| https://github.com/solidjs/solid-docs/graphs/contributors
|
| We would have never gotten the docs translated into 15
| languages otherwise. I do agree that one should be cautious
| regardless. But I don't want to underplay the contributions of
| many contributors putting in improvements every day.
| mst wrote:
| There are projects of mine where I'm the only relevant core
| contributor but the ecosystem is developed by many other
| people and it's largely worked out fine.
|
| I would hope that if either of us got hit by the proverbial
| bus that people involved in the ecosystem would pour
| themselves a strong drink and dig in to the necessary
| maintenance anyway.
|
| Projects I've ended up moving on from have regularly worked
| out that way, and I think that while solid might not be as
| popular as some people would want for something to bet their
| production code on, it does seem to me that it's popular
| -enough- that I don't believe you're a truly dangerous single
| point of failure here.
|
| (if this comment read as negative rather than an attempt at a
| clear eyed analysis, I apologise for phrasing it wrong)
| rglover wrote:
| Escape the nightmare, embrace the zen, use Joystick:
| https://github.com/cheatcode/joystick.
| KrishnaShripad wrote:
| Regarding the example under "Reactivity, not lifecycle hooks":
|
| Does the <Counter /> component reference the same outer "count"?
| So is "count" here global or local to the component? In other
| words, what is the scope of "count"? Does it change based on
| where it is placed? If I create multiple <Counter /> components,
| do they all reference the same "count" or is it different for
| each component?
|
| Sorry this question might seem naive if you are experienced in
| SolidJS. I haven't given SolidJS a shot yet (though it is on my
| list of things to check out).
| manmal wrote:
| I think the count variable is quasi an Rx subject, it has
| identity and any code using it is keeping a hard reference on
| it. It would probably be GC'd if nobody referenced it. In my
| understanding, yes, multiple components would use the same
| instance of count.
| ryansolid wrote:
| Yeah this is correct. The trick to this is that the
| subscriptions happen in our JSX and hooks. And really is just
| a nested tree of `createEffects` if one ever re-evaluates or
| is disposed it releases its child computations. So while the
| lifecycle isn't tied to components it is still hierarchically
| structured. Ie.. places where logic can branch becomes the
| owning scope, like conditionals or loops. So Signals like
| count don't really matter where they live and will live as
| long as in scope or referenced, the rendering still largely
| defines how long things are around.
| leonardopainter wrote:
| This article points out how ridiculous React is. This is just a
| simple timer, yet there are so many things you can get wrong.
| This article doesn't seem to even clear the interval so it runs
| forever. Solid solves some problems, but I don't know why
| everything has to be reactive. I have never understood it, I just
| noticed that from knockoutjs onwards, every front-end framework
| was based on automatically updating views based on state.
|
| I create a library at github.com/thebinarysearchtree/artwork. To
| be honest, I don't know if it is going to work or not. It is just
| javascript with no reactivity. When I rewrote a fairly typical
| large application that you would find at most corporations (not a
| giant tech company application), every component ended up being
| about 50% of the code of react, with excellent performance.
|
| The problem I have with it that makes me uneasy is that
| ultimately you are creating content in JavaScript, which I don't
| think is ideal. The lack of HTML structure isn't a problem as
| devtools and so on show that. The problem is things like:
| const label = label('Email:');
|
| I want the HTMLLabelElement variable to be called label... but
| that is the name of the function that creates it. Then there is
| the setText example on the github page... I just didn't want to
| write label.innerText.. h3.innerText... etc etc .innerText.
| Variadic arguments are not ideal though, and when you have lots
| of elements with lots of attributes, eg: const
| content = div({ className: 'content', title:
| 'whatever', innerText: 'something' });
|
| it doesn't look like art, which is the point of the library. It
| is just hard to create content with JavaScript and not really the
| tool for the job. If I could solve that, I would be very happy
| with the library. It kind of needs JSX, but then it is back to
| having the JSX variable auto-update the state and well.. I guess
| that is why knockout and so on do it. Maybe I could do just plain
| HTML without state.
|
| So yeah, I don't know. I mean, it does end up being half the
| code. If you look at the todo example on my github page, and
| compare it to the one on React's homepage or solid's homepage, it
| is literally half the amount of code with native hand-written
| performance. This continues on to real-world components, it is
| just that.. I am a perfectionist I guess, and I want it to be
| elegant always.
|
| anyway.. I haven't even finished writing the documentation.
| MaxMoney wrote:
| frolicker wrote:
| Wait what's the problem here? Because you didn't like adding
| [count] as a dependency to setEffect(()=>{},[...count goes
| here...]) you wrote an entirely new framework?
| recursive wrote:
| It's not just that one case. Everything in react is like this.
| I find react code hard to reason about because this type of
| friction exists almost everywhere. Solid is what I always
| wished react was, but had a hard time articulating.
| [deleted]
| unfocussed_mike wrote:
| > That's a lot of code to write for an auto-incrementing counter.
|
| Is it though?
|
| I mean I happily write more code for a single-page Vue component
| for something like this.
|
| Terseness is not always a virtue.
| orra wrote:
| > Terseness is not always a virtue.
|
| This is a subjective thing, right? Personally, I hate
| boilerplate: either it's a distraction because it's boring and
| superfluous, or worse it's long and it's wrong. Regardless, it
| adds to the cognitive load when maintaining code.
| unfocussed_mike wrote:
| Yeah, definitely, hence the "not always" in this case.
|
| There are several terse syntaxes I really like. I'm just not
| convinced it's a virtue in this context.
| strangeattractr wrote:
| The vue code for this is pretty terse anyway to be honest. A
| single variable in data, a call to setInterval in the created
| hook and a few lines of html with template formatting. It's
| extremely clear what's going on too.
| unfocussed_mike wrote:
| I agree. I think the single-page .vue model is also really
| amenable to whitespace and consistent formatting.
| pictur wrote:
| javascript ecosystem is truly a shithole. I say this
| independently of the article.
| [deleted]
| solididiot wrote:
| <cynic>Yeah React is already so last year.</cynic>
| bayesian_horse wrote:
| The issue is more about not understanding how React works and how
| to use hooks. The setInterval example is easily solved. No, you
| can't just half-assedly guess your way to a correct solution.
|
| Also, composing asynchronous behavior with useEffect is also not
| a good idea. Don't abuse useEffect as an Event Handler (too
| much). Think about using Redux (+ thunks/saga) or something
| similar.
| thex10 wrote:
| As someone who doesn't feel so enamored with React's hooks, I
| find this compelling.
| jamghee wrote:
| React hooks are footguns
| adam_arthur wrote:
| Vue hooks avoid the closure/scoping issue mentioned in the
| doc. Very similar conceptually, but I find Vue's
| implementation a bit nicer to use
| MarcelOlsz wrote:
| Took me 30 minutes to get up and running in Vue. Week 4 of
| this job and I still can't unfuck myself with React.
| kevinmchugh wrote:
| I'm missing some toes from the old react lifecycle methods.
| The vanilla hooks were easy to use, reason about, and robust
| against misuse in a way the lifecycle methods weren't.
|
| I could see custom hooks being more dangerous and difficult,
| but Higher-Order Components are too.
| dimgl wrote:
| I'm surprised to see so many negative opinions about React.
| Surely, I can't be the only one that truly likes React and finds
| myself being extremely productive and making impressive apps with
| it.
| recursive wrote:
| You're definitely not the only one. But I find it refreshing to
| hear some people voicing many of the complaints I've had about
| React for years. Up until very recently, criticizing react
| seemed to be nearly unheard of.
| rk06 wrote:
| Have you tried solid/vue? If so, consider adding your
| perspective of what react does better.
| sprobertson wrote:
| This looks a lot like my current favorite state framework (which
| yes is done by Facebook people), Recoil - https://recoiljs.org/
|
| Your naming however reminds me of the RxJS and general reactive
| programming paradigm I've always pined after... some combination
| of the two would be my UI state management holy grail.
| deckard1 wrote:
| Many devs have succumbed to the siren song of event sourcing.
| And many code bases have sank on those rocky shores.
| c-smile wrote:
| Instead of vDOM, solid.js uses <template> - real DOM elements +
| cloneNode().
|
| And that's doubtful decision. Each live DOM element is about
| 100-200 bytes in memory.
|
| While in React (PReact, Mithril) this JSX expression:
| <div>a</div>
|
| is this: ["div",{},["a"]]
|
| 5 or so times less.
|
| In other words: needs to be tested on large DOM structures.
| infensus wrote:
| That's just a component template though. When you produce large
| DOM trees, you usually do so by rendering your components a lot
| of times, not by having a lot of different components
| jorroll wrote:
| Like the author of this post, I appreciate Solid's API because
| component's only render (i.e. run) once by default and then you
| define which sections of the component should re-render on
| changes by using "signals" provided by the library (e.g.
| `createSignal()` and `createEffect()`). In react, the entire
| component re-renders on every change and you need to specify
| which code should _not_ re-run. This was necessary because of the
| way react was created, but strikes me as fundamentally flawed.
|
| Having used Solidjs for some pet projects, I've come to strongly
| prefer Solidjs over React. It's an evolution of react, so I've
| found my existing skills/knowledge transfers. This being said,
| Solidjs is brand new and the ecosystem is _minuscule_ compared to
| React. For this reason, I plan to continue using React for the
| foreseeable future. One of the biggest weaknesses of Solidjs is
| the lack of a "nextjs" like framework. It appears work is being
| done in the solid-start[1] repo, but it looks like it's still
| years away from being fleshed out. I want Solidjs to succeed, but
| I'm not interested in being an early adopter.
| [1]: https://github.com/solidjs/solid-start
| aidenn0 wrote:
| > Like the author of this post, I appreciate Solid's API
| because component's only render (i.e. run) once by default and
| then you define which sections of the component should re-
| render on changes by using "signals" provided by the library
| (e.g. `createSignal()` and `createEffect()`). In react, the
| entire component re-renders on every change and you need to
| specify which code should _not_ re-run. This was necessary
| because of the way react was created, but strikes me as
| fundamentally flawed.
|
| I don't particularly like React, but this strikes me as the one
| thing it got right; the only "always correct" thing to do is to
| rebuild the VDOM on any change, so that's the default.
|
| Then you can be more selective about which parts as performance
| dictates.
| jorroll wrote:
| Interesting. I guess it just boils down to different
| preferences.
| matsemann wrote:
| That would be true if all a react component was dom output.
| But since it has side effects (rest calls, mutating state,
| effects), rerunning everything is the wrong thing to do in
| almost all instances.
| aidenn0 wrote:
| Sure, if you put side effects in your react components,
| you're gonna have a bad time <insert South Park meme>.
| jakelazaroff wrote:
| This is where I'm at, too -- it's faster and simpler than
| React, and less magical than Svelte, but it's just too
| immature. As another commenter pointed out, there's basically
| one contributor:
| https://github.com/solidjs/solid/graphs/contributors
| jorroll wrote:
| I think a challenge for new javascript libraries/frameworks is
| that, for many developers (including myself), we're evaluating
| the whole architecture. The question isn't, "Which library has
| the best API and is most performant for rendering components?"
| It's which choice gets me to "usable app" quickest and most
| pain-free? Included in the calculation is the ecosystem, the
| build tools, the documentation, the deployment strategy.
|
| For all these reasons, while I do _really love_ Solid 's API,
| React + Nextjs + Vercel (or another React stack like Gatsby,
| etc) ultimately provides a smoother development experience for
| the time being. It isn't enough to build a better React,
| someone needs to provide an easy to use build and deployment
| process for it as well.
|
| I ended up giving up on my Solidjs experiments because I spent
| too much time debugging the build process and porting React
| libraries. It's still not obvious to me how I could deploy a
| Solidjs app to, e.g., a Cloudflare Worker and provide a `/api`
| callable functions endpoint for the application. I have no
| doubt that I could figure all of it out, but I'm not interested
| in spending the significant amount of time necessary to do so.
| I love the fact that Nextjs just gives me all of this. All of
| this is to say that, while the core Solidjs library is really
| "solid" (pun intended), I still don't think Solidjs is ready
| for new projects (unless you really like doing things from
| scratch).
| alskdjflaskjdhf wrote:
| >Having used Solidjs for some pet projects, I've come to
| strongly prefer Solidjs over React. It's an evolution of react,
| so I've found my existing skills/knowledge transfers. This
| being said, Solidjs is brand new and the ecosystem is minuscule
| compared to React. For this reason, I plan to continue using
| React for the foreseeable future. One of the biggest weaknesses
| of Solidjs is the lack of a "nextjs" like framework. It appears
| work is being done in the solid-start[1] repo, but it looks
| like it's still years away from being fleshed out. I want
| Solidjs to succeed, but I'm not interested in being an early
| adopter.
|
| The chicken-and-egg ecosystem problem for new frameworks is
| tough. I've been working on Svelte stuff lately which has a
| similar problem but less extreme--the ecosystem is still much
| worse than React's, unsurprisingly, but it's also much better
| than Solid's right now.
|
| I think Solid's primary branding is around performance and
| Svelte's primary branding is around it being easy. For getting
| things off the ground, I think "easy" is a much more successful
| approach.
| orenelbaum wrote:
| Solid has done some branding around performance but the
| promotion is shifting to be more balanced, as Solid really
| isn't about performance. Solid's biggest priority has been to
| give the best DX for building performant applications that
| stay maintainable at scale and after years of work on the
| same project. Solid might seem harder than Svelte or Vue to
| get started with (although this is arguable IMO) but due to
| it's simplicity I think that it's much easier to master and
| understand what actually is going on.
|
| Compare this to Svelte which has the goal of creating the
| perfect high level abstraction so that you never need to
| understand how things work and was originally created for
| smaller one off projects with much smaller complexity and no
| maintenance burden.
| iamleppert wrote:
| This article perfectly captures the essence of why I no longer
| work in web development. Never again!
| christophilus wrote:
| Out of curiosity, what do you do now?
| devmunchies wrote:
| Google search says senior eng leadership.
| torginus wrote:
| Can anyone explain the point of the virtual DOM and why it's not
| a source of huge performance issues? What I mean as soon as you
| retain a reference to a DOM element, it's lifetime becomes
| managed by the JavaScript gc - let's say you build a paginated
| gallery app in pure HTML and an spa - in the first case, the
| browser knows that as soon as you navigate away from the page,
| all those image thumbnails are free real estate, at the latter
| case it first needs to wait for the spa to release references to
| the underlying html objects, then the gc needs to run, at which
| point it can get rid of it.
| [deleted]
| schwartzworld wrote:
| The reason for the virtual DOM: in react, the entire world is a
| function that gets rerun on every render. The whole point is to
| be able to define some state and then render the whole world in
| accordance with that new state. When react was conceived, Dom
| updates were very slow and could bottleneck the application.
|
| Knowing that your entire UI is running inside a function that
| gets re-executed with every render, gives a tremendous amount
| of safety and predictability to your application and makes
| testing a breeze. But you can't actually rerender the whole
| world every time because performance, so instead React relies
| on a JavaScript object to hold a representation of the UI, and
| then surgically updates only the pieces that need updating.
| This was React's big thing.
|
| The reason people want to move away from virtual dom is because
| browsers have gotten faster and now the Dom updates aren't the
| biggest source of overhead.
| Kuinox wrote:
| https://svelte.dev/blog/virtual-dom-is-pure-overhead
|
| It is a huge performance issue.
|
| I tried to do a pokedex in react, you have to use a virtual
| list, because react/virtual dom is too slow, doing any
| operation on a plain list with 1k element, like filtering lead
| to multiples seconds freeze.
|
| This also lead to a lot of issues, like not being able to
| ctrl+f text being out of screen in a virtual list.
| torginus wrote:
| Great article. The fact that Angular, the framework built by
| the company who also builds the world's most popular browser,
| does not have a virtual DOM, is very telling.
| bstar77 wrote:
| It's actually a terrible article that has no relevance in
| 2022, and it is even misleading for 2018 standards.
| Kuinox wrote:
| I wouldn't acclaim angular for the performance either.
|
| Building apps on it show consistent subpar performance.
| ramoz wrote:
| generally speaking, Angular handles dom manipulation
| better than React and Vue. Angular has managed to
| simplify its enterprise/production applicability and
| performance is a first-order feature that's hard to f up.
| React -- you can f performance up before you're done
| writing your first component.
| bstar77 wrote:
| I don't understand your issues here. I built a community app
| for a hockey league that manages around 120,000 players in
| the DB. I do tons of loading, sorting and various algorithms
| on the data. I've never once had React be my bottleneck.
|
| Rendering a page server-side and delivering it to users is
| about as inefficient a process as you can get unless you have
| massive resources dedicated to an optimization almost no one
| needs anymore. The virtual DOM is extremely efficient, it
| just needs more memory and CPU cycles on the client which are
| resources readily available. Browsers are very good at
| managing this in 2022.
|
| Btw, your code in that article is completely irrelevant... I
| would not be showing people that article in 2022.
| Kuinox wrote:
| I bet you don't display the 120k players at once on the
| front, you use some sort of virtualised component (like ag-
| grid) thats put in the DOM only what is displayed on
| screen, and keep the whole set in memory.
|
| It cause an issue: now the search in document browser
| feature will not work properly.
|
| This is acceptable the usecase you are describing(due to
| the huge dataset), but a lot of interfaces use such virtual
| list, and it's an PITA for the user.
|
| Take Azure DevOps for example: In a lot of place, you can't
| ctrl+f a project outside the screen, even if it exist, you
| have to scroll to it.
|
| > Rendering a page server-side [...]
|
| Nobody talked about server side rendering there.
|
| > The virtual DOM is extremely efficient
|
| Did you read the article I linked ?
|
| The virtual DOM is not "extremely efficient" it's only good
| at removing uneeded DOM modifications. Not doing these
| uneeded modifications in the first place is faster.
| mst wrote:
| I have hit a point where I've moved my browser from running
| locally on my laptop to running on a hetzner dedicated
| server over VNC because it performs ridiculously better so
| "readily available" is apparently an unfortunately variable
| claim.
|
| I would note however that my laptop is not entirely recent
| and I'm using firefox and my big pain point has been React
| Native Web apps like web twitter. So you're likely still
| mostly right, and the question inevitably becomes "how much
| mostly is enough for any given application".
| mlajtos wrote:
| I also did sort-of Pokedex a long time ago [0], but haven't
| seen any performance issues. No virtualization whatsoever.
| Code [1] is rather simple.
|
| [0]: https://mlajtos.github.io/lb-pokedex/build/
|
| [1]: https://github.com/mlajtos/lb-pokedex
| Kuinox wrote:
| I ran a profiling tool. I searched "zz" then deleted these.
|
| Deleting it caused a 120ms UI freeze (and I notice it :p):
|
| Profiling report: https://share.firefox.dev/3C3OhIq
|
| Given I had slightly more entries (a hundred more) and that
| I had way more node per entry, it led me with way worse
| performance.
|
| Instead of a plain list I have a little summary card per
| pokemon (which is why I have more node per entry).
|
| The naive implementation in Vue run flawlessly(sadly no
| preview):
|
| https://github.com/Kuinox/kuinox_pokedex/
|
| Note that the react implementation do weird thing because I
| tried to get around the issue without success.
| dhucerbin wrote:
| Great majority of my projects are data dashboards and I struggled
| with React for some time because of its top-down model - it can
| hinder performance really badly. If one of your points on
| scatterplot should be marked, you need to carefully pass this
| prop through few memoization layers, so any other points won't
| try to re-render.
|
| I've been on this quest for a long time, because I like React
| model. So I had fun with putting observables in my app (kefir and
| karet from calm-js and my own thing with xstream), I tried custom
| selectors with redux and all 'like-redux-but-simpler' libraries,
| I also tried recoil. These solutions can work and worked for my
| apps, but it felt like I was fighting against React.
|
| Solid was nice. It provided necessary tools to write interactive
| data visualisations with ease and in performant way. It has
| quirks but they are manageable - my team also learned and
| contributed to projects in Solid.
|
| First, the concept of "component functions" that are more like
| factories. It is not groundbreaking (reagent had this idea long
| ago) but is quirky. Thankfully, half hour with Solid playground
| and everybody can see what code is generated and how it works
| under the hood. It is really predictable but also tangible - you
| can play with just part of your app in playground if something is
| unclear.
|
| Second quirk is props object. I understand the trade-off but it
| trips users (me included) that you can't just treat it as regular
| object. Sadly, only solution for this is lint rule - yuck. But it
| is much simpler rule than hook rules - just don't destructure
| props.
|
| In the end, Solid is great tool for "web apps". Think about
| dashboards or diagram editors. Cheap components, fine grained
| reactivity, focused updates yield great performance results
| without jumping through hoops.
| lpghatguy wrote:
| New JS frameworks always make for compelling hello world
| examples.
|
| Can you branch on state or use loops over data in Solid.js? The
| reason _why_ React has a virtual DOM is to enable more
| interesting relationships between your data and your
| presentation. Anyone can make a framework that makes the source
| code for an incrementing number look pretty!
|
| As an example of this point, check out the "Simple Todos" example
| for Solid.js[1].
|
| In React, we render lists by using regular JavaScript idioms like
| loops, arrays, and array methods like map. However in Solid.js,
| much like traditional templating languages, we get a construct
| like <For> that reinvents a concept that's already in the
| language.
|
| I've been writing React and React-alike code for a long time. I
| think that fine-grained updates avoiding reconciliation are a
| good idea, especially for performance. At one point, I built a
| React-like library for Roblox and Lua whose most novel feature
| ended up being "Bindings"[2], which look sorta like Solid.js
| state containers. They create little hot-path data dependencies,
| but the bulk of your components still use normal React-like
| rendering. [1]:
| https://www.solidjs.com/examples/todos [2]:
| https://roblox.github.io/roact/advanced/bindings-and-refs/
| tambourine_man wrote:
| >...much like traditional templating languages, we get a
| construct like <For> that reinvents a concept that's already in
| the language.
|
| I'm right there with you, but when React invents a whole markup
| language inside of JavaScript, it's not in much of a standing
| to make purity criticisms.
| BigJono wrote:
| Well you've obviously completely missed the point of JSX
| then. The "whole markup language" that they invented is
| literally a line for line transform. Optimisation aside,
| there's no reason why line 58 of a file with JSX in it won't
| be line 58 of the transpiled JS file, and read _exactly_ the
| same. All JSX is is a custom function call syntax.
|
| It's about as pure as you can get while having any sort of
| html-ish 'templating' whatsoever.
|
| So, I'd say it's exactly in the right place to be making
| purity criticisms. They've taken the only approach that
| preserves the integrity of the code and doesn't involve build
| time magic.
| ______-_-______ wrote:
| Solid's <For> doesn't rely on any build-time magic, other
| than the JSX custom function call syntax that is also
| present in React. If you want, you can even call it like an
| ordinary function: function MyComponent()
| { return For({ each: [1,2,3,4],
| children: x => <div>{x}</div>, }) )
|
| It's just a function call, and it doesn't even need
| `React.createElement`. What's more pure than that?
| scotty79 wrote:
| Normal for statement is more pure than that.
| tambourine_man wrote:
| Oh I missed the point on React altogether. After 10 years,
| I still fail to see why anyone would use it voluntarily.
|
| But coming back to JSX, a custom function call syntax is OK
| and pure because it has a one to one mapping on line
| number?
|
| I don't know if there's much point in discussing purity
| since it's badly defined and mostly in the eyes of the
| beholder, but it always smelled like one hacky syntactic
| sugar to me.
| masklinn wrote:
| That is an utterly bizarre rejoinder. JSX has always been
| (and afaik still is) optional and extremely thin syntactic
| sugar. It's little more than a convenience macro (so that
| views can look a little more like the markup equivalent).
|
| It has no intrinsic semantics, and maps pretty much directly
| to actual javascript (which you can write directly or use an
| alternative helper for -- hyperscript being a common one).
| keb_ wrote:
| > In React, we render lists by using regular JavaScript idioms
| like loops, arrays, and array methods like map. However in
| Solid.js, much like traditional templating languages, we get a
| construct like <For> that reinvents a concept that's already in
| the language.
|
| This argument is silly because it inevitably becomes a pissing
| contest of who can be most like vanilla JavaScript. In that
| case, why use JSX? Just write hyperscript calls instead. Why
| use React Router/React Context helpers? Just wrap your
| components using vanilla function providers instead. _Why use
| React Hooks, which inevitably look like magic to a JavaScript
| veteran because the library inherently hides away some global
| state?_ I hope you can see what I 'm getting at here.
| leonardopainter wrote:
| >The reason _why_ React has a virtual DOM is to enable more
| interesting relationships between your data and your
| presentation. Anyone can make a framework that makes the source
| code for an incrementing number look pretty!
|
| Actually, that is only half the reason. You can do whatever you
| want in my library (github.com/thebinarysearchtree/artwork) and
| it doesn't have any kind of virtual DOM or whatever Lit does,
| because you just create elements with JavaScript. The second
| reason, that everyone just assumes is the default, is that
| React has to use HTML-like templates and not just JavaScript.
| Kaze404 wrote:
| JSX is a purely optional part of React. You can use it with
| just Javascript and no bundlers just fine.
| alskdjflaskjdhf wrote:
| >In React, we render lists by using regular JavaScript idioms
| like loops, arrays, and array methods like map. However in
| Solid.js, much like traditional templating languages, we get a
| construct like <For> that reinvents a concept that's already in
| the language.
|
| I find this a totally bizarre complaint. I've spent the past
| few months working on Svelte stuff and I've seen people on HN
| make this same complaint about Svelte's templating language
| with {#if} and {#each}. Who cares? What is so wrong, exactly,
| with "reinventing a concept that's already in the language"? It
| does not make code any harder to understand or to write, and it
| does not harm performance (in this case, quite the opposite).
|
| I would much rather have a reactivity model where I plug in
| completely standard concepts and patterns (a for loop) than one
| where I have to deal with a bunch of framework-specific,
| complicated ones (hooks). That Solid's reactivity primitives
| are familiar is an advantage, not a disadvantage.
| jbreckmckye wrote:
| > It does not make code any harder to understand or to write,
|
| Well, what can you tell me about TypeScript type inference
| for this custom DSL?
| toqy wrote:
| I wouldn't call <For> in Solid a custom DSL anymore than
| any given React component. And Solid looks to have good TS
| support.
|
| https://www.solidjs.com/docs/latest/api#%3Cfor%3E
| kjleitz wrote:
| Have you used Vue 3? There is fantastic TypeScript support
| in templates, including comprehensive intellisense for the
| templates in VS Code with the Volar extension.
| Surprisingly, _refreshingly,_ good.
| sbergot wrote:
| Because you sometimes want to filter, sort or project your
| data. Then you have to handle this in viewmodels or invent
| more and more features for the templating language. Then you
| want to refactor into components. So you need facilities for
| invoking subcomponents. Maybe you want something recursive to
| display tree-like data.
|
| So you end up with a secondary full featured language usually
| with worse IDE support, worse error messages, more surprising
| issues, etc. You need to understand the scoping mecanisms and
| if things go wrong hope there is a debug tool available.
|
| And in the end those templating languages do not prevent you
| from mixing UI responsibilities from the rest of your code.
|
| If you want a reactive model you can have one. I personally
| prefer explicit messages like calling setState.
| tjchear wrote:
| Haven't used solidjs before, but I paid the doc section a
| quick visit and saw that it's basically <For each={foobar}>
| where foobar can be whatever javascript code you want. So
| you can certainly do filter/sort/project on your data
| before rendering.
| Aeolun wrote:
| You'd probably not want to project inside that loop
| though, but before it, in a reactive effect.
| shrew wrote:
| > Because you sometimes want to filter, sort or project
| your data.
|
| The idea that this type of thing should be happening
| anywhere near the view rendering loop is the exact reason
| I've not had a great time picking up React codebases.
|
| By the time you're rendering data into markup, the data
| should be in the exact state you need it. No further
| filtering or data mangling or sorting. That type of data
| manipulation should happen at the point of data change and
| then it shouldn't happen again until the data changes
| again.
|
| The simplistic templating languages in
| Vue/Svelte/Alpine/whatever-comes-next force you to pull
| your data manipulation back to somewhere more appropriate,
| with Vue even throwing a warning if you try to filter
| within v-for construct.
|
| Because React is JS, people are let loose to do wildly
| inefficient operations and do them over and over and over
| whenever _anything_ in that component changes.
| pier25 wrote:
| Exactly. The whole paradigm of reactive data binding is
| that data dictates what the UI should render. Don't solve
| your data needs when rendering ffs.
| code_runner wrote:
| I love vue's concept of computeds. It makes me think back
| to knockoutjs when things felt like they "just worked" as
| long as you knew where the ES5 footguns were.
|
| It's nice to have a concept "ground truth" in data and
| props and then computeds that sort of tie it all
| together.
| shrew wrote:
| My feelings exactly, it makes for a satisfying separation
| of concerns, and if you understand what's going on under
| the hood it makes for cleaner templates and more obvious
| component code.
| gedy wrote:
| Yes, and those are available as well with MobX (in
| React), Svelte, etc.
|
| You can do same/similar with React hooks, just not as
| clean or obvious.
| shrew wrote:
| You can 100% do these things in React, I don't believe
| React is a less able framework by any means. If anything
| it gives you a powerful toolbox and pulls down the guard
| rails.
|
| I do, however, think that working with React changes your
| mental model somewhat, and when I'm working with React I
| catch myself doing a lot more data wrangling close or in
| the rendering loop than I would in any other modern
| framework. Certainly since class components have fallen
| out of favour, you're working with a function designed to
| be run hundreds of times, while Vue and Svelte both
| provide clear patterns to deal with data at the point of
| change, then separately deal with updating the display of
| that data as required.
|
| It takes using something like MobX to really push a React
| codebase to a data-driven model and that means many
| inexperienced developers fall into the common pitfalls
| far more easily than if they're using an alternative
| framework imo.
| chriswarbo wrote:
| > So you end up with a secondary full featured language
| usually with worse IDE support, worse error messages, more
| surprising issues, etc.
|
| Gilad Bracha calls these "shadow worlds"
| https://gbracha.blogspot.com/2014/09/a-domain-of-
| shadows.htm...
| tshaddox wrote:
| > What is so wrong, exactly, with "reinventing a concept
| that's already in the language"?
|
| Nothing, inherently. Just like there's nothing inherently
| wrong with having extremely clear and simple rules for how to
| use hooks, and lint rules to identify when you're not
| following those rules. Nothing inherently wrong with either,
| some people just have strong distaste for one or the other.
| madeofpalk wrote:
| A react feature that I appreciate is that it is "just
| javascript". It's easier to learn how to loop or have
| conditionals in React because it uses native JS features. It
| makes it easier to understand, for me.
|
| Having templating DSLs in other frameworks isn't a deal
| breaker, but it's a pro of React that I appreciate.
| recursive wrote:
| But I mean, it's not really. A hook invocation looks
| exactly like a javascript function invocation. Except it's
| subject to hook rules. Those don't come from javascript.
| Those are language rules that come from react. And even
| worse, the syntax for invoking a hook is exactly the same
| as the syntax for calling a function.
| nicoburns wrote:
| I've not used Svelte, but when I've used such DSLs the
| problem tends to be that they're not very flexible, and as
| soon as you step outside of the provided helpers you're stuck
| and you just can't do the thing.
| pier25 wrote:
| It's true, but the counterpoint is that DSLs make your life
| much easier in 90% of the cases (if not more).
|
| Personally I've never found a problem I wasn't able to
| solve in Svelte.
| shrew wrote:
| Do you have an example you've run into where a DSL such as
| Svelte's or Vue's has actually stopped you from doing
| something? Would be genuinely interested to see it as I've
| never run into such a situation myself.
| chrismorgan wrote:
| > _In React, we render lists by using regular JavaScript idioms
| like loops, arrays, and array methods like map. However in
| Solid.js, much like traditional templating languages, we get a
| construct like <For> that reinvents a concept that's already in
| the language._
|
| Once you deal with larger amounts of data and need virtualised
| rather than fully-materialised lists, you start using different
| things in React as well. The fact of the matter is that if you
| care about performance at all, the simple ways are just
| insufficient, and the native language constructs were designed
| for procedural programming, not reactive interface rendering,
| which requires fundamentally incompatible semantics. It's not
| even fair to claim that React uses regular JavaScript idioms--
| VDOM, hooks, the entire shebang is all about eschewing regular
| JavaScript idioms _because they don't scale_. (OK, so there's
| also the matter of transient state like scroll positions,
| element focus, and form field values; it's not fair to say that
| React does all these things purely for performance's sake, as
| the naive immediate mode approach would also break such
| functionality.)
| mwcampbell wrote:
| > virtualised rather than fully-materialised lists
|
| I want to push back somewhat on this practice. Our computers
| are fast enough now, and the browser implementations
| optimized enough, that they should be able to handle
| thousands of materialized list items without breaking a
| sweat. Sometimes you really need virtualization, e.g. if the
| underlying data source has millions of records. But if the
| data can be fully materialized, then the implementation is
| simpler, and the user can take advantage of things like find
| in page. Virtualization is a convenient way to avoid the
| inefficiency of unoptimized VDOM-based rendering (e.g. with
| React, and yes, I know there are other optimizations
| available in React), but fine-grained updating (as in Solid)
| is even better.
| suction wrote:
| What JS framework would you choose to work with big datasets
| like, e.g. a data grid with half a million rows that should
| have a "filter as you type" functionality?
| littlecranky67 wrote:
| Doesn't matter which framework if you implement it right.
| Filtering data from the dataset is plain js, and it will be
| slow. Rendering the data to screen requires a lot of work,
| such as using offscreen-buffers for smooth scrolling etc.
| Actually ag-grid does this pretty well, and I've used it
| for similar in a React app. Now hold your horses, ag-grid
| is angular 1.x, encapsulated as a component. Another proof
| that the framework is not important, you need to optimize
| hell out of it.
| chrismorgan wrote:
| Most of the work for this is essentially database tech
| rather than UI tech. From the UI perspective, you just need
| to be able to say things like "current query is 'foo', and
| based on my current scroll position I want to render
| records 32-86" (since 42-76 will be visible on screen, and
| then we add a few more for good measure to give a small
| time buffer for retrieving more when you start scrolling),
| ask the database layer for the required records, and render
| them as a perfectly normal virtualised/only-partially-
| materialised list. It's then up to your database layer to
| perform the filtering; whether that database runs on the
| frontend or backend makes no difference, and whether it's
| sqlite.js or records.filter(...).slice(...) makes no
| difference (though their performance characteristics will
| certainly vary). This _can_ be integrated with the UI
| framework fairly tightly, but there's no need for it to be.
|
| For the UI part of it: what I would use would depend on my
| requirements (is it a list, is it a grid, how is it to be
| interacted with, _& c._) and what was already in use
| (React, Svelte, plain JavaScript, other). I _personally_
| would often be inclined to implement it from scratch,
| because I'm typically not impressed with most library
| options (they have a tendency to be heavy, limited, and
| slower than they need to be) and am familiar with exactly
| what needs to go into it to make it as perfect as is
| possible (it's not a particularly large amount of work, but
| it is fiddly in places and _must_ be done correctly or
| it'll be awful), but that's not a course of action I would
| recommend for most developers.
| PetahNZ wrote:
| Isn't that what a backend is for?
| pygy_ wrote:
| You shouldn't do that kind of work from the rendering
| thread, and you should use occlusion culling to only render
| the needed DOM
| victorNicollet wrote:
| Having recently shopped around, and implemented, this kind
| of data grid: no JS framework actually handles the hard
| parts, but (more-or-less complete) libraries exist for
| nearly all of them.
|
| My specific use case is a React application, and I have
| found it easier to implement a dedicated listener system,
| than try to fit things into component states.
| pier25 wrote:
| > _we get a construct like <For> that reinvents a concept
| that's already in the language_
|
| Isn't this optional? Can't Solid use regular JSX loops?
| AgentME wrote:
| JSX doesn't have loops. When using React, you use regular
| not-React-specific Javascript tools to do loops and create
| lists of React elements.
| t_tsonev wrote:
| If this is true, why do you need unique item keys? React
| cares about loops a lot more than it may seem at a first
| look.
| sbergot wrote:
| keys are not specific to loops. They are needed whenever
| you are returning a react document with a dynamic
| structure. They allow for more fine grain dom updates.
| latchkey wrote:
| https://www.solidjs.com/docs/latest/api#control-flow
|
| For reactive control flow to be performant, we have to
| control how elements are created. For example, with lists, a
| simple map is inefficient as it always maps the entire array.
|
| This means helper functions.
| thatswrong0 wrote:
| This feels like we're trading complexity here for
| complexity there, and it seems impossible to judge which
| way is actually "better". I use loops in React all the time
| but only have used `setInterval` in a component a handful
| of times..
| ctvo wrote:
| Most of our jobs is determining the right trade offs.
|
| I don't see the big deal here. Error boundaries,
| suspense, context, very popular routing libraries all
| have used components to encapsulate functionality. That's
| to say first party and third party functionality in the
| React ecosystem have gone down this path.
| [deleted]
| orenelbaum wrote:
| We are not trading some complexity here for some
| complexity there. We are trading a huge amount of
| complexity for a framework that is simpler by an order of
| magnitude. Simplicity is one of the really undeniable
| benefits of Solid once you gain a decent understanding of
| the framework. React at times might appear simple on the
| surface but the overall complexity is pretty huge
| compared to Solid.
| wokwokwok wrote:
| I believe there's a finite, fixed amount of complexity in
| problems; that there is, categorically, no way to solve
| problems without that amount of complexity that is
| inherently part of the problem domain.
|
| So, what you have here _does not_ remove complexity from
| problems, it _moves_ the complexity from one place to
| another.
|
| So, when you have a _simple_ task, and a straightforward
| framework, what you see is "it's easy!". ...because when
| you use the complex framework you get a bunch of
| "solutions" to problems that don't exist on your problem.
|
| That's why it appears overly complex.
|
| ...but for a _complex_ problem, when all you have is a
| simple framework (like <For...>) you have to implement
| the complexity _yourself_ , which makes you view the
| framework as feeble and under whelming.
|
| So, you _are_ just moving the complexity from one place
| to another; the question is, is the complexity of react
| really something most people need, or can a framework
| like solid solve the 90% of simple problems most
| developers have?
|
| It's hard to tell.
|
| Most new frameworks excel at solving simple problems
| because it makes for cute demos.
|
| Is solid any different?
|
| That's my question. How does it work at scale, for large
| complex projects? Is there a whole design system
| implemented in it? Who's using it and for what?
|
| The claim that it's "not complex" doesn't help.
|
| All that means is there are probably a crap load of
| things it doesn't include I'll have to do myself.
|
| There _is no magic bullet that removes complexity from
| tasks_.
|
| React is a complex beast, and a nice clean framework to
| replace it would be welcome.
|
| ...but you have to approach this kind of discussion
| honestly.
|
| Hello world examples are a dime a dozen.
| thatswrong0 wrote:
| I feel like if it were actually an order of magnitude
| less complex, it would be eminently obvious from a blog
| post about it? Maybe I'm just tired and don't "see it"
| for whatever reason, or maybe I need to find some better
| examples.
|
| From the moment I saw a post about immer.js, I was sold
| because it seemed like an obviously better solution for
| the vast majority of cases where I would otherwise grab
| Immutable.js, a library that I wanted to like but
| inevitably struggled against.
|
| This.. isn't quite as revelatory. I'm not saying it's not
| all that you claim it is, it's just that from a glance, I
| don't see how this somewhat different approach addresses
| the problems I run into often with React in a major way
| (beyond the claimed performance boost).
| fpoling wrote:
| immer.js can have terrible performance for data
| structures starting already with 100 of elements. Using
| JS proxies is not cheap.
|
| We have found that continuing to use immutable.js Map and
| List but using plain JS objects, not Records is sort-of a
| sweat spot. But one needs to enforce immutability with
| Flow/TypeScript read-only types and use the latest
| immutable.JS to make it work.
| leonardopainter wrote:
| My library (see other comments) has components that are
| about half the amount of code as react or solid and in
| pure javascript. The javascript shows exactly was is
| happening, as opposed to the "simplicity" of react that
| shows a pretend version of what is going on, then 5 years
| later people discover that is a bit of a problem and now
| we are onto the next library (solid?).
|
| I wonder if I could have your opinion on my library, and
| why half the code, native performance is actually more
| complicated in the long-run. I don't know the answer at
| the moment. Documentation isn't complete... it is just
| web components. eg hello world just becomes a function
| like const component = hello('Andrew');
| document.body.append(component); in the example on
| github. Anyway, the todo shows a more typical real world
| example I guess.
| jbreckmckye wrote:
| Likewise I simply don't empathise with the author's complaints.
| Hooks make sense if you think in closures. Hooks are isolated
| so you can think about them in isolation.
|
| What I like about the React monoculture is that it's one less
| thing I have to care about. I can focus on the other aspects of
| my programs, beyond turning JSON into HTML.
|
| I haven't used SolidJS so I'm not going to put it on blast.
| However, hearing people compare its reactivity model to
| Knockout JS gives me the heebie-jeebies, because Knockout
| projects were horrific to reason about (and test) beyond a
| certain scale.
| andrewstuart wrote:
| I tried several React alternatives.
|
| At this stage, size of community is a really important factor,
| overriding many other factors.
|
| It's just incredibly important for there to be tools support,
| questions answered on stack overflow and a community of people
| developing related software.
|
| At this stage there's only really VueJS, Angular and maybe one or
| two others with community large enough to justify changing.
| rglover wrote:
| Just started back in October, but you can talk to me directly
| and get questions answered pretty quick:
| https://github.com/cheatcode/joystick
| continuational wrote:
| How is the setInterval cleared when Counter is no longer
| rendered? It seems like a leak.
| bgirard wrote:
| It's certainly a leak. That setInterval is going to be holding
| the closure context alive which will reference the component in
| many frameworks.
|
| The setInterval will also keep firing causing, wasting CPU and
| battery.
|
| It's hard to take any examples here seriously without showing
| proper cleanup that would pass code review.
| sanitycheck wrote:
| Good to see other people spotted that, I noticed it
| immediately and had a "there's a bug! a bug!" alarm bell
| ringing in my head throughout the rest of the article. I may
| have some sort of setInterval related PTSD.
| tobyhinloopen wrote:
| I always wonder why all JavaScript client-side frameworks have
| such distinct design.
|
| No other dev environment for building GUIs has react-like
| components.
|
| What's so special about the web that we keep creating frustrating
| frontend frameworks for?
| gman83 wrote:
| Flutter, Jetpack Compose, and SwiftUI all have React-like
| components.
| pevey wrote:
| I personally love the front end frameworks, and I don't find
| them frustrating at all. Knockout was a workhorse until angular
| came along. And then vuejs. And now I use sveltekit for pretty
| much any web app.
|
| The frameworks are popular because you can build things
| incredibly quickly once you know the ins and outs of your
| framework of choice. The component-style design, the endpoint
| design, so much is just driven by the needs of web-based
| development and the framework creator's preferred way of
| abstracting away some of the challenges.
| Scarblac wrote:
| The browser was intended to render documents, not applications.
|
| In particular, HTML has a tree structure, which means that
| things that are semantically related on the page and update
| together are often miles away from each other in the tree.
|
| And the page in the browser is part HTML, part CSS, part
| Javascript. Frameworks try to let the developer work in JS only
| and generate the rest.
|
| And finally, much of the application's state is often kept in a
| backend, and access to it a asynchronous.
|
| I think that's why Web development is so distinct from other
| UIs.
| leonardopainter wrote:
| One reason is probably that creating UIs programmatically was
| historically very cumbersome in JavaScript due to various
| issues that are no longer relevant. That means everything had
| to be HTML-based hybrids of some sort.
| rk06 wrote:
| Because there are a lot many js devs than others. Hence js
| ecosystem is significantly larger.
| mdoms wrote:
| What was wrong with the class component? It was very
| understandable and predictable.
| thatswrong0 wrote:
| Class components are fine for the simplest examples, but the
| moment they start increasing in complexity, they become a bit
| of a mess. Sharing functionality across multiple components
| becomes tricky with class components (with the only real option
| being HoCs / render props). You necessarily have to spread
| logic across different lifecycle methods.
|
| Hooks allow you to bundle code together by functionality, and
| consequently allow you to easily extract and share said
| functionality in a very composable way.
|
| This is my go to for visualizing the difference:
| https://i.imgur.com/e9K8vfz.gif
| ctvo wrote:
| > Hooks allow you to bundle code together by functionality,
| and consequently allow you to easily extract and share said
| functionality in a very composable way.
|
| You're using React. The mechanism that enables code
| reusability is through composing components.
|
| There's nothing wrong with class components even for the most
| complex logic. The only downside is the community has moved
| on and mostly adopted hooks and functional components.
| thatswrong0 wrote:
| > The mechanism that enables code reusability is through
| composing components
|
| If you think that this: return (
| <Apple> {({ apple }) => ( <Slicer
| slice={apple}> {({ sliced: slicedApple } =>
| ( <DinnerPlane contents={slicedApple} />
| ) } </Slicer> )}
| </Apple> );
|
| is more desirable than this: const apple =
| useApple(); const slicedApple = useSlicer(apple);
| return <DinnerPlate contents={slicedApple} />;
|
| Then go for it I guess.
|
| Although you'd have to somehow ignore the fact that you'd
| end up with an even bigger mess if you want these
| intermediate functionality steps to interact with the
| parent component in a non-trivial way, ..
|
| Needless to say, I have written such render-prop and
| "renderless" components in the past, and I see very little
| upside compared to hooks.
| masterofmisc wrote:
| Thats interesting. So in your 2nd example, am I right in
| saying the variables 'apple' and 'slicedApple' are react
| JSX that you are ultimatly passing through to
| <DinnerPlate/> to render on the screen? If so, yes, that
| is fairly intuitive.
| thatswrong0 wrote:
| 'apple' and 'slicedApple' would more likely be strings /
| objects / arrays in the real world. Maybe this still
| woefully contrived version is clearer?
| function FacebookComment({ commentId }) { const
| comment = useGetComment(commentId); const likes =
| useGetLikes(comment); return (
| <div> <span>{comment.text}</span>
| <span>{likes.length} likes</span> </div>
| ); }
|
| I don't think deal with more braces right now to bring
| the alternative into existence unfortunately
| masterofmisc wrote:
| Ohh i see. Yes, that makes sense. Thanks for taking the
| time to reply.
| ctvo wrote:
| ??? <DinnerPlate>{...map <Slicer><Apple
| /><Slicer/> }</DinnerPlate>
| tinganho wrote:
| I think in the class world this is normally done by writing a
| service and injecting it on the constructor of the parent
| class. Since, React doesn't have DI built-in, it becomes
| problematic with the injection. hooks are essentially classes
| imo.
| arcosdev wrote:
| How does it become problematic? You just pass in
| dependencies as arguments to functions or components.
| extheat wrote:
| Thanks for the viz, haven't done React in a while so it's
| interesting to see how things have improved. The new paradigm
| seems alot better modularized and the logical structure seems
| easier to follow, combined with it taking advantage of newer
| JS features.
| dboreham wrote:
| Unnecessary coupling...something...something...
| arcosdev wrote:
| Because classes as a language construct are one big massive
| footgun on nearly every level.
| llamataboot wrote:
| Honestly my hope (and I admit as a full-stack but leaning back-
| end developer to be biased against JS) is that the future is in
| things like turbo-stream, stimulus reflex, phoenix liveview etc -
| or in things like all_futures (essentially an ActiveRecord
| wrapper around kredis) - that we move towards building reactive-
| apps by firing off events from the back-end and figuring out how
| to subscribe to them on the front-end
|
| the amount of confusing boilerplate I've seen to keep updated and
| maintained when a JS framework is loading front-end state by
| making API requests against a backend and then trying to figure
| out how to keep those in sync when we could just be firing off
| SSR HTML over the wire and/or very thin events that FE components
| can subscribe to or emit for literally no gain in functionality
| is beyond me
|
| even better, just add reactive sprinkles over what you need
| reactive and do the rest with standard MVC/REST patterns, if most
| of what you are using react for is glorified forms, you don't
| need react for that! user your reactive sprinkles of notification
| toasts, and chat channels...
| rezonant wrote:
| What about apps that have no backend? What about apps that
| should work both online and offline?
| lawrencechen wrote:
| ^ What about Figma? Photoshop? Not everything is only a CRUD
| app.
| llamataboot wrote:
| I'm not saying there are no use cases for a JS framework, and
| I have a few I like, just that the switch to rails api
| only/separate react app has in almost every case I've seen
| added tons of complexity without a clear win
| mst wrote:
| Those are very different applications and the trade-offs
| involved are completely different.
|
| In the -common- case OP seems to me to have a valid point.
| lbj wrote:
| Almost every criticism of React that I've read, goes away when
| you drive it from Clojurescript. If you haven't had the pleasure
| I suggest you take it out for a spin.
|
| Example of a full blown React component in Clojurescript:
| (defn counter [] (let [state (r/atom 0)]
| (fn [] [:div {:onClick #(swap! state inc)}
| "The count is: " @state])))
| imtringued wrote:
| Reminds me how vanilla hibernate is unusable but
| Grails'/Groovy's GORM (built on Hibernate) is absolutely
| fantastic.
| alephnan wrote:
| As part of my annual routine, I'm exploring the "latest and
| greatest" JavaScript UI library. Solid.js's performance seemed
| compelling. 15 minutes into documentation and this is what I
| encountered. Can you guess which one of the ChildComponent*
| updates when the text input on the parent component is updated,
| and the props passed to the child? export default
| function ParentComponent() { const [value, setValue] =
| createSignal(""); return ( <div>
| <ChildComponent value={value()} /> <input
| type="text" oninput={(e) => setValue(e.currentTarget.value)} />
| </div> ); } const ChildComponent1 = ({
| props }) => <div>{props}</div>; const ChildComponent2 =
| (props) => { const value = props.value || "default";
| return <div>{value}</div>; }; const ChildComponent3 =
| (props) => { return <div>{props.value ||
| "default"}</div>; }; const ChildComponent4 = (props)
| => { const value = () => props.value || "default";
| return <div>{value()}</div>; }; const ChildComponent5
| = (props) => { const value = createMemo(() => props.value
| || "default"); return <div>{value()}</div>; };
| const ChildComponent6 = (props) => { props = mergeProps({
| value: "default" }, props); return
| <div>{props.value}</div>; }; const ChildComponent7 =
| (props) => { const { value: valueProp } = props;
| const value = createMemo(() => valueProp || "default");
| return <div>{value()}</div>; }; const ChildComponent8
| = (props) => { const valueProp = props.value;
| const value = createMemo(() => valueProp || "default");
| return <div>{value()}</div>; };
|
| The answer is 3, 4, 5, 6. My takeaway is this: there are multiple
| ways of doing it right, but also a handful of gotchas. The only
| way to be safe is to keep the mental model of these partitions
| while you develop, test, debug, and code review. As a code
| reviewer, you can easily accept the wrong code. For now, I remain
| skeptical of Solid.js as solving the complexity woes of Reactive
| programming. I'm not sure React.js is better.
| ryansolid wrote:
| Or Vue either to be fair. Similar rules in the Vue's setup
| function. It's how reactivity works in JavaScript. Basically
| don't destructure or access values out of of primitives or JSX.
| That's basically the gotcha.
|
| Unfortunately it's the price you pay for portability thus far.
| You can build your own language around this like Svelte but
| then composability is limited (need to rely on other
| mechanisms). You can make the updates coarser grained like
| React but then you need a different mechanism(like VDOM
| diffing) to apply updates granularly. I imagine this situation
| improves in the future but we haven't gotten there yet.
| masterofmisc wrote:
| So, its React with the sharp edges smoothed away. Interesting. I
| am not a web developer, so forgive me if this is a stupid
| question, but can someone tell me, if you decided to use Solid.js
| as opposed to React, can you still make use of all the 3rd party
| React UI frameworks out there? Is it compatible with React in
| that sense?
| jorroll wrote:
| Unfortunately, you cannot use React code inside Solidjs[1] so
| you cannot make use of the huge ecosystem of react UI
| components/libraries. It isn't compatible in that sense.
| However, there is an "official" option[2] for including Solidjs
| code inside React. [1]:
| https://www.solidjs.com/guides/faq#is-there-react-compat%2C-or-
| some-way-to-use-my-react-libraries-in-solid%3F [2]:
| https://github.com/solidjs/react-solid-state
| masterofmisc wrote:
| Ahh right. I see. Thanks for the info and the link.
| dheera wrote:
| Every time I see stuff like this
| componentDidMount() {
|
| I get driven away from React. It looks haphazard. Seriously? What
| about componentDidntMount() {
| componentWantedToMountButDidnt() {
|
| ...
|
| I'm used to clean naming conventions like void
| Component::on_mount() { .... }
| cosmotic wrote:
| Maybe the name is trying to communicate it happens after the
| component mounted instead of just before
| dheera wrote:
| `on_mount_complete` sounds more professional
| cosmotic wrote:
| Agreed; the existing name is not great.
| yuchi wrote:
| The reason behind this different naming convention comes from
| the diversity in experiences of the original team. This
| will/did prefix instead of "on" comes from Mac OS X/iOS
| patterns and allows the name to convey the "when" of the
| listener. It is not "during component mounting" it is "after it
| did".
| Jach wrote:
| I guess this is just a limitation of JS the language showing
| itself. Other languages have actual aspect-oriented support
| where before/after/around methods are very clear name-wise
| and semantics-wise (if not always so clear without tooling
| support what happens if you come across a 'mount()' call).
| Maybe it's time for a new JS framework! /s
| vertex-four wrote:
| Which languages in common industry use in 2022 have
| language-integrated aspect-oriented programming support?
| Jach wrote:
| Fair point. I hinted with the idea of a new framework
| that you may be able to bolt something acceptable on top
| of JS (I'm sure it's been done already in the past with
| some framework) especially if you just want the
| before/after/around advice features of AOP without other
| stuff. Or perhaps go into custom syntax transpiled to
| JS/TS-then-JS since no one seems to mind heavy build
| processes these days. For the most common industry use,
| I'd have to say it's still Java's Spring AOP/AspectJ.
| Maybe it's not language-integrated, but it's pretty
| close.
|
| For an uncommon use example of what could be possible:
| (defmethod react.component:mount :after ((self counter))
| ...) ; instead of componentDidMount (defmethod
| react.component:update :around ((self counter)) ...) ;
| instead of shouldComponentUpdate (defmethod
| react.component:unmount :before ((self counter)) ...) ;
| instead of componentWillUnmount ; (the
| react.component namespace qualifier could be whatever
| else and not necessarily typed out)
|
| However closely you integrate it with the language,
| having that machinery generally available seems better
| for naming and for providing new lifecycle functionality,
| without everyone having to reinvent the wheel and provide
| it in different incompatible ways. But it's clearly not a
| big issue.
| [deleted]
| JonathonW wrote:
| When does on_mount run?
|
| React's componentDidMount() is a lifecycle method that runs
| after a component mounts, once it's been inserted into the DOM.
| This is in contrast to componentWillMount() (now
| UNSAFE_componentWillMount(), because it breaks when async
| rendering is enabled), which is called _before_ the component
| mounts.
|
| This naming scheme becomes even more important for the update
| lifecycle methods-- in addition to componentDidUpdate(),
| there's a shouldComponentUpdate() called before it (where you
| can return true/false to tell React whether or not to proceed
| with the update) and UNSAFE_componentWillUpdate(), called
| between those two.
| unfocussed_mike wrote:
| componentIsNotThatBotheredButStarSighStarIfIMust() { ... }
| qbasic_forever wrote:
| Well, modern react is pushing folks to use the hooks model
| which jettisons the whole componentDidMount and other class
| functions. Now you use a side effect hook:
| https://reactjs.org/docs/hooks-effect.html This is a little
| more clear that it's for side effects of the component being
| put in the DOM, but it does require a bit more knowledge of
| react and hooks.
| StevePerkins wrote:
| The author lost me in the introduction.
|
| > _" Ohhh, an OO pattern with a couple of one-liner lifecycle
| methods is just WAY too much code! Higher likelihood for errors
| and worse developer experience."_
|
| ...
|
| > _" So instead, I'm going to replace this with a functional
| pattern, that crams a couple of lifecycle functions into a
| closure, and is riddled with edge cases and common developer
| mistakes."_
|
| This article perfectly crystalizes why my career has tracked
| toward the backend over the past decade. All of the virtual ink
| in this article, and honestly most of the complexity in the field
| overall... and it seems to really all just boil down to, _" I
| think this looks cooler."_
| nawgz wrote:
| A factor of two reduction in LOC and an elimination of almost
| all boilerplate is justifiable in itself. I don't know where
| the author said "I think this looks cooler"
| rr808 wrote:
| True but backends are not always refuge. The back end Java
| version at my company would have a DI container, a few
| interfaces, factories, configuration files, custom attributes
| and a few random library dependencies thrown in.
| mabbo wrote:
| > "I think this looks cooler."
|
| You're using this straw man to demean the author, but I think
| you miss an interesting point: it can be very hard in software
| developer to articulate the good and bad. "Uncle Bob" refers to
| this as "code smells", where you can't quite say immediately
| what's wrong here, just that you don't like it much. Something
| smells bad.
|
| And maybe the point of Solid is to point out a mistake React
| made in their implementation of hooks. Hooks were badly needed,
| no doubt, but often times an okay solution to a really serious
| problem can look like a great solution.
|
| The back end went through a lot of this already. That's why the
| patterns are more stable there, and why you feel less churn.
| The front end is exciting precisely because there's so much to
| still figure out!
| austincheney wrote:
| Super subjective.
|
| To people who know what they are doing more code than
| necessary to accomplish a task is the code smell.
|
| To people who are super insecure vanity code is required
| because patterns are memorized, so any deviation from the
| unnecessary boilerplate is the code smell.
| notpachet wrote:
| > To people who know what they are doing more code than
| necessary to accomplish a task is the code smell.
|
| While I agree, I think a lot of developers are
| oversensitive to boilerplate, sometimes to their own
| detriment. And the effort to shave off boilerplate quickly
| runs into diminishing returns. Beyond a certain point you
| end up with code that is harder to use because of the
| layers of abstraction you've added to avoid the last-mile
| developer writing unnecessary boilerplate.
|
| But I am a touch typist, whereas I'm noticing more and more
| developers who are not, so maybe there's something there.
| thomascgalvin wrote:
| UI development seems determined to repeat every mistake we've
| made on the backend over the past thirty years, while adamantly
| refusing to ask us about any of those mistakes.
| pier25 wrote:
| Care to elaborate? What mistakes are you referring to?
| nawgz wrote:
| None in particular, it's just a classic jibe from those who
| dislike UI frameworks because they don't use and thus don't
| understand them
| jakelazaroff wrote:
| I don't think there's much overlap between the two, besides
| general programming best practices.
|
| In my experience, backend development is often simpler
| because you can move any state out of your own code into
| dedicated external components, like databases and queues.
| With frontend code, you _have_ to manage state; there's
| nowhere else for it to go.
| jimmont wrote:
| I didn't find the word "think" in the article. Did you mean
| "feels like this looks cooler"? Feeling does appear to be the
| prevailing way decisions are made and put forward in the
| community. I think that's a problem. And one that won't be
| going away anytime soon.
| contravariant wrote:
| Seems a bit odd to call the version that repeatedly calls the
| constructor an OO pattern.
| phailhaus wrote:
| The OO pattern is far worse, and it's easy to show why: there
| is only one lifecycle method of a type for each class. This
| means that when you have a set of related behaviors, you have
| to _split them up_ across several lifecycle methods and keep
| them in sync. Sure, that 's fine if you just have "one-liners",
| but software grows, and over time your class will become
| difficult to maintain as each of those lifecycle methods start
| managing several different behaviors, all interrelated. With
| hooks, this isn't a problem: each set of behaviors can be
| encapsulated by a single hook that handles all lifecycle events
| together. This can be further abstracted into its own function,
| which allows them to be trivially reused in _any other
| component_. It 's simply not feasible in OO patterns.
|
| I think if you actually used hooks, you'll notice this
| immediately. It's not a matter of "looking cooler", a lot of
| language theory went into making UI development functional and
| less stateful, which in turn makes it far easier to manage
| complex applications. A small team can maintain a pretty huge
| beast if using hooks effectively.
| christophilus wrote:
| I've been in the industry since the days of VB6 (which I
| loved). I've never been more productive than I was with VB6 and
| WinForms. That said, UI has _always_ been a mess, even then.
| The more feature-rich you want your UI, the gnarlier and
| messier it gets.
|
| Everyone always likes to blame the front-end engineers for
| being slovenly, but my experience is that; UI is just messy.
| It's just hard to program cleanly.
|
| Not to mention, modern UIs are generally more complex than the
| old VB days (at least, my programs are): they have to adjust to
| various screen sizes. They are almost always client/server apps
| and need to account for more failure modes. They are built on
| top of a mess of a document layer that was never intended to be
| an application layer.
|
| This last point is _the_ reason the front-end space has so much
| churn. It 's still an unsolved problem, and may never be well-
| solved, but I'm glad folks are trying to solve it. React was a
| step-change for me in terms of building better UIs. I'm looking
| forward to the next step-change.
|
| Lastly, before someone makes the argument: no; we aren't going
| to stop building applications on top of the DOM + CSS. Not
| until someone comes up with an alternative that gives us the
| same ease of distribution and broad base adoption.
|
| Edit: I should note, I'm a full-stack dev, and have been more
| back-end than front-end for most of the early part of my
| career. The backend is _always_ easier for me at least, but I
| don 't think it's because front-end devs are hipsters.
| [deleted]
| _fat_santa wrote:
| Back when I studying CS and as Junior, I would laugh at memes
| about "Frontend vs Backend" where they described the Frontend
| as this pretty pasture and the Backend as this god forsaken
| place of spaghetti code.
|
| In a way I find this meme even funnier now because of how
| backwards it is. Often times it's the backend that's really
| clean and organized and the frontend is a hot mess.
| svachalek wrote:
| I've also been doing both sides since the 90s and it's funny
| how people speak of "just" frontend coding. It has lots of
| async/parallel issues with messy constraints, and it's the
| dumping ground for dirty data and error handling issues. It's
| often done poorly, but doing it right is a very complex
| problem.
| frolicker wrote:
| I have been in the industry since punch cards were a thing
| and servers took up multiple rooms. I've never been more
| productive. UI has gotten a lot better since those days and I
| have migrated my efforts to use frameworks such as Vue.js
| which is sofar the most elegant and modern approach for doing
| UI work. Creating a desktop app is very easy with electron js
| although beit a bit heavy and not the most effecient in terms
| of memory, cpu cycles, etc but it's easier than punch card
| days I used to enjoy.
| muttantt wrote:
| Hard to beat Vue, especially when combined with Quasar
| Framework. The absolute simplest way to deliver SaaS and
| enterprise apps.
| bradly wrote:
| VB6 was great. I also really enjoyed RealBasic for desktop
| apps on the Mac. It just worked. Network programming with
| sockets was so simple. Now I open XCode and am completely
| overwhelmed.
| marcellus23 wrote:
| > UI is just messy. It's just hard to program cleanly.
|
| I'm an almost entirely frontend dev (iOS + macOS now, web
| development in the past) and this is what I've come to
| believe. It's easy to program UI cleanly if it's extremely
| basic or not very usable -- but the second you want an
| animated transition between states, or to remember what the
| user checked on the last page so that you can keep it checked
| on this page, or any number of other things that you need to
| do if you actually want people to _enjoy using your
| software_, it gets much harder.
|
| My take is it's because building UI is building software for
| humans, and humans often want behavior that doesn't allow for
| clean abstraction. Backend dev is more about building for
| other software -- not that it's easier, just a different set
| of problems.
| thr0wawayf00 wrote:
| > My take is it's because building UI is building software
| for humans, and humans often want behavior that doesn't
| allow for clean abstraction. Backend dev is more about
| building for other software -- not that it's easier, just a
| different set of problems.
|
| Never really thought about it this way but I completely
| agree
| gorjusborg wrote:
| When you say it out loud, it all makes sense.
|
| UI developers focus on user interface, and much of that has to
| do with looks, style, and personal ergonomics. In a way, it
| makes sense that the engineers steeped in this type of problem
| set would be oriented to thinking this way. Even if they aren't
| initially, the probably will be over time.
| frolicker wrote:
| prea wrote:
| > All of the virtual ink in this article, and honestly most of
| the complexity in the field overall... and it seems to really
| all just boil down to, 'I think this looks cooler.'
|
| IMO there's significant complexity in building a feature-rich
| frontend client. The "thicker" the client, the worse it gets.
| There's definitely a lot of 'I think this looks cooler' going
| around, but also we shouldn't forget that the need to come up
| with something better is partially a response to very real,
| very-not-imagined, frontend complexity.
| usrbinbash wrote:
| > IMO there's significant complexity in building a feature-
| rich frontend client.
|
| Doing complex things is always complex, but when SIMPLE
| things are complex, then something is going very wrong.
|
| And this is exactly where we are with most JS frameworks
| these days. Layer upon Layer of abstraction, and instead of
| the complexity the dev has to deal with decreasing as a
| result of it being abstracted into frameworks offering simple
| interfaces, complexity increases.
| nawgz wrote:
| > this is exactly where we are with most JS frameworks
| these days
|
| Have you been saying the same thing since 2014? JS
| frameworks have never been simpler, never been more
| discoverable thanks to TS, and there are plenty of levels
| of abstraction a developer can put between themselves and
| vanilla JS. But even calling React too-far-abstracted-to-
| be-simple is comical; it's a simple system offering
| composition of components.
| notpachet wrote:
| _Sips tea and happily keeps writing class components with Redux_
| steve76 wrote:
| bstar77 wrote:
| This is really interesting. I'm happy the author covered the
| effects side of things because this is where I've had some
| challenges with non-trivial React apps. Sometimes effects can be
| very complicated and result in React getting stuck in an infinite
| loop.
|
| Before you say it's because I'm "doing it wrong", Material UI's
| website had this problem for quite a long time. That issue
| required doing manual refreshes to not trigger the infinite loops
| (something you would only see in the debugger). This problem in
| reactivity is a issue in React that even the best devs can
| struggle with. My solution was simple... use useEffect less.
| Depend less on reactivity.
|
| The bottom line for me is that I feel like I can accomplish
| anything in React, but the devil is in the details. There are so
| many scenarios that I would need to vet with Solid.js, but if it
| works better at managing a complex app's reactivity, it could be
| very compelling.
| andix wrote:
| Did anybody use Observable Hooks yet? https://observable-
| hooks.js.org/
|
| This seems to be quite a good way to compute and apply complex
| state to a component. In my opinion better than useReducer().
|
| But to be honest, for most components useState() and useEffect()
| are totally enough. And if you do something wrong like in the
| counter example, you see it right away.
| parentheses wrote:
| This article hits on something I've felt for a long time. The
| idea that "hooks are superior" to me is ridiculous. If a linter
| is required to tell me when I'm writing a bug that is not
| immediately obvious, that is a failing in the framework to round
| those edges. Lints are not rounded edges!
|
| Solid is nice and _seems_ to fix the issues with hooks, but as
| another comment mentioned, the challenge is with building at
| scale. It's unclear to me how this scales and where the sharp
| edges are.
|
| React IMO trades off performance in exchange for ergonomics.
| These ergonomics bear fruit early on, but you start dealing with
| this debt very quickly. As "nice" as Redux is, I shouldn't need
| it so early. React is designed in a way that results in pretty
| terrible performance. I once wrote a React app, and discovered
| perf issues 2 weeks in. Any UI framework I used in the past would
| have scaled beyond this point without having to have the data
| layer rewritten. Frameworks of the past also had what seemed like
| way less "magic".
|
| I totally accept that it's seriously nice to write, but how many
| trees has React alone burnt?
| deckard1 wrote:
| React traded one set of footguns for another set. This is also
| _after_ they fudged with the class component lifecycle methods
| before tossing in the towel on that entire API.
|
| > If a linter is required to tell me when I'm writing a bug
| that is not immediately obvious, that is a failing in the
| framework
|
| yep. They also commandeered the entire use* namespace _just_ so
| they could get lint to warn when you put a hook outside the
| start of a function. Hacks on top of hacks.
| schwartzworld wrote:
| > If a linter is required to tell me when I'm writing a bug
| that is not immediately obvious, that is a failing in the
| framework to round those edges.
|
| Isn't the point of static analysis (including linters) that
| they catch those kind of bugs? Having that little red underline
| (or console warning) saves a lot of pain.
|
| Hooks have completely changed the way I write React code. It's
| so much easier to test and reason about. Really the only
| problem is that the guardrails aren't more heavily enforced.
| ipnon wrote:
| React would work well as a compiled to metal language. Instead
| we end up with React on Typescript on ES6 on ES5 on the browser
| that _still_ only has one language targetable. We 're shackled
| to a rocketship in motion desperately monkey patching the
| engines.
| mwcampbell wrote:
| We can at least eliminate ES5 now that IE is dead.
| nobleach wrote:
| >"If a linter is required to tell me when I'm writing a bug
| that is not immediately obvious, that is a failing in the
| framework to round those edges".
|
| I do not want this handled at the framework level though. There
| are plenty of times in my day-to-day where that linter is
| wrong. If I were to add one of the dependencies (it's sure I
| should add) my component would re-render over and over. Sure,
| one could argue, "well, then you've poorly architected your
| code"... but THAT is where I feel like the failure occurs.
| Having to do write my code to please a paradigm. What that
| means is I only "sorta agree" with the design trade-offs. And
| much like Ruby on Rails, you either go all in, or spend your
| days hating the framework.
|
| I do worry that Solid also has these "If you know, you know"
| edges though. So I'm trading looking at a function and assuming
| it'll run over and over with, looking at a function and
| thinking, "how can I make this thing run again when it needs
| to?" I'm not saying it's wrong, it's just another piece of
| tacit knowledge one has to learn when adopting a new framework.
| joshribakoff wrote:
| Read the hooks FAQ, the linter is not wrong, you are :)
| https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-
| omit-f...
| draw_down wrote:
| oaxacaoaxaca wrote:
| I have the same complaint about hooks. Most people seem to
| ignore that tidbit, but to me it's really frustrating. Plus I
| recently hit more hook issues when putting a setInterval inside
| a useEffect. There's no way to do a normal didMount/willUnmount
| workflow without other hacks (i.e. useRef) just to set up a
| simple timer. Maddening!
|
| Edit: after writing this I went and read the article. Same
| scenario I was bitching about lol
| robertoandred wrote:
| Sure there is. Set the interval on mount, clear it on
| unmount: useEffect(() => { const
| interval = setInterval(() => { // whatever
| }, 1000) return () => {
| clearInterval(interval); } }, [])
| mastersummoner wrote:
| I think I ran into a very similar issue recently too, stale
| closures right? didMount/willUnmount worked perfectly, but
| useEffect got screwy very fast, even posted a SO article
| trying to see the best workaround, nothing great.
| littlecranky67 wrote:
| People always use the setInterval() issue as a footgun. The
| real footgun is people not reading the documentation for the
| framework they use, because the exact example is handled in
| the official react docs [0]. I always advice aspiring react
| devs to understand _why_ this exact setInterval() doesn 't
| work (and why there is the need for the rule-of-hooks),
| because it will automatically create an understanding how
| hooks and react itself works.
|
| [0]: https://reactjs.org/docs/hooks-faq.html
| tshaddox wrote:
| Also in most of these cases, the "natural" way people would
| prefer to write code for an interval would likely have very
| unclear semantics, particularly if the interval delay is
| coming from somewhere else such that its value can change
| (like component state or props).
| dataviz1000 wrote:
| I strongly recommend everyone to read A Complete Guide to
| use Effect[0] blog post by Dan Abramov. He 3 years ago
| addressed this exact problem and how useEffect solves it.
|
| [0] https://overreacted.io/a-complete-guide-to-useeffect/
| toshk wrote:
| When I started with classes, I hardly had to read the docs,
| few hours and was good to go. For many developers I worked
| with at the time this was the case.
|
| React was easy coming from jQuery, Backbone other
| frameworks at the time.
|
| With effects, i've read the docs many times. I still don't
| fully understand how it's supposed to work.
|
| I don't seem to get the feeling / abstract concept behind
| it and it still surprises me at times when it fires / or
| not.
|
| Too much magic for me. But maybe im getting old :).
| mosdl wrote:
| Same, I just use classes for anything that needs more
| than a few lines of business logic.
| littlecranky67 wrote:
| Well if you do not want to read the docs, go with vanilla
| JS ;) Seriously, no matter what you use, read the docs.
| Arguing that a library should not require you to read the
| docs is just nonsense - cause any library makes decisions
| about abstractions for a reason. If you do not want/need
| those abstractions, do not use the library blindly. It is
| always the case that you should now and agree with those,
| that is why you use the library in the first place. So,
| read the docs, please.
| anamexis wrote:
| Ok, but surely it's a good thing when frameworks are
| intuitive?
| furyofantares wrote:
| The post you're replying to says they've read the docs
| many times.
| a2800276 wrote:
| In their defense, they said "read the docs" not "read the
| comments"... :D
| oaxacaoaxaca wrote:
| Right there with you. I've been building React apps full
| time since 2016. I used to convince people to switch to
| React because of how easy it was to learn and how quick
| it was to get through the docs. Props, state, setState,
| done.
|
| I've built some really complex frontends with React. But
| now here I was, struggling with setInterval, ha.
| dsego wrote:
| This is my understanding, but I just use hooks, don't
| know the implementation details. Pure react functions
| receive props and render output. Each time the component
| is rendered (basically a function call), it reads the
| props and spits out some DOM nodes (simplified). But you
| loose the ability to have lifecycle events. So they
| invented a mechanism that keeps some hidden state that's
| tracked for us behind the scenes, and we can then "hook"
| into that lifecycle state.
|
| The main issue is that it's not a native language
| construct, but a mini-dsl sort of so you need to have
| this state machine in mind even thought it's implicit and
| hidden from you.
|
| Instead of reading the docs, you might want to search
| online how to write hooks from scratch. It's one of those
| concepts that needs to click.
| stickfigure wrote:
| I had the opposite experience. I started with classes,
| and anytime I had to do anything even slightly
| complicated I had to go running for the docs. The
| lifecycle methods are byzantine and frequently require
| not only overriding the method, but checking the values
| of parameters to determine the proper sequence of
| operations.
|
| In contrast, useEffect() is "exactly what I want" without
| having to figure out what combination of lifecycle
| methods to implement.
|
| I'll grant you that this could have been done differently
| - I'm not a fan of the "order of calls represents hidden
| state" mechanism for hooks. It's possible to imagine a
| _different_ API for class components that provides
| ergonomics similar to useEffect() and useState(). But
| hooks are still an improvement over the old class
| component API.
| jameshart wrote:
| I don't think complaining about needing a linter makes sense.
| JSX is already a compiled language, so you have a compile and
| build step (doubly so if you're also using Typescript). Think
| of ESLint rules-of-hooks as just a plugin to your compiler that
| further modifies the syntax of JavaScript to include rules
| about when and how you can call certain functions.
|
| Hooks are a _syntactic_ element of react code. Calls to them
| aren 't legal inside conditionals or loops.
|
| Full linting support smooths over that rough edge just as
| effectively as babel handling ?. syntax smooths over its
| absence in certain JS runtimes.
| fpoling wrote:
| React hooks is another attempt to gain ergonomics. The idea is
| to try to spread the virtual DOM into native effects. In theory
| the code specifies or declared the effects once and the
| framework takes care about subscribing/unsubscribing as
| necessary. But in practice this became so messy that in any
| complex cases one better stick to classes and explicit
| subscribe/unsubscribe.
|
| The right way to do that exists in Elm. But I do not think
| there is a way to translate that into JS without requiring
| either a lot of boilerplate or very messy code
| neoberg wrote:
| I agree that hooks "can" be messy but in my experience they
| are quite useful and nice to maintain. That is if the code is
| written with maintainability in mind - which applies to any
| code really.
|
| I've been working on a quite complex React codebase for 5
| years now - it's not the biggest but still not so small. I
| was there on day 1. The team that works on it now full time
| is ~15 devs + 10-15 doing some minor stuff from time to time.
|
| We've started using hooks about 1 year after they introduced
| them. Before we were very deep into redux and redux-saga. Now
| most of our codebase uses only hooks for most of the things
| we did with redux before - there are still some redux but
| most major parts are migrated to using hooks and contexts. It
| is probably the best decision we made after switching to TS.
| Most of our codebase is still very easy to maintain. Last
| year I went on a paternity leave for 6 months and I was
| pleasantly surprised how easy it was to adapt back.
|
| Edit: forgot to write about Elm. I like elm a lot -even
| though I don't agree with how it's managed-. I even organized
| a local elm meetup :) But I think while it is very good in
| theory, it's not too easy to scale especially if you plan on
| hiring more devs. Also the way effects and data is completely
| separated from the view is not very ideal for bigger
| projects. You either end up having to touch too many files
| for a single feature or have incredibly big files.
| toastal wrote:
| Oh that's jumping the gun. TEA doesn't compose and you can
| pretend you don't need components until you do and then you
| end up with big mess of hard-to-follow spaghetti code. It's
| not 'bad', and has good use cases but The Elm Architecture is
| not without flaws.
| z5h wrote:
| Elm composes just fine and you can get close to the
| semantics of components. I wrote this over 3 years ago,
| have been using it in many projects with no concerns.
| https://package.elm-lang.org/packages/z5h/component-
| result/l...
|
| There are other ways to achieve similar. You don't end up
| with "big mess of hard-to-follow spaghetti code", you might
| end up with a "large amount of unfamiliar-looking code".
| Getting better at reading a larger-than-anticipated amount
| of unfamiliar code takes a bit of practice, then it isn't a
| problem. And then you have all the benefits of Elm with
| zero problems.
|
| The actual hard thing about code is managing complexity,
| and working with "it just works" magic when it doesn't
| "just work".
|
| I agree Elm has some flaws, and there is an initial up-
| front time investment which is unsavoury to many.
| sbergot wrote:
| Yes hooks are not great. They violate too many functional
| programming rules that the react team pretend to care about.
|
| I still like using them however. I had a few issues when trying
| to do more abstract code.
| jameshart wrote:
| I don't understand why people think react hooks are meant to
| be 'functional'.
|
| They are _highly_ , _deliberately_ , _emphatically_
| procedural.
|
| The order they are called matters! The time of when they are
| called matters! The number of times they are called matters!
| You get a different result from calling the same hook with
| the same arguments at different times! You get different
| results if the call site for them is in different places!
|
| They _do_ enable you to do some things in JavaScript that are
| more easily enabled with higher ordered function stuff in
| functional languages, but there is nothing 'functional' about
| how hooks work or how they are used.
|
| And that's okay! 'Functional' doesn't automatically mean
| 'better' and 'procedural' doesn't mean 'worse'. For what they
| do, hooks (considered as the entire hooks ecosystem including
| linting extensions that help enforce the rules as if they
| were syntax errors) are a very clever extension within
| JavaScript syntax that let you pull off some very neat
| separation of concerns in a reactive code model.
|
| 'Functionalness' has very little to do with whether hooks are
| good or bad.
| Izkata wrote:
| > I don't understand why people think react hooks are meant
| to be 'functional'.
|
| Because when function components first came along that's
| what the whole of React was supposed to be: "functional"
| UI, using things like redux or mobx for state. Plenty of
| guides still use that terminology even though React's
| homepage now uses "declarative".
|
| That said I think they were always misusing the term, I
| remember this because I used to complain to people that
| react itself was declarative, not functional, and just gave
| the option of writing in a functional style.
| svachalek wrote:
| I'm not sure what happened over there but they completely
| lost the plot with hooks. And now you're not "correct" or
| "modern" if you don't use them. They're ... fine, I
| guess. Most of the time. But not at all in line with the
| fairly clean and consistent vision of early React.
| leonardopainter wrote:
| >If a linter is required to tell me when I'm writing a bug that
| is not immediately obvious, that is a failing in the framework
| to round those edges. Lints are not rounded edges!
|
| Those linter warnings with React hooks show just how much of a
| disaster it is. All of the "simplicity" that comes with hooks
| is just complexity that is now completely out of sight, and
| only appears once the code is run in a linter. That is even
| worse than having the complexity in the code.
| cies wrote:
| I like Elm. :)
|
| On the JS/TS planet there's https://cycle.js.org , which comes
| close.
|
| Looks even better than Solid IMHO.
| kccqzy wrote:
| Hooks triggered my code smell detector so bad that I didn't
| even bother finishing the tutorial.
|
| That said, I still preferred React.createClass so I guess I'm
| somewhat off the beaten path when it comes to React.
| brimble wrote:
| Read the implementation of Hooks (in the React codebase) if
| you want a big LOL. They're a slower, partial re-
| implementation of objects with bizarre custom syntax. In a
| language that's already so heavily OO that the functions are
| objects.
| Tade0 wrote:
| Back when they were initially released my teammate started
| rewriting everything in them. Little did he know, if you're
| not careful with hooks, you can severely damage performance.
|
| My take is that if a feature requires a linter to be properly
| implemented then it's obviously giving the developer too much
| rope to hang themselves with.
|
| Also it appears that they were introduced mainly for
| performance, but for some reason sold as the new "better" way
| of writing applications.
|
| I actively avoid React and its ecosystem, because I believe
| there's just too much FOMO and "fashion"(for lack of a better
| word) in what drives its development and not enough
| meritocracy.
| joshribakoff wrote:
| The idea with hooks is a compiler could generate the dependency
| array. The flaw isn't with the hooks paradigm
| ryansolid wrote:
| But those dependencies would be static. This goes beyond
| that. I won't call hooks flawed, they are suitable for
| React's model, but looking at what reactivity does is a
| different sort of thing. It is a subtle difference at first.
| [deleted]
| apatheticonion wrote:
| After working with React for years it is something I would not
| recommend and can only think of limited use cases to use.
|
| You can write really performant software in React, but
| ergonomic (beyond stockholm syndrome) I would not call it.
|
| It's also difficult to implement quality software engineering
| principles in a React application such that an application is
| maintainable, glacable and easy for someone new to a project to
| pick up.
|
| The flexibility in its toolchain is nice, however
| chrisweekly wrote:
| > "glacable"?
| toshk wrote:
| With Class components it was often easier to create Pure
| components, or do a shouldcomponent update check to optimize
| performace. They later introduced memo for functional
| components.
| fatih-erikli wrote:
| "That's a lot of code to write for an auto-incrementing counter"
|
| In reality, you will never need to write an auto-incrementing
| counter :) React gives you a mental framework, you draw a page
| based on the state in a declarative way. The clever abstraction
| you make, the less you write the code, so it's a little bit
| pointless to compare it with an auto-incrementing counter
| application, in reality has no use case at all.
| hsn915 wrote:
| This feels a lot like knockout.js but with a jsx syntax.
| drewrv wrote:
| Knockout.js was/is wonderful, I'm not sure why it never took
| off the way angular or react did. I do appreciate jsx though so
| I'll be looking into Solid.
| hsn915 wrote:
| As far as I could tell, around that time (and even now to
| some extent) the amount of activity on StackOverflow is used
| to measure the popularity of a project.
|
| Angular had a "made by google" kind of logo on its website,
| indicating to many people that it's of high quality and worth
| adopting.
|
| But Angular was also so convoluted and had so many problems
| that so many people kept running into random problems all the
| time and had to ask questions about them on SO. This signals
| (incorrectly) that Angular is popular, driving more people to
| believe it's worthwhile to adopt it.
|
| Knockout had neither. It was not sponsored by a corporation.
| And it was so good that you hardly ever run into random
| problems.
|
| Ultimately it was eclipsed by React and Typescript because
| lack of type checking for the html templates means it's hard
| to scale it will to large projects.
| leonardopainter wrote:
| The problems with knockout were:
|
| very hacky syntax embedded into html. Sometimes you had to
| even use some kind of comment notation because there was no
| entry point into the html to add data properties or whatever
| it had.
|
| it was slow.
|
| the observables weren't variables you could use like plain
| JavaScript variables
|
| it has the same problem as React - state-based algorithms are
| not very good ways to solve problems (if (showDialog && !open
| && ranOnce). You have to keep creating more variables to
| represent more states instead of using normal programming
| language concepts, and then all of the observables ping
| around and become complicated.
| orenelbaum wrote:
| It kinda is, but it's more than just JSX. Solid was basically
| born out of Knockout and is in many ways a continuation of
| Knockout, but it has some relatively significant changes and
| additions to make this approach more viable, especially for
| large long standing projects. JSX is more of a quality of life
| thing, you don't even have to use it, Solid's runtime exists
| completely separately of JSX and can work great without it or
| even potentially be integrated with other templating languages.
| fabiospampinato wrote:
| I've spent the past month kind of rewriting parts of Solid in an
| attempt to better understand it, and coming from React the way
| Solid works is just so much more beautiful, it feels liberating.
|
| There's no rules of hooks, no dependencies arrays, no stale
| closures, no wildly different resulting performance depending on
| where exactly you put your components boundaries, no VDOM at all,
| no props diffing, when I change the state corresponding to an
| attribute or property that just gets updated immediately, the way
| deep DOM nodes structures are created is sooo much more
| efficient... it's amazing!
| nateroling wrote:
| After years of using Knockout and Angular/RxJS, I'm not at all
| convinced that adding Observables to React is going to lead
| anywhere interesting.
| deweywsu wrote:
___________________________________________________________________
(page generated 2022-03-01 23:03 UTC)