[HN Gopher] Making sense of React Server Components
       ___________________________________________________________________
        
       Making sense of React Server Components
        
       Author : joshwcomeau
       Score  : 73 points
       Date   : 2023-09-06 16:27 UTC (3 hours ago)
        
 (HTM) web link (www.joshwcomeau.com)
 (TXT) w3m dump (www.joshwcomeau.com)
        
       | mattaw2001 wrote:
       | [flagged]
        
       | mattaw2001 wrote:
       | [flagged]
        
       | idosh wrote:
       | [dead]
        
       | rabuse wrote:
       | Hilarious that the industry is going full-circle back to server
       | rendered pages.
        
         | jbverschoor wrote:
         | Basic thing every so many years. Waste of life
        
       | MPiccinato wrote:
       | I will have to give this article a more full read rather than
       | just a skim, but...
       | 
       | I am left with such confusion as to how React/Next arrived at
       | this solution. `useEffect` didn't run on the server when doing
       | SSR, great, easy enough to understand. Now several common hooks
       | don't run on the server because they are considered interactive?
       | And it isn't that they won't run, their initial pass in most
       | cases doesn't do anything, it is that Next now yells at you for
       | having a `useState` hook in a "Server Component".
       | 
       | I would like to write a component, not have to think about where
       | it is running in most cases, and go on with my day. I mostly use
       | React for large SPAs and have adopted Next for doing SSR on the
       | few pages that I needed it for (SEO, etc).
        
       | halfmatthalfcat wrote:
       | It's annoying that the React team announced Server Components
       | without a well defined spec, the wire protocol most
       | significantly. Instead, it's a cabal between the React team and
       | Vercel which obviously is going to give them an inherent
       | advantage and probably steer things in their favor, rather than
       | the broader React ecosystem as a whole.
        
         | quonn wrote:
         | It seems like there is a project on github called simple-rsc
         | that works without Next.
        
       | rco8786 wrote:
       | I'll do what I did the last time one of these articles popped up.
       | Word counts:
       | 
       | complex: 2
       | 
       | confusing: 3
        
         | [deleted]
        
       | lioeters wrote:
       | > As I write this, there's only one way to start using React
       | Server Components, and that's with Next.js 13.4+
       | 
       | I don't understand how this is acceptable to the React user
       | community, that only Vercel gets to be in this privileged
       | position. Why did they not include other companies, or the users
       | themselves, in the discussion and development of this feature.
       | 
       | > Since Server Components are a new React feature, third-party
       | packages and providers in the ecosystem are just beginning to add
       | the "use client" directive to components that use client-only
       | features like useState, useEffect, and createContext.
       | 
       | > Today, many components from npm packages that use client-only
       | features do not yet have the directive. These third-party
       | components will work as expected within Client Components since
       | they have the "use client" directive, but they won't work within
       | Server Components.
       | 
       | The arrogance of expecting all third-party packages, React-
       | related or not, to buy into the "use client" directive. A humbler
       | approach would have been a "use server" directive to opt-in to
       | this behavior, instead of expecting the _entire rest of the
       | ecosystem_ to adapt to it.
        
         | foota wrote:
         | Reading further, use client is viral, and propagates to
         | children components.
        
         | [deleted]
        
         | adamesque wrote:
         | The reason Vercel was selected for this privilege is pretty
         | simple, to my understanding: they volunteered and committed
         | engineering resources to partner with the React team to work
         | through a pretty major and experimental new API with a lot of
         | expected breaking changes.
         | 
         | Child of a sibling comment has more details:
         | https://news.ycombinator.com/item?id=37408918
        
         | paulddraper wrote:
         | Facebook open source has been quite good (React, GraphQL, Buck,
         | PyTorch).
         | 
         | This is...weird. How did Vercel manage that?
        
           | marksomnian wrote:
           | Dan Abramov (React core team, formerly of Meta) talks about
           | this in a Twitter thread:
           | https://twitter.com/dan_abramov/status/1654688751342301184
           | 
           | In short, it's because Vercel invested engineer-years into
           | piloting RSCs as part of a production framework and making
           | Next the guinea pig. Next wasn't actually the first framework
           | to try RSCs - Hydrogen (Shopify) and Gatsby both tried early
           | versions of it and provided feedback, but Next is the first
           | to implement it to the point that it can be considered
           | stable.
           | 
           | The long-term goal is that RSCs aren't a Next-only concept -
           | for example the Remix team said that they wouldn't implement
           | them until they became more stable (https://twitter.com/ryanf
           | lorence/status/1678416472010260480), but are working on it
           | now (https://twitter.com/ryanflorence/status/1697253955376722
           | 092). But the React team has always historically favoured
           | trying new features in production to iterate on the API (this
           | happened a lot internally at Meta), and this was an
           | opportunity to do that.
        
             | tshaddox wrote:
             | Also worth noting that after experimenting with RSCs in
             | Hydrogen, Shopify acquired Remix and is now building
             | Hydrogen using Remix.
        
         | TheCoelacanth wrote:
         | Third-party packages don't need any directives unless they
         | specifically want to put a client/server boundary in their
         | component.
         | 
         | The directive marks where the transition from server to client
         | happens. If you aren't already starting in a server component,
         | then you don't need to do anything to use client features.
        
       | Gunax wrote:
       | Server side rendering isnt special any more:
       | 
       | https://joshcollinsworth.com/blog/antiquated-react#server-si...
       | 
       | This blog was posted to HN a few weeks ago. The author does a
       | really good job of summarizing React's relationship with the rest
       | of the SPA ecosystem.
        
       | TheGeminon wrote:
       | > Instead of bouncing back and forth between the client and
       | server, we do our database query as part of the initial request,
       | sending the fully-populated UI straight to the user.
       | 
       | > But hm, how exactly would we do this?
       | 
       | Couldn't help but chuckle. What mysterious technology could allow
       | us to send an entire fully-populated UI over the web?
        
         | benatkin wrote:
         | > What mysterious technology could allow us to send an entire
         | fully-populated UI over the web?
         | 
         | WebAssembly? Just kidding. But I think a lot don't realize that
         | you _could_. It 's pretty well supported now and a small
         | WebAssembly library can fit in about the same size as a full
         | page photo.
        
           | gabereiser wrote:
           | Vugu?
        
         | gabereiser wrote:
         | "As if a million voices cried out in terror and were suddenly
         | silenced" - The full circle. When they left us, they were but
         | learners, now they have become masters. Realizing that this
         | nirvana exists, that people have been doing it this way for
         | ages. That a combination of interactivity with the offloading
         | of compute and rendering is a good thing for their performance.
         | That grey beards really do know a thing or two. /s
         | 
         | All sarcasm aside, having composable components server-side is
         | only a good thing. I welcome it.
        
           | nwienert wrote:
           | We already had composable components server side with SSR,
           | they just didn't query data inside the render loop. But that
           | doesn't really gain much, if anything leads to slower overall
           | performance as now instead of doing something like GraphQL
           | and resolving your entire tree in a single optimized database
           | call, you're probably waterfalling all over the place.
        
             | hotnfresh wrote:
             | GraphQL hype is (and always has been, really) out of
             | control.
             | 
             | GraphQL doesn't do a damn thing to help you optimize your
             | database calls. It also doesn't do a thing to help with
             | security or preventing DOS-inducing queries, which is the
             | first question anyone who's been around this block before
             | (exposing remote query interfaces) has about it.
             | 
             | Some big frameworks that happen to speak graphql will
             | automagic that stuff for you _in simple cases_ , but we
             | don't claim e.g. the capabilities of the Rails framework
             | with rails-api et c. as capabilities of REST or SQL or
             | whatever.
             | 
             | This stuff is really annoying because you get half-
             | technical leadership (or non-technical) thinking graphql is
             | magic and that it's good for all kinds of things it's not
             | and that it'll save lots of time that it won't, between the
             | hype and the name.
        
               | paulddraper wrote:
               | GraphQL is for (1) static typing (2) front-end developer
               | productivity and (3) front-end latency.
               | 
               | Maybe it does those well, maybe not, but if you expect it
               | do anything else, you'll certainly be disappointed.
        
             | gabereiser wrote:
             | who's to argue that you didn't fetch your entire tree in an
             | optimized way and passed that to your render loop as props?
             | I think there's patterns for this. I'm not arguing that we
             | haven't had the capability of composability with SSR, we
             | definitely have. What I'm arguing is that merging the two
             | worlds of front-end and back-end in a singular nomenclature
             | (besides just typescript) is good for velocity. Or maybe
             | I'm just inviting more pain as mixin's become traits and
             | the waterfall of bugs comes our way.
        
         | paulddraper wrote:
         | The Star-Bellied Sneetches
        
         | [deleted]
        
       | foota wrote:
       | This is my first time really reading about them, I'd assumed
       | they'd do some ASPX style interactivity where server components
       | updates on the server and send back html, it's interesting that
       | they haven't tried to go for something like that, meaning this is
       | a lot more limited in scope in some ways than I'd thought.
        
         | marksomnian wrote:
         | If you mean updating the page as the result of a mutation,
         | Server Actions (https://nextjs.org/docs/app/building-your-
         | application/data-f..., still in alpha) can do that - Next can
         | re-render a route and send the newly updated UI as part of the
         | response (this is a Next-specific feature, but I can't see why
         | other frameworks couldn't implement a similar pattern around
         | RSCs).
        
       | xixixao wrote:
       | > In order for this to work, we'd need to be able to give React a
       | chunk of code that it runs exclusively on the server, to do the
       | database query
       | 
       | This is not true/it's misleading. What you need is to be able to
       | fetch on the server, and hydrate on the client using data from
       | the server. This is possible with SSR and injecting into the
       | React stream, using isomorphic (client) components.
       | 
       | The article is great, but the reasons for RSC are more
       | subtle/complicated than the flow of the article would imply.
        
         | xixixao wrote:
         | You can see a live demo of this here (using Remix and
         | https://github.com/brillout/react-streaming): https://blessed-
         | ibis-783.convex.site/
         | 
         | The relevant isomorphic data fetching hook source code is here:
         | https://github.com/xixixao/convex-hosting/blob/main/app/hook...
        
       | bdcravens wrote:
       | so ... ColdFusion custom tags?
        
         | kraig911 wrote:
         | I legit spit out my coffee when I read this.
        
           | swyx wrote:
           | its actually something thats been discussed before https://tw
           | itter.com/floydophone/status/1462928358988156932?s...
        
       | benatkin wrote:
       | > This tutorial is written primarily for developers who are
       | already using React
       | 
       | Also good for those moving away from React, since we understand
       | React too. Probably won't change it, but may give us things to
       | look for in our new frameworks. A former coworker who was
       | _really_ into React just switched to Flutter.
        
         | cageface wrote:
         | I just started building a new app in Flutter too after working
         | exclusively in React for the last several years.
         | 
         | I'm not sure I'd use Flutter for the web yet but I definitely
         | prefer it to React Native.
        
           | benatkin wrote:
           | I like how Flutter is truly different. I learned just how
           | different it is because it has a completely different
           | problem, shader compilation jank. It shows what great risks
           | the Flutter team took to create something innovative. It's
           | paying off, and time will tell how big it will be!
           | https://docs.flutter.dev/perf/shader
        
             | cageface wrote:
             | I think it really comes down to Google's level of
             | commitment to Flutter. They've done a lot of great work so
             | far and I think it could easily become the first choice for
             | cross platform app development if they investing in it to
             | the degree they have so far.
        
       | megaman821 wrote:
       | The more features React adds the less I end up using React. The
       | new additions are just so inelegant, and don't fit my brain. The
       | function useEffect has so many caveats and such a terrible API. A
       | magic "use client" string at the top of a file is just
       | ridiculous. React code is nearly impossible to understand and
       | write without extensive external documentation now. I feel sad
       | for the future developer that has to modify this type of code ten
       | years from now; I hope Google is good at searching decade old
       | documentation to figure out what the hell is going on in old
       | React code.
        
         | champagnepapi wrote:
         | Agreed. IMO, it all started with Hooks. Things really went
         | downhill from there. useEffect is terrible! Example, how easy
         | it to forget the dependency array?! Because of that, you have
         | to setup linting rules to fix the poor API provided by that
         | hook...
        
           | paulddraper wrote:
           | HN is a funny place.
           | 
           | A useful feature that an insane majority of React devs have
           | come to prefer is "downhill."
           | 
           | Kids these days.
        
             | danielvaughn wrote:
             | I find it's mostly the kids who like hooks, and the older
             | devs who've been around since jQuery or further back, who
             | dislike them.
        
               | Scarblac wrote:
               | I'm 49 and started with the Commodore 64, and function
               | based components with hooks are _so much cleaner_ than
               | the old class based components, it 's unbelievable.
               | 
               | The classes had closely related functionality spread out
               | over several different methods making them hard to
               | understand at a glance, function based components are
               | very concise.
               | 
               | I think people who dislike hooks tend to overuse
               | useEffect (it's rarely needed) and to do too much inside
               | components rather than inside custom hooks.
        
               | tshaddox wrote:
               | For what it's worth, that's not at all my experience on
               | the teams I've worked with. I was around when hooks were
               | released and it was an immediate and significant
               | improvement to our team at the time.
        
             | bgirard wrote:
             | I think this is an artifact of HN's voting system. Most
             | readers probably don't have enough karma to even downvote.
             | For the ones that do, guideline discourage downvoting for
             | comments that you disagree with.
             | 
             | And I can see why the majority of HN readers would upvote
             | the top level comment. Particularly since it's a popular
             | re-hashed opinion.
             | 
             | Top comments aren't a good survey of the opinions of a
             | specific community for that reason.
        
             | keb_ wrote:
             | Many folks were criticizing hooks when they were
             | introduced.
             | 
             | Of course React devs will "prefer" it; they are the
             | idiomatic way to adding state/triggering effects in React.
        
             | [deleted]
        
           | Gunax wrote:
           | Every other framework not only has its own implementation of
           | hooks, but notably: every one of them is faster, smarter,
           | easier to write, or a combination of all three.
           | 
           | I agree that useEffect is bad.
           | 
           | But there are other SPA frameworks that do things better. In
           | fact, just about _any_ other framework does things better.
        
           | hotnfresh wrote:
           | Hooks felt like a big make-work project to let folks claim
           | high-impact commits on a project that didn't really need any
           | of those, anymore.
        
             | politelemon wrote:
             | What does this expression mean, make-work project?
        
               | hotnfresh wrote:
               | Digging a hole and filling it back up again. Work for the
               | sake of having something to do.
        
               | politelemon wrote:
               | Ah I understand it now thanks. Not an uncommon thing in
               | many places!
        
         | fidotron wrote:
         | It will turn out to be a great conspiracy where the React team
         | are being encouraged to make it so only LLMs can make sense of
         | React code in future.
        
         | paulddraper wrote:
         | > The function useEffect has so many caveats and such a
         | terrible API.
         | 
         | Really? What caveats?
         | 
         | The only maybe oddity that I can think of is that if the deps
         | array is omitted it always runs.
         | 
         | What API would you prefer? Something more like signals?
        
           | danielvaughn wrote:
           | This may be a personal thing, but I really like reading and
           | writing code that feels like it's telling a story. That is,
           | operating sequentially (this happens, then this happens, then
           | this other thing, etc).
           | 
           | useEffect breaks the sequential nature of your code and makes
           | it feel like you're reading a script from a Quentin Tarantino
           | movie.
        
             | littlecranky67 wrote:
             | Agreed, but non-sequential execution is the nature of
             | event-driven, async non-blocking code. Event-driven as Web
             | Applications (not Websites!) mostly deal with events (user
             | input or network events). As long as the JavaScript VM and
             | the DOM uses non-blocking async models no framework - being
             | it Vue, Angular, React or whatnot - will ever change that.
             | 
             | Sequential, blocking modells like i.e. batch ETL jobs are
             | just not the domain of the browser.
        
           | SinParadise wrote:
           | Not useEffect specifically, but wiring something very
           | stateful like a map library into the React rendering paradigm
           | while keeping the state management in React via useState etc.
           | can be very difficult to do so in a performant way.
           | 
           | I recalling using a lot of useRef to manually tune when to
           | re-render, and in an ideal world I shouldn't be this granular
           | about it.
           | 
           | You can certainly use one of the many React map wrapper
           | libraries to lessen the pain, the pain is still very real,
           | just dealt with by someone else.
        
             | nwienert wrote:
             | But what's better? In the end you need control over stuff,
             | it's almost like people want frontend to be magically easy
             | but unfortunately there's just the reality that either you
             | have high abstraction but less control, or low abstraction
             | and more control (more code, more gotchas, etc) until you
             | get a smart optimizing compiler ofc.
             | 
             | Hooks imo are great, as they are pretty explicit and low
             | level.
             | 
             | Nowadays signals are the new kid on the block, though mobx
             | and similar have existed since forever in react land, but
             | they have their own crazy edge cases like reactive loops
             | and implicit behavior.
        
             | paulddraper wrote:
             | > and in an ideal world I shouldn't be this granular about
             | it
             | 
             | Hm, could you give an example of this ideal performant
             | state management world? Angular? Vue? Svelte? MobX?
        
               | keb_ wrote:
               | Svelte is a good example. But you don't have to go that
               | far; Solid and Preact have signals with auto-tracked
               | dependencies.
               | 
               | As another commenter mentioned, yes it's less low level
               | than managing your own dependencies, but then again, most
               | React apps are already wrapped in layers and layers of
               | abstractions/context providers/selectors and use Jest as
               | their test runner (which injects the global namespace
               | with functions) and does other black magic and weird
               | metaprogramming, so I think most React devs are already
               | OK with less lower level stuff.
        
           | Izkata wrote:
           | It does a shallow compare, not a deep compare. Workarounds
           | tend to involve additional hooks:
           | https://dev.to/vsramalwan/ways-to-handle-deep-object-
           | compari...
        
           | keb_ wrote:
           | The dependency array is a huge footgun. Engineers,
           | experienced and newbie alike, get it wrong all the time
           | (either causing infinite render loops, or skipping necessary
           | re-renders). This affects useCallback and useMemo as well.
           | After a while, I stopped thinking "oh the developers just
           | aren't doing it right" and more "the React team can do better
           | than this."
           | 
           | > What API would you prefer? Something more like signals?
           | 
           | Yes. Or full tree redraws like Mithril.js did 8 years ago.
        
             | tshaddox wrote:
             | Or you installed the lint rule once 4 years ago and never
             | had a problem again.
        
               | gyanreyer wrote:
               | Agreed, everyone who complains about dependency arrays
               | almost certainly hasn't used the linting rule. That being
               | said, I'm not sure that an API is well-designed if the
               | only way to use it effectively is by forcing you to even
               | know there is an eslint plugin to begin with, and then
               | once you do know that, that means now you're being forced
               | to add eslint to your project whether you like it or not.
               | And sometimes eslint just stops working for who knows
               | what reason, I have a developer on my team who's
               | constantly dealing with issues where his eslint/prettier
               | setup isn't running correctly.
        
             | paulddraper wrote:
             | React does full tree redraws (well, unless you use memo).
             | 
             | useEffect is for side-effects.
        
               | Izkata wrote:
               | Class components have "shouldComponentUpdate()" that
               | avoids this entirely.
        
               | keb_ wrote:
               | It does not. Child components will only render when their
               | parent component re-renders or for example, its state
               | changes.
               | 
               | Either way, this is different than what I mean with
               | Mithril.js (it does full tree re-renders on event handler
               | calls or when a manual redraw function is called).
        
           | foota wrote:
           | Personally, I grew to prefer signals and rx and APIs for
           | heavy things. I wish it were easier to hook up some custom
           | class object to a component to use as state, but it always
           | feels clunky.
        
           | cjcenizal wrote:
           | This page[0] lists many situations in which useEffect
           | shouldn't be used. Some might seem counter-intuitive.
           | 
           | [0] https://react.dev/learn/you-might-not-need-an-effect
        
             | paulddraper wrote:
             | tl;dr Don't use useEffect if there is an alternative.
             | 
             | That's a bunch of examples where there are good
             | alternatives.
        
             | consilient wrote:
             | That's not a bunch of separate caveats, it's a few
             | principles illustrated with lots of examples.
             | 
             | - Don't use effects for things that aren't genuinely
             | effectful
             | 
             | - Put finnicky state management stuff in reusable utils
             | instead of re-implementing it from primitives over and over
             | again.
             | 
             | Neither is React-specific.
        
         | johngalt2600 wrote:
         | Agreed. React is great but I really do not enjoy writing it.
         | Much prefer Vue
        
         | bakugo wrote:
         | > I hope Google is good at searching decade old documentation
         | 
         | Google isn't even good at searching recent documentation, from
         | my experience.
        
       ___________________________________________________________________
       (page generated 2023-09-06 20:01 UTC)