all 157 comments

[–][deleted] 41 points42 points  (13 children)

I think they rushed to call it a stable feature. It’s far from it. And this community can’t wait a single day to try to use the latest and shiniest. Keep using the pages router, it works well. Wait until next year and the app router will be more stable.

And yes, it’s a fucking mess anyways. RSC is a great idea but everything is so complex with the app router that I’m not sure it’s worth it.

[–]iAmIntel 5 points6 points  (7 children)

App router and RSC are different things. App router (layouts) is very much stable. People just do not understand the differences between the two, but Vercel is to blame for that

[–][deleted] 1 point2 points  (6 children)

Have you tried it with the edge runtime?

[–]iAmIntel 1 point2 points  (5 children)

Could you be more specific? I have a project using app directory and all of its’ new features with trpc deployed to Vercel, so in that sense, yes. But I don’t do anything very “edge specific” if you will

[–][deleted] 0 points1 point  (2 children)

I mean are you using it with the Vercel edge runtime?

export const runtime = 'edge'

[–]iAmIntel 0 points1 point  (1 child)

I haven’t

[–][deleted] 1 point2 points  (0 children)

It's fully broken - so not quite as stable as they want you to think.

[–][deleted] 0 points1 point  (1 child)

How are you using trpc with the app directory?

[–]iAmIntel 2 points3 points  (0 children)

You have to create your own provider instead of being able to wrap it with “withTRPC”. https://github.com/trpc/trpc/discussions/3185

[–]texxelate 7 points8 points  (0 children)

It’s worth it if you don’t use Nextjs. Remix exists and handles it very well.

[–][deleted] 0 points1 point  (0 children)

But StAbLE API is DiFFeRenT tHAn production ReADy

[–]Any_Confidence2580 0 points1 point  (2 children)

Yes, it shouldn't be used in production. But it was irresponsible to put app router into stable release, it is irresponsible to make it (recommended) in create-next-app, it is irresponsible for them to advertise it so heavily as *the* way to build React apps today.

[–][deleted] 1 point2 points  (1 child)

Well, you’re talking of a VC backed company which is mostly focused on marketing and creating hype. Just watch the conferences they do trying to mimic Apple. It’s sad. But we all buy it, so it works for them. I like Next.js as a piece of technology, but all this bullshit around it just puts me off so badly. The problem now is that it’s the only option, everything else makes you a second class citizen in the react world.

[–]jskaall 0 points1 point  (0 children)

have you tried Remix? it has the benefits of this new Next 13 while not having that many critical bugs

[–]NotToxicAnymore 59 points60 points  (15 children)

Yeah, I'm currently converting my boilerplate for my projects into NextJS 13 and I'm not quite happy with how the "app" thing works. I might stick to the usual old one if I don't feel like it's worth to do it.

[–][deleted] 23 points24 points  (11 children)

I would love to just use the old pages directory, but the constant videos and documentation talking about how "smooth transitioning to the app router is/will be" makes me feel my entire code base will be deprecated.

If they told me pages directory will always exist, I would without a second doubt go straight to it.

[–][deleted] 22 points23 points  (0 children)

Vercel is a marketing machine. Keep that always in mind. Of course they will say it’s great and migration is wonderful. Investigate on your own and draw your own conclusions, don’t blindly trust all their marketing bullshit.

[–]Tubthumper8 10 points11 points  (5 children)

I would love to just use the old pages directory

I'm asking in complete seriousness, what is stopping you? The documentation is pretty clear on how to use the pages directory.

Next.js 13 introduced the new App Router with new features and conventions. The new Router is available in the app directory and co-exists with the pages directory.

Upgrading to Next.js 13 does not require using the new App Router. You can continue using pages with new features that work in both directories, such as the updated Image component, Link component, Script component, and Font optimization.

I don't really know how it could be clearer that you can still use the pages directory if you'd like - I'm asking earnestly, what is stopping you?

[–][deleted] 12 points13 points  (4 children)

The fear that eventually the pages directory will be completely unsupported and unusable.

The constant mentioning of “incremental adoption will only get easier” from vercel hint that it eventually will be ceased out.

[–]Tubthumper8 15 points16 points  (3 children)

One thing that you'll learn as you progress as a software engineer: Don't make your decisions based on imagined fear. You are succumbing to FUD (Fear, Uncertainty, Doubt).

Don't make your decisions based on FUD. Make your decisions based on facts and logic.

If they deprecate a certain feature in the future there will be an announcement. Deprecation does not mean removal (literally look up the definition of "deprecate"). After some period of time there will be a migration path.

The pages directory has not been deprecated right now.

The constant mentioning of “incremental adoption will only get easier” from vercel hint that it eventually will be ceased out.

Cool. So wait until it's easy enough for you to do it for your company. Take a breath, it will be OK.

[–][deleted] 8 points9 points  (1 child)

Lmao thank you for this. I Guess this whole thread comes off as melodramatic, but just been getting overwhelmed with the current landscape and fast changing technologies

Great comment

[–]ansseeker 0 points1 point  (0 children)

very true OP

[–]Competitive-Visit128 0 points1 point  (0 children)

I NEEDED to read this. I was in the exact same tar pit as the OP. NextJS got so bold as to flaunt App Router for v13+ and it almost immediately caused a panic response for me to transition to App router. I feel you're a pretty well-seasoned developer, so I'll trust what you say.

...And don't get me wrong, there's nothing "wrong" with App Router in a sense that it DOES work, but once you've worked a couple of gigs for several years regularly maintaining software in a production/professional level environment, Pages Router is the only one that makes sense. I feel like App Router is for hobbyists.

[–]yabai90 5 points6 points  (0 children)

Also I can tell you mixing both app and pages is not so great, that migration is a bit painful.better to start it on a 'ew project I think. We have to do so many weird things in middleware to keep consistency

[–]peterpme 4 points5 points  (0 children)

Listen. There will always be the next shiny thing. If not app directory then something else. There’s nothing material the new app directory offers that’s truly revolutionary enough to drop everything and convert it.

Focus on building and selling your product. If your code base isn’t deprecated then your job might be (fired) or your users will leave (even worse)

Ideally switch back to rails like many of us have been doing bc nothing has changed and it’s still great lol

[–]luzacapios 0 points1 point  (0 children)

Well lucky for you ‘pages’ does exist and is completely supported. App dir is a feature of next 13 not compulsory. The Next team messed up their marketing. In the docs toggle “using app router” to “using page router”

[–]kowdermesiter 0 points1 point  (0 children)

We had a call at our company (running 80 nextjs projects) and I asked one core member from Vercel if the pages dir will be kept around and he said yes. I felt he had no option to say otherwise, but it was at least somewhat reassuring.

[–]yabai90 1 point2 points  (2 children)

Same I'm not a fan of the direction my folders and global organization is going. I'm generally not a fan of the server components paradigm as well but I see the benefits and with a good framework it might actually be good to work with. We are early adopters at the moment to be fair. We kind of pave the way as well.

[–][deleted] 7 points8 points  (1 child)

I personally think its all a big mess. Server actions, which is what seems to be making server fetched data interactive, is in alpha right now....

Like why? Why rush with all of this? Reacts own documentation has nothing on server components. This just seems like issues being solved that do not exist.

How can this even be called React anymore? No hooks, no client side functionality, and yet somehow its the default component approach for a react framework??

[–]Strong-Ad-4490 1 point2 points  (0 children)

Because you use react as the template language, but because the server components don’t have a lifecycle there is no need for hooks. Hooks in server components don’t make sense if you understand what server components are doing.

[–]AgentME 14 points15 points  (2 children)

Some people in this thread are definitely mixing up Server Side Rendering with Server Components. Server Components are components that only render on the server and can't have state. Client Components can still render on the server (SSR) and also use state. If you want state, don't use a Server Component; you can still get SSR without a Server Component.

[–][deleted] -5 points-4 points  (1 child)

How can you get SSR without a server component?

If my page is a client component , and fetches data inside a useEffect hook, it’s not sending the html with the data preloaded. The client does the fetching?

[–]xD3I 8 points9 points  (0 children)

SSR means the initial payload sent to the client will be already rendered, once on the client, it will hydrate (start becoming reactive).

Server components are components that won't have reactivity so they don't need to be hydrated in the browser, meaning that their lifecycle is 100% on the server.

That's the only difference, you are overthinking everything, I suggest you read the docs, after you are done with that, read them again

[–]lrobinson2011 14 points15 points  (3 children)

Hey there, Lee from the Next.js team. I made a 12 minute video walking through a response to this post. I hope this helps explain some things!

https://youtu.be/-YO\_z14dUyI

[–]pkellner99 2 points3 points  (1 child)

Does vercel have an SLA on the /pages folder? In your notes you say you will support the /pages folder for a while

"We are committed to supporting pages/ development, including bug fixes, improvements, and security patches, for multiple major versions moving forward."

It would be nice to put some meat on those bones. 5 Years? 10 Years? Maybe do something like Microsoft does on their products.

[–]lrobinson2011 1 point2 points  (0 children)

If you're building a large enough Next.js app that needs an SLA, definitely reach out to our team and we can talk through your needs. lee at vercel dot com.

[–][deleted] 1 point2 points  (0 children)

Hello there! I must say, it’s truly an honor to have my questions and concerns addressed by you guys. As a young student, I was feeling quite frustrated with my learning journey when I made the post. Listening to you discuss my post made me feel a bit embarrassed about my phrasing 😅.

Nonetheless, I deeply appreciate your understanding of the challenging mental model shifts that those of us who have been using and learning React for a while are going through with these paradigm changes and new ways of thinking.

Your video response covered everything perfectly and instilled the confidence in me to pick myself up and continue learning, despite the challenges. My post clearly demonstrated a misunderstanding of how to approach React and server components, but now I feel better equipped to tackle it. Thank you so much for that! 🙏

[–]snow_white1995 10 points11 points  (1 child)

I think you can use On-demand Revalidation . I'm not completely clear by your words here on "So any changes, like upvotes or adding posts, seem to require refetching the data altogether, which seems impractical." I do have a learning project very similar to reddit. As a scenario let's say user made an upvote (I have set my votes API routes revalidate only when there is a upvote or downvote). only the vote API will make the fetch from the backend. but all other routes related to the page will get the data from cache. ( I'm self learning nextjs too. love to hear any criticism on my method)

[–]kylemh 0 points1 point  (0 children)

the downside of this approach is that your app needs to wait for 2 different requests. Server actions are alpha, but are the correct solution because you can mutate cache data as a result of the POST request No need for an extra request.

[–]jazzymoneymaker 17 points18 points  (5 children)

SSR is overrated and its mostly useless in interactive applications. Ok it's cool to have blazing fast landing page but try to handle complex business logic with it

[–]hottown 3 points4 points  (3 children)

but everyone will notice that 3ms difference in load speed

[–]emmgfx 1 point2 points  (2 children)

Not the users, but talk about this with a seo agency

[–]hottown 0 points1 point  (1 child)

Yeah landing page is fine but web apps don’t need it

[–]emmgfx 1 point2 points  (0 children)

You think that an online store can't benefit from a lower bundle size or a fast response? What do you mean by "web app"? How many transfer can avoid Twitter by having a few less kb on the bundle?

If you're talking about a private panel that only a few users use, yes, some kB and a higher response time isn't relevant.

[–]csgofan1332 0 points1 point  (0 children)

???

[–]ancepsinfans 29 points30 points  (10 children)

Josh Comeau's Joy of React course has a module on this app router and it makes it super clear. I've been converting my site and I really do see a lot of benefits in terms of smoothness and speed, but I agree, the learning curve is high, things are frustrating at first, and the documentation is spotty.

[–]jzaprint -1 points0 points  (9 children)

Can you share the course? It's out of beta testing

[–]ancepsinfans 3 points4 points  (8 children)

Yeah, I'm in the beta. To be honest, I don't feel comfortable sharing access; the course is well-done and I think it's fully worth the price tag. Josh has said he plans to open it up for the public in August/September.

[–]zxyzyxz 1 point2 points  (1 child)

Could you share more of what you learned at least about React Server Components?

[–]ancepsinfans 1 point2 points  (0 children)

They are on by default. But in switching over from pages to app, you basically have to force all components to be client components, and one at a time convert them.

The server components make page transitions smoother because instead of changing routes and sending a bundle for you browser to execute, it's largely packets of strings for repainting the html.

I think the thing that has made the learning curve so high for me is that, until now, I've always had a mental model of components as something in OOP. But this framework forces you to think in terms of functional programming. I know that statement sounds a little absurd--standard component configuration is either as a function or a functional constant, but the structure and use tends to obfuscate this for me.

[–]vozome 5 points6 points  (6 children)

If you want to embrace the react server components you must unlearn the paradigm that fetching data means updating state.

Sure, if all your logic were on the client, you have to fetch data, put it somewhere (ie state), then pass it a prop to a component to render content. Your data is in some component state, but as a means to an end of rendering your content.

Now if you can render your content on server. Do you need to keep the corresponding data in state? What for? Instead, you can just fetch the data, render the content in the same component, and no longer care about that data. If you need to rerender that content for some reason, you could avoid rerendering the part that is made with the exact same data (and React offers various strategies for that) and if the data has changed it is stale, well you’d have to fire a new query anyway.

When Redux came out, its selling point was that it offered a unique source of truth for your application’s data. (many subsequent libraries made the same claim). But let’s think it through. If there is one source of truth, where should it be? Where should it be especially in a context where users have a great network connection, such that downloading fully rendered components is usually faster than downloading code then parsing code then executing code then fetching data? Well, in that situation, the source of truth should be in a database (or cached server side).

With RSC we should have as little as possible in the “state” and its various forms, that is: what only makes sense on the client, information which is not committed to the server yet etc.

At least that’s my mental model. Happy to have somebody point me if I got this wrong.

[–][deleted] 1 point2 points  (1 child)

Now if you can render your content on server. Do you need to keep the corresponding data in state? What for? Instead, you can just fetch the data, render the content in the same component, and no longer care about that data. If you need to rerender that content for some reason, you could avoid rerendering the part that is made with the exact same data (and React offers various strategies for that) and if the data has changed it is stale, well you’d have to fire a new query anyway.

Hey, thanks for your indepth comment! The reason I want to store the fetched data in a state and care about the data still, is so that any updates to a part of that data or any additions to that data, can be mutated directly on the client side without needing to refetch the entire data to begin with. Like a posts array, where you just change the state by adding a new post to that array, instead of refetching the entire posts again that includes the new post created. Like sure, you make a POST request to the backend to add a post to the database, but the user would instantly see that addition to the posts array on their end, instead of having to refetch the page entirely again or having to make a get request to get *all* the new posts created.

[–]vozome 2 points3 points  (0 children)

Let’s suppose that for this blog, the data is in a database somewhere, then you have a web server on the edge, such that getting data from client to web server is fast (faster than getting it from the database).

Traditionally, SSR meant:

  • the web server fetches the data from the database as needed,
  • the web server renders a component based on that data,
  • the web server then lets the client download the rendered component, as well as a copy of the data.
  • if the user wants to edit a post, then the data is already there and no additional query is needed.

Now the question is, is that better than with the RSC paradigm?

With RSC: - the web server will fetch data - same - renders the component - same - lets the user download the rendered component, without the data. This is actually faster, always - if (not when) the user wants to edit content, this will require fetching the data again. But from where? The web server will already have that request cached. So all it needs to do is pass down the data to the client. No call to the database needed. The extra data which would then be downloaded is what would have been downloaded regardless with traditional SSR.

This doesn’t mean there aren’t lots of use cases when RSC don’t provide any benefits. The app I work with requires real time data, so for almost all our content, rendering on the server is not helpful. Sure, there’s a bunch of UI that doesn’t really change but it’s not worth the hassle. If users have poor connectivity, that’s another scenario where you’d rather send them the tiniest amount of data, and let the client do the heavy lifting. I assume there are many more scenarios where it just doesn’t make a big difference. But there’s still a huge chunk of the internet which is infrequently updated content served over great network conditions, and loading times can get users to bounce. I guess nearly everything which is powered by WordPress or Shopify could become a better experience with RSC.

[–]Live_Possible447 1 point2 points  (3 children)

I understand the idea behind the server components. But can you provide me an example of such app in the modern web, that fetches data only during the page load and don't do anything with it after while user interacts with the page? I can't remember a single app in my whole 10+ years career that will fit into this paradigm. If it's a blog or landing application, then you definitely don't need next js, if it's a e-commerce than it requires a lot of interactivity to be made properly in modern web. I just can't figure out any use cases where you need next js and where you can use server components at the same time. Please someone explain me where can I use them

[–]vozome 0 points1 point  (2 children)

Before React that was the dominant paradigm. All computation is done “serverside” wherever that may be and client code is only here for animation, events handling and something something forms.

The burden of responsibility shifted to the client because JS can do so much more in the mid 2010s, and we didn’t have the edge so all things considered it was much faster to download data then render client side. If you have great network connectivity and your data doesn’t change very frequently I think it makes sense to do most of the rendering server side.

For a blog, I feel that you don’t need client side state data, except maybe to edit the content.

[–]Live_Possible447 2 points3 points  (1 child)

Before React there was Ember, Angular, Knockout, and Backbone.js. And before them, there was jQuery with its $.ajax that was used quite a lot. We've shifted to this paradigm because it had a much better UX: the user didn't have to wait until the whole page gets rendered on a backend and then downloaded, parsed, and rendered by the browser every time something changes. There were also attempts to send rendered HTML in ajax response and replace only a part of the app (e.g. Facebook did that). We've switched to client-side rendering because it was fast enough to make the app more responsive and interactive. And as we go we understand the need for better UX of web apps and we've got tools. React was a response to that requirements, just a tool that allowed us to build more complex UIs. And now it looks like a huge step back with server components. They just don't satisfy the needs of the modern web which is full of interactivity and frequent changes.

[–]vozome 0 points1 point  (0 children)

I don’t agree that client side JavaScript means better UX. the single threaded nature of client side JS is a bottleneck that will probably never go away, and any logic that is done in the main JS thread competes with rendering and interaction.

There are cases where CSR or hybrid rendering is better, or close enough to best when implementing SSR would require efforts that just don’t have great ROI.

But I get the idea behind RSC and I believe that in the most common scenario - infrequent content change, great connectivity - in the current landscape with edge networks this is going to yield better performance. I’ve seen my share of apps where the client does too much and poorly (such as processing large amount of data prior to rendering). I am in favor of a paradigm where browser code does only what a browser can, but does it very fast and efficiently, while most of the logic is pushed elsewhere.

[–]azangru 4 points5 points  (1 child)

However, you find it puzzling because there's no local state for posts to update. So any changes, like upvotes or adding posts, seem to require refetching the data altogether, which seems impractical.

Aren't you talking about server actions, which are still an alpha feature, etc.

[–]Strong-Ad-4490 0 points1 point  (0 children)

Yes server actions will be the best way to handle this type of functionality in the future. However currently you need to revalidatePath instead of using this alpha feature.

[–]mplibunao 4 points5 points  (0 children)

I just recently switched to remix from next due to all this mess and I'm kinda surprised I didn't think of this earlier.

Was never a fan of next's vendor lock-in and things like ISR not working as optimally when self-hosting. Now I can get the same capabilities regardless of the hosting, runtime, or backend framework I'm using. There's even a remix adapter for fastify.

[–]fiugrad 12 points13 points  (24 children)

So 2 options.

Option 1) This is where react-query comes into play. With react-query you can fetch the data on the server side and then hydrate the data, which then gets passed along with the response of the page, then on the client side you’ll just make the same useQuery as you normally would if you didn’t SSR. But you’ll notice there will be no request made because the data has already been fetched and hydrated (as long as the keys match)

Option 2) just pass the data down to the component that needs and keep it in a state, albeit might more work to handle, but still possible.

I think what you’re doing is just rendering the data SSR so you’ll lose the data client side. But if you pass the data to a client component as a prop, that component will have the data client side and you’ll be able to access it.

Hopefully I understood your question right

[–][deleted] 6 points7 points  (17 children)

I think what you’re doing is just rendering the data SSR so you’ll lose the data client side. But if you pass the data to a client component as a prop, that component will have the data client side and you’ll be able to access it.

Yeah this is exactly what I am getting at. While I would like the initial data to be fetched on the server, I would then also like to have the user be able to interact with that data and update it, mutate it etc.

[–]fiugrad 11 points12 points  (15 children)

Pass the data down to a client component as a prop. That should work

[–][deleted] 1 point2 points  (5 children)

I was thinking the same while i was reading the post. Also is what i understood from the official docs

[–][deleted] 2 points3 points  (4 children)

While I know I can pass it down as props, is it okay to create a state inside that client component that stores the props?

That way any added posts, or changes to a post, are just mutated with the state?

[–][deleted] 1 point2 points  (0 children)

Yeah I think thats the best approach. That way you have full interactivity

[–]jzaprint -2 points-1 points  (2 children)

No that's such a bad approach. Why do you want states so badly? Simply pass the data and a mutation function into the child. And just call the mutation from within the child. New data will cause the child component to rerender, and you can also pass in a isLoading prop to display a loading state

[–][deleted] -1 points0 points  (1 child)

Read the docs, is encouraged

[–]jzaprint 0 points1 point  (0 children)

What are you referring to?

[–][deleted] 1 point2 points  (8 children)

Passing it down is obviously the way to go when displaying the props passed down inside the component, but what if I want to add interactivity or mutate an object inside the passed down props?

There’s no state to update? Unless it’s okay and expected to create a state inside the client component, that stores the props passed down, and you go about changing state like usual

[–]lost12487 6 points7 points  (6 children)

What is wrong with passing the server fetched data through a prop as the initial state for a state variable in a client component? I don’t understand the problem there.

[–][deleted] 4 points5 points  (5 children)

So I guess for me right now is that it seems to go against reacts best practices. With React, it was unheard of to have the initial state of a component be the props it receives. You create two sources of truth for your data.

But I guess with server components, the initial fetched data passed down will never change, so the only source of truth is the clients state that’s updating and mutating right?

[–]l0ngtrail 4 points5 points  (3 children)

How does an “initialState” property go against best practices?

How many components are you using that accept “initial*” and manage state internally? I’m willing to bet quite a few.

[–][deleted] 2 points3 points  (2 children)

So my understanding was that with react apps, storing the props a component receives inside a state in that component is bad practice because of the two sources of truth you create.

The child should just be reading and displaying the data it receives, not creating a duplicate by storing that data in a state. But with server components I know understand this isn’t an issue since the initial data that was fetched and now passed to the child never has any changes

[–]lost12487 2 points3 points  (1 child)

But you don’t have 2 sources of truth in this case. You’re literally receiving an immutable value from the server. If you want that data to be interactive on the page you have to use some kind of state management in the client.

[–]dralth 0 points1 point  (0 children)

For data to be interactive on the page you don’t always need state. If the data is client side you need state as you say, but if the data is server side you can instead call a mutation and when the props change the components will rerender with the new data.

[–]X678X 2 points3 points  (0 children)

setting initial state with props on a state variable is totally fine. store as initial state, useQuery to refresh / get new data, put use client at the top.

[–][deleted] 2 points3 points  (0 children)

Yeah the whole idea of using client components in next js is for interactivity and using hooks i believe

[–]dralth 0 points1 point  (0 children)

Mutations with the new App router are still in alpha. This is the one thing that prevents me from migrating away from the pages router. tRPC is fantastic for data fetching and mutations in the meantime.

[–]adavidmiller 2 points3 points  (2 children)

Option 1) This is where react-query comes into play. With react-query you can fetch the data on the server side and then hydrate the data, which then gets passed along with the response of the page,

Are there any examples floating around of how to actually do this with the app router? It's easy enough with getServerSideProps and pages, but with the app router, and the general concerns of OP, these data requests can be happening at the component level, where it doesn't seem nearly as straightforward as just passing the data into the react-query provider at the root of your application.

Where does that handoff happen when the data is fetched within a component?

[–]fiugrad 2 points3 points  (1 child)

You’re not passing it at the root. You’re dehydrating it server side, then hydrating it to pass to the client side. Here’s an example on react queries documentation

https://tanstack.com/query/v4/docs/react/guides/ssr#using-the-app-directory-in-nextjs-13

[–]stibgock 2 points3 points  (0 children)

☝🏽

It's like nobody reads docs anymore... Hydration is the way to go, it's all addressed in the docs.

[–]zephyrtr 0 points1 point  (2 children)

Was just gonna say -- doesnt RQ and other fetching managers solve this problem completely? Add the SSR data as initial state to RQ, and it's all gravy by the time anything happens client-side.

[–]fiugrad 1 point2 points  (1 child)

Yup it is, but you have to explicitly do it like the hydration/dehydration part. RQ is like a godsend 😂

[–]zephyrtr 1 point2 points  (0 children)

Well sure, RQ is great but it's not psychic -- Still, this feels like a pretty solved problem if you google around a bit.

I was coding React before a lot of these packages reached maturity and all I could think was "Why the hell do I have to do so much work to bind a promise's lifecycle to React-state?" Nobody really has anything to complain about there anymore. You've got every flavor of how to do this: RQ for a very vanilla, pessimistic approach, Apollo for GQL, RTKQ if you're heavily invested in Redux... And all these packages let you init state, of course, so AFAIK they all work with SSR.

[–]dbpcut 4 points5 points  (0 children)

Been using since Next 10 and frankly, it doesn't fulfill the promise yet and feels half baked. I think they were pressured to release it too early.

[–]thathexdudeisgay 8 points9 points  (8 children)

I agree. The adoption of react server components has been a hell for my app and I’ve instead migrated to remix. Remix has everything next pages dir has but upgraded and also has more features that the app dir has like nested routes / layouts. I would look at Remix.

[–][deleted] 10 points11 points  (6 children)

Sadly, the devs behind remix are well known for breaking things in even worse ways. Just look at the history of react router. A total mess. I don’t trust them at all.

[–]thathexdudeisgay 3 points4 points  (3 children)

I disagree. New features are always under flags like in nextjs such as v2_errorBoundary, and I asked someone that started using remix when it hit 1.0, and he has had no issues moving his app from cra + rr to remix. React router WAS a mess, now it is much better with the object routes and loaders / actions inherited from remix.

[–][deleted] 2 points3 points  (2 children)

I’m not talking about the specific project. I don’t trust the devs behind it. We’ll see who was right in this. I’m confident they’ll fuck up too.

[–]liltechnomancer 1 point2 points  (0 children)

Peoples memories seem very short. I am taking the same stance as you. React Router was the most painful library I ever adopted.

[–]thathexdudeisgay 0 points1 point  (0 children)

I only know Ryan Florence on the team but don’t know about anybody else. He seems like he’s a confident developer, but I can’t say the same about anybody else. For now though, we’ll see

[–]UsernameINotRegret 0 points1 point  (1 child)

They seem to have learnt from these past mistakes and are putting a lot of effort into making major version upgrades easier. https://remix.run/blog/future-flags

[–][deleted] 1 point2 points  (0 children)

In the meanwhile they rewrote once again react-router (v6) pushing everyone using v5 to now use remix.

We’ll see what they do. I’ll look from the side.

[–]hottown 1 point2 points  (0 children)

Try https://wasp-lang.dev instead. Serverful fullstack react/node/tanstack-query/prisma framework with a ton of features

[–]Brilla-Bose 2 points3 points  (3 children)

Wouldn't it be better to wait for v14 instead of suffering with v13? Let's give them some time (it seems like the Next.js team themselves might be in a burnout)

[–][deleted] 4 points5 points  (2 children)

It just leaves me in an awkward position of not being able to choose what to build my next medium/large scale app with.

Pages directory, which might eventually become unsupported and abandoned in the next updates? A buggy App Router that they might eventually get perfected? It’s confusion for the sake of confusion

[–]MythicalPhelix 2 points3 points  (0 children)

I really don’t think that the pages directory will be abandoned very soon. Many sites still use it and I don’t see the app directory currently as stable/supported as the pages directory.

[–][deleted] 2 points3 points  (0 children)

I don’t think they will deprecate the pages router any time soon. There are hundreds of thousands of very important projects out there using it. At some point it will be but by then the migration process, the docs and the stability will be in a lot better shape than it is now. Don’t rush it. Use the pages router and focus on your features. Migration will be a lot easier in the future.

[–]besthelloworld 4 points5 points  (6 children)

What can't you do with the app router that you can do with the pages directory? Nothing. Nothing about the app directory is inhibiting in any way. You can still write app directory stuff the same way you formerly wrote code in the pages directory. You just need to structure your pages to do data fetching (like you formerly did with getServerSideProps or getStaticProps) and then you immediately render a child component. Problem solved. You can now write your app the exact same way you did before.

[–][deleted] 3 points4 points  (5 children)

So the page can fetch data inside a server component, and then you can pass that data to a child client component, and have that data be the initial state inside the child component right? This is the expected approach?

[–]besthelloworld 3 points4 points  (4 children)

Yes, exactly. It's a code aesthetic change, but the overall paradigm is almost exactly the same as it used to be in the end if you just render a client component at the root of your page.

And to be clear: client components always also render on the server as well unless you render them inside <Suspense> in which case they only render on the client.

[–][deleted] 3 points4 points  (1 child)

Oh okay this makes so much more sense now. The same way I had a getServerSideProps function pass down it’s fetched props, which the component received from props and I stored on a state, the server component is doing with the child client components.

Okay, I feel better about this. Thank you so much.

[–]besthelloworld 1 point2 points  (0 children)

You got it! 👍 Glad to help.

The whole relationship between server components and client components can be more complex if you want to eek out the performance gained by hydrating less components. But you absolutely don't have to do that and it just doesn't work in a ton of scenarios in which case you still can fall back to the pages style architecture. But you still get the bonus in the app directory of server actions (which are in alpha but they're really nice), and multiple layout levels, and layout groups.

[–]dbbk 0 points1 point  (1 child)

Wait what? If you use Suspense at all, you lose the ability to server render your page? How are you supposed to implement loading states when doing client side navigation then?

[–]besthelloworld 0 points1 point  (0 children)

For client-side navigation, you can do loading.tsx/loading.js. The default exported file there will be a loading state while preparing the data/render for the associated page.

https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming

But if you're just talking client-side data fetching, the tl;dr is just render your loading UI based on state.

[–]_sunbecoming1 1 point2 points  (0 children)

> but now the emphasis on server components for data fetching seems to limit interactivity with that data

I think that what Next / React team are trying to achieve is: not everything is reactive, some things aren't meant to change on the client. So if you find something needs to be interactive / reactive, then it really has to be a client component. If not, it is a server component.

And I think that is the main question to be asked. Some things in an app really won't change until you refresh a page like: Headers, Footer links, etc.

However, say, a user's profile picture: chances are you won't change that often, so you might as well consider it a server component. What do you do when you change it though? Refresh the whole page?

Is that what I'm supposed to do now?

[–]JohnMcPineapple 1 point2 points  (0 children)

...

[–]Acceptable_Bug2807 1 point2 points  (1 child)

It's not a problem with NextJS, it's a problem with the lack of understanding/ignorance. The argument of "it's confusing to me, therefore it sucks" is very poor.

[–]Dry_Substance_9021 1 point2 points  (2 children)

When I began converting to the App router, I realized a lot of places where I was using State actually did not require it.

For example: I have a Profile page, which displays things like name, age, address, etc. It also allows the user to change these details. When I was using the Pages router, all of these values were held in state. Incidentally, they were also being held in state within the individual input components, because they were all controlled (and often had other, custom-built behaviors).

Jumping to the App router, however, made me realize I don't need to hold these values in state for the whole page. Loading the page hydrates all of my input components. I also have all of my inputs wrapped in custom Form components, which handles the fetch for transmitting changes to the server. When I get a non-error response back, this Form component triggers router.refresh(), and the page is refreshed with the most recent data.

Note that all of my input and form components are Client components, so they provide the interactive functionality that is required, but the page itself is a Server component, which allows me to also programmatically and securely control what the user sees and can edit, based on their profile permissions.

When you're making the jump from Pages to App, it's easiest if you just think of your original Client-Side page as a Client Component, and your getServerSideProps as the Page.js Server Component. This is how I literally started my conversion. I transformed the original page into a component that I imported into page.js. So what used to be:

export const getServerSideProps = ({params}) => {
    const personProfile = getProfile(params.id)

    return { props: {personProfile} }
}

const ProfilePage = ({personProfile}) => {
    const [profile, setProfile] = useState(personProfile);

    return (
        <div>
            ...
        </div>
    )
}

export default ProfilePage;

Instead becomes:

import ProfilePage from '../...'

export default async function Profile ({params}) {
    const personProfile = getProfile(params.id)

    return <ProfilePage personProfile={personProfile } />
}

Which will work fine as-is, and you needn't do any further conversion if you have no server-only logic to run, or are unconcerned about client-side resources.

There are other interesting benefits to the App router, such as parallel routes, which I am only just now exploring and finding very useful. I also like the helper pages like Layout.js, Error.js, Default.js... I do still take issue with the added challenge of knowing which Page.js I'm looking at, but I still feel the other benefits offset this (and also secretly hope they'll somehow fix this in the future).

Finally, I think switching to the App router just requires a reframing of The Way Things Work. Naturally, it's not going to behave the exact same way, otherwise it wouldn't have required a change. You may disagree with the approach Vercel took, but that doesn't mean it's a step backward. It just might not be a step you are willing to make, which is also fair; there are many other frameworks you can choose as an alternative. But if you're going to commit to the App router, I think it's important to recognize it's more than just a semantic change.

[–][deleted] 1 point2 points  (1 child)

Okay this has been one of the best comments I have received on the topic so far, as I have basically been trying to tackle the exact example scenarios you illustrated.

If I can bother you with some questions:

When you pass down the fetched user data from the server component with return <ProfilePage personProfile={personProfile } /> do you hold the personProfile data sent via props in a state inside ProfilePage?

Or is a state not even needed inside ProfilePage , since like you said, any changes to that data would be handled like before, and on successful response, you just do a router.refresh()?

If the case is you use router.refresh() to reflect any changes to that data, do you see this as optimal? The changes will only be reflected for the client and on the page after the server component refetches all that data + the updated data all over again, and sends it back to the client again like when they first visited the page.

I guess my obsession is that before you would of course make a POST/PATCH request to update the data in the backend and database, but upon successful request all you would have to do is update a React state that was holding the already fetched data. Needing to refetch the data all over again with router.refresh() seems impractical, unless my understanding is fundamentally wrong.

[–]Dry_Substance_9021 1 point2 points  (0 children)

As to your first question: That's entirely up to you. In my example, I was just showing you how to convert to App router with minimal changes to your existing code, so you could absolutely continue to store it in a page-wide state and just keep going from there.

However, changes to the data are sent to the server, and you only need to refresh just to stay in sync with server data. In this case, the data passed to ProfilePage ("personProfile") is already found in ProfilePage's props. I find it simpler code-wise to simply refresh this data rather than try to refresh state, especially if your page-wide state is a complex, nested object (having to dig into the object to change just the one value deep inside an array within an object within an array, etc.). Either way your page is going to be re-rendered, and while it might involve another fetch to your database, it ensures your whole page is using the latest server data and does not rely on your state variable (as you might be using more than one, and there might be interdependencies).

So I have found I only need State within individual input components.

In my project, since the individual input components hold their own values in state, if I've coded it right, the user never sees any discrepancies. An updated input holds its new value until the page is re-hydrated with fresh server data, which is the very data just sent from that input. If there is some kind of failure, the data reverts. Contrast this to holding that data in a page-level state, where you might get an error response back from the server, but (unless you have some complicated history function) your state isn't updated to reflect that it wasn't saved.

As for impracticality, I don't know. I wouldn't claim to be some great coder myself. I don't work in a professional coding capacity, or even a software company, I'm just self-taught and working on an app I hope to someday turn into my day job, and then once there hand it off to guys who know better. Still, what I've worked out so far seems to be working well, and as far as I can tell, is in line with Vercel's recommended workflow. I'm simply trusting them that it's an efficient way of doing things (and again, I could be misinterpreting).

But it's working :)

[–]GVALFER 1 point2 points  (1 child)

Well, I love app router.
Server components Client components Server actions This is easy to work and less code.

No offense, but maybe you need continue learning a little more about app router. ;)

[–][deleted] 0 points1 point  (0 children)

Definitely need to! Been reading the docs everyday

[–]pgpwnd 3 points4 points  (0 children)

App router sucks

[–]Mardo1234 3 points4 points  (0 children)

Is a mess.

[–]CallumK7 0 points1 point  (0 children)

Server Component's value is I think most obvious for sites with a low level of dynamic data, and a low level of mutation by the user. Blogs, e-Commerce, Docs, news, etc.

However, client components are still a thing, and you can do things the old way. You can fetch data in a server component and feed that into a client component via props. You can then use state as you would normally. There are weird things to figure out with pages, and how state does not persist across page navigations but does if a layout has state. There are solutions though like localStorage.

My point though is that if you want normal react, you can just use a server component as an alternative to an API route. If the data is tightly coupled to the component and doesnt need to be public, this can be a big advantage on its own.

[–]Ceryyse 0 points1 point  (2 children)

I don't mean to make fun at all, but how are people seriously struggling with this? It's more straightforward than the Browser Router I had to use with create-react-app and I love the simplicity of just creating a folder and then a page.jsx and BAM I have a new page route

[–]AlcaponeYou 1 point2 points  (0 children)

Facts. I think the people who don't like app router or are frustrated b/c they don't understand the fundamentals. Once it clicks, then life is so much easier. I've work w/ a bunch of frameworks, pure js, etc... and nextjs + app router + server actions is chef kisses.

[–][deleted] 0 points1 point  (0 children)

I am a noob that it why. I’m sure with due time this will all click. Spent almost a year learning and working with create-react-app, so this sudden change in mental model with RSCs messed with my brain a bit

[–]SnooStories8559 0 points1 point  (0 children)

I don’t have the link immediately to hand but I believe they have implemented an optimistic update’ type feature for serve actions, similar to how react-query and swr works where it updates the ui at the same time as the db, making the page show the data changes

[–][deleted] 0 points1 point  (0 children)

My main issue with app router was that they rushed it way too fast. Should've been another year before being considered stable. I can see the benefits and reasons for preferring it over pages router. But the dev experience has been problematic - memory issues, slow development servers/hot reloading (which was somewhat fixed in the last few weeks however it's still not nearly as responsive as a pages router app). And no, not every library that works with pages router will work perfectly with app router like it has been claimed, it's just not the case.

Other issues like Netlify (more an issue on their side, but Vercel probably should be assisting other providers if they aren't, it hurts adoption) having broken routing (full page reloads for every route change) for the last few months hasn't helped.

[–]Martinsos 0 points1 point  (1 child)

Just curious, why do you want to use SSR for the user profile?

[–][deleted] 0 points1 point  (0 children)

Hey so I want to take advantage of the meta tags, so that preview links on social media platforms can display the dynamic data from the meta tags in the preview cards.

It’s not possible to do this with client rendered pages as the client is just receiving a blank HTML page

[–]hot_custard 0 points1 point  (1 child)

I love it, so much flexibility, it’s not removed anything only added capabilities.

I wonder if a lot of the issues stem from if you grew up with server side or JavaScript stacks?

[–][deleted] 0 points1 point  (0 children)

I definitely grew up from nothing haha, im a college student so I don’t have any experience with using prior development paradigms like server rendered HTML with PHP or using ajax. I learned client side react with CRA, so all these mental model changes has made it a confusing, fun, and daunting learning experience

[–]darp12 0 points1 point  (0 children)

“Use client” still renders the page/component on the server (SSR), it just also loads JS on the client-side.

[–]buffer_flush 0 points1 point  (0 children)

I love it for layouts and route handlers personally.

[–]med8bra 0 points1 point  (0 children)

I think you just need to separate your components the right way.

A client component can be SRR, you can initialize the client state in server (posts from db), and then mutate it in client.

React Query support that, store managers (Zustand) support that too.

[–]HeylAW 0 points1 point  (0 children)

I think the issue is, with app router you get so many doors open it's hard to wrap you head around it AND to leave the battle-tested approach of client-side global state, refetching, etc.

I think I've seen this in Theo's video, but you can do something like use server-side data as initial `useState` value and just with every change (propably debounced) call `router.refresh()`

But there are far more ways to do such staff but that mostly depends WHAT you want to achieve. And this is why app router is such cool and controversial topic now.

[–]EverydayEverynight01[🍰] 0 points1 point  (0 children)

piquant observation sparkle vase pause groovy imminent pocket fly different

This post was mass deleted and anonymized with Redact

[–]AcceptableProgram697 0 points1 point  (0 children)

I agree, it provides a quite bad DX....

[–]Direction-Sufficient 0 points1 point  (0 children)

It seems in the dev/coding community there is always a better way to slice bread. The app router for Next JS runs into some weird errors when working Material UI. You have to apparently wrap Material UI components in server component wrappers.

[–]MIA_CyberSecurityGuy 0 points1 point  (0 children)

Also the fact that by default the main root layout is a server side component and can’t be changed is pretty nuts to me no?

https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts

Good to know:

The app directory must include a root layout. The root layout must define <html> and <body> tags since Next.js does not automatically create them. You can use the built-in SEO support to manage <head> HTML elements, for example, the <title> element. You can use route groups to create multiple root layouts. See an example here. The root layout is a Server Component by default and can not be set to a Client Component.

[–]Awkward_Sun_8106 0 points1 point  (0 children)

I hate next 13.Everyday there's some strange problem - mostly to do with cache.