10 common mistakes with the Next.js App Router

Vercel
8 Jan 202420:37

Summary

TLDRThe video outlines 10 common mistakes when building Next.js applications using the app router. Topics covered include: incorrectly implementing route handlers, misunderstanding route handler defaults and caching behaviors, unnecessarily using route handlers with client components, improperly utilizing Suspense boundaries with server components, not accessing request data in server components, misplacing context providers in the component tree, misunderstanding client/server component relationships, forgetting to revalidate data after mutations, throwing redirects inside try/catches instead of using routers or actions. The goal is to help developers avoid these pitfalls and build better Next.js apps.

Takeaways

  • 😯 Don't call route handlers from React components, call functions directly instead
  • 💡 Route handlers are cached by default like Pages, make them dynamic if needed
  • 😀 Server actions work with client components too
  • 🤔 Place Suspense boundaries above data fetching components
  • i️ Use component props to access request info like headers and params
  • 🔀 Context providers belong in Root layout, not wrapped around each component
  • 👪 Client components don't need explicit `useClient` if parent is already client
  • 😠 Common mistake to forget revalidating data after mutations
  • ❗️ Don't throw redirects inside try/catch blocks
  • 🎓 Lots of opportunities to learn from mistakes building with Next.js!

Q & A

  • What is a common mistake developers make when using route handlers in Next.js applications?

    -A common mistake is thinking that route handlers need to be called from React server components, leading to unnecessary network requests by fetching data from an API route that could be directly accessed or function calls within the server component itself.

  • How does the behavior of route handlers differ between local development and production environments in Next.js?

    -In local development, route handlers might return new values on each request due to caching behavior being different. However, in production, after building and starting the server, the data is cached by default and does not change on each request, showcasing the difference between local and production environments.

  • Why is it considered a mistake to use fetch within React server components for accessing local data in Next.js?

    -Using fetch within server components to access local data is unnecessary because both the data fetching and the component rendering occur on the server. Developers can directly call functions to retrieve or manipulate data without making an extra network request.

  • What is the purpose of route handlers in Next.js applications?

    -Route handlers allow developers to handle HTTP verbs like GET, POST, PUT, and DELETE, enabling API routes for fetching or mutating data. They are particularly useful for handling webhooks or external requests.

  • Can server actions be used with client components in Next.js?

    -Yes, server actions can be used with client components to simplify interactions, such as form submissions, without the need for additional code to handle route handlers, thus streamlining the development process.

  • What is a common misconception about using suspense with server components in Next.js?

    -A common misconception is placing suspense boundaries incorrectly, specifically not placing them higher than the data fetching component. For suspense to work effectively, the suspense boundary needs to encompass the component where data fetching occurs.

  • How can developers handle incoming request data in server components with Next.js?

    -Developers can handle incoming request data by utilizing built-in functionalities like headers, cookies, params, and search params. These allow reading information from the request, such as headers or URL parameters, directly within server components.

  • What is a common mistake when integrating context providers in Next.js applications?

    -A common mistake is incorrectly placing context providers within the component tree. The best practice is to place them in the root layout, allowing the application to maintain server components as children while still utilizing client components where necessary.

  • Why is revalidating data after a mutation important in Next.js applications?

    -Revalidating data after a mutation is crucial to ensure that the UI reflects the latest state. Without revalidation, changes made through server actions may not be immediately visible, leading to a mismatch between the server state and the client display.

  • What is the recommended way to perform redirects in Next.js applications?

    -The recommended way to perform redirects is to use them outside of try-catch blocks or in a finally block to avoid conflicts with error handling. For client-side redirects, the useRouter hook should be used for programmatic navigation.

Outlines

00:00

😊 Common mistakes with route handlers

The paragraph discusses common mistakes developers make with route handlers in Next.js, such as incorrectly calling route handlers from React components instead of directly calling the handler function, not understanding route handler caching behaviors, and using route handlers unnecessarily with client components when server actions can be used instead.

05:01

😩 Forgetting to revalidate data after mutations

This paragraph explains the common mistake of developers forgetting to revalidate data with cache tags or revalidate path after mutating data, such as after submitting a form. It provides the example of adding a todo but not seeing the todo list update.

10:03

😖 Incorrect suspense usage with server components

The paragraph discusses the mistake of improperly wrapping suspense boundaries around server components that fetch data, which results in suspense fallbacks not being triggered. It explains how to correctly use suspense above server components to enable proper pre-rendering.

15:03

😟 Context provider placement with server/client components

This paragraph explains the ideal placement of context providers is around the root layout server component, allowing server components and client components to consume the context properly. It also clarifies that client components do not need extra useClient calls.

20:03

😕 Redirects incorrectly used inside try/catch blocks

The paragraph points out that developers commonly make the mistake of trying to do redirects inside try/catch blocks, when redirects internally throw errors. It explains redirects should be used after try/catch instead.

Mindmap

Keywords

💡route handlers

Route handlers allow defining HTTP verbs like GET, POST, PUT, DELETE to expose APIs for getting or mutating data. They are often confused with API routes from pages router, but route handlers can be called directly without an API request.

💡caching

Route handlers have caching behavior similar to pages - they are cached statically by default in production, generating same response on each request. Options like reading request headers/cookies or POST requests make them dynamic like API routes.

💡server actions

Instead of needing route handlers for submissions from client components, server actions allow calling server logic directly without extra network requests. They simplify client-server interactions.

💡suspense

Suspense allows data fetching closer to UI components and handles loading states. Common mistake is wrapping component instead of parent component, which prevents fallback from working.

💡request context

Server components give access to request info like headers, cookies, route params, search params to forward headers or read data like auth tokens. Useful for server-request interactions.

💡context providers

Context providers should be placed in root layout component, not wrapping individual components. This keeps layout component a server component while allowing children like pages to be client components.

💡client components

Children of client components are client components by default without needing explicit useClient. Server components can also be children to weave client and server components.

💡revalidation

Common mistake after data mutations (like adding todo item) is forgetting to revalidate cached data. Can revalidate page path or add cache tags to revalidate specific data.

💡redirects

Redirect throws special error so shouldn't be used in try/catch blocks. Should be used after blocks instead or with useRouter hook in client components to avoid crashes.

💡mistakes

Article frames common problems as mistakes, but admits they are really opportunities to learn something new as the framework and patterns are still evolving.

Highlights

Mistake: Calling route handlers from React server components is unnecessary; direct function calls are more efficient.

Explanation of route handlers and HTTP verbs, emphasizing their use for data retrieval and mutation.

Clarification on route handlers vs. API routes, highlighting common misconceptions.

Illustration of an unnecessary network request scenario with route handlers and its efficient alternative.

Discussion on the defaults for route handlers and common confusion points.

Insight into local vs. production behavior of route handlers and caching mechanisms.

Introduction to the concept of partial pre-rendering and its implications for route handlers.

Highlighting the misuse of suspense with server components and the correct application.

Understanding the need for dynamic route handlers through example of a git pattern.

Clarifying the use of server actions with client components to simplify code.

Demonstration of server actions replacing the need for route handlers in form submission.

Discussion on context providers and their placement within Next.js applications.

Explanation of server and client component interweaving and common mistakes.

Advice on revalidating data after mutations to ensure consistency.

Caution against improper use of redirects in try-catch blocks within Next.js.

Transcripts

play00:00

I've talked to hundreds of developers

play00:01

building with the xgs app router

play00:03

probably looked at over a thousand

play00:04

different repositories and here are the

play00:06

top 10 mistakes that I've seen that

play00:09

hopefully can help improve your next

play00:11

nextjs application let's get into it

play00:13

okay first is thinking you need to call

play00:15

route handlers from your react server

play00:18

component now I have to step back a

play00:20

little bit here and talk about what a

play00:21

route Handler is in the first place a

play00:24

route Handler allows you to have verbs

play00:26

httv verbs like get post put and delete

play00:29

for example and have a API exposed that

play00:33

allows you to get some data or mutate

play00:36

some data now for folks coming from the

play00:38

pages router World they might think wow

play00:40

this seems basically like the same thing

play00:42

as API routes and that's usually where

play00:46

the mistake comes in you make a route

play00:48

Handler like this which is a g it

play00:51

returns some Json response that is hello

play00:54

world and I go back inside of my page I

play00:57

mark it is async I say okay I want to

play01:00

have fetch to localhost sl3000 API I'll

play01:04

get back this Json data and then I'll

play01:07

printed out here in the H1 and this does

play01:10

work but it's actually kind of a mistake

play01:14

because for two reasons one you have to

play01:16

hardcode the full URL because you're

play01:18

here in the node.js context but two you

play01:21

actually don't even need that extra step

play01:23

or that extra Network request because

play01:26

this runs securely on the server as well

play01:29

as this running cely on the server

play01:31

instead you could just put that Json

play01:34

here you could just call that await get

play01:37

user or whatever that function is here

play01:40

whatever that promise is directly

play01:42

without needing to use the route Handler

play01:44

in the middle so typically when I see

play01:46

something like this I would cut it and

play01:48

it would be let data equals away either

play01:51

fetching to somewhere externally and not

play01:53

having the route Handler in between or

play01:55

just calling that function that you've

play01:56

abstracted out here as well too so

play01:58

that's number one okay building off this

play02:00

for number two let's talk about the

play02:02

defaults for Route handlers this is

play02:04

another place that I see people get

play02:05

mixed up so let's say you did need a

play02:08

route Handler for some reason I think

play02:11

most of the time when I see people

play02:12

actually needing route handlers it's for

play02:14

handling web hooks or for handling some

play02:18

sort of external request in their

play02:20

application maybe it's for scaffolding

play02:22

out something like next off for example

play02:24

but they create a route Handler just to

play02:26

test things out so they make something

play02:28

like this and they're wondering why

play02:31

let's say I put in something like

play02:35

date and let's do yeah let's do

play02:38

something like this so I have a date and

play02:40

I have a new date and a local string of

play02:42

New York now if I go to localhost

play02:46

3000i I'm going to see this new date

play02:48

string and if I reload the page I'm

play02:51

getting a new date on every single

play02:53

request now there's two opportunities

play02:56

here to better understand how this model

play02:57

works the first is understanding the

play02:59

difference between local and production

play03:02

so in local even though this data is

play03:05

Cash which I'm going to get to in a

play03:07

second you're going to get a new value

play03:09

it's going to get recreated on every

play03:10

single request and secondly is

play03:13

understanding why this is cashed by

play03:16

default so let me show the first one let

play03:18

me open up my terminal and I'm going to

play03:22

run um run build and run starts so I'm

play03:27

going to do a production build of my

play03:29

application and then I'm going to start

play03:30

up my local Dev server my production

play03:32

server on my Local Host so now if I go

play03:35

back to here and I reload the page it

play03:38

never changes so this is a difference

play03:40

between how your local uh your local Deb

play03:43

environment is working through next Dev

play03:45

versus doing that production build and

play03:47

then serving your production server now

play03:49

the question is why does it work this

play03:51

way well this is actually pretty

play03:53

powerful if you understand more of the

play03:55

intention behind it a route Handler is

play03:58

the base of how Pages work inside of the

play04:01

app router as well too and Pages can be

play04:04

cached by default so even if I'm doing

play04:06

an asynchronous component or a server

play04:08

component and I'm fetching some external

play04:10

data that doesn't necessarily have to

play04:12

run on demand on every single request

play04:15

it's kind of like instead of a server

play04:16

component it's a data component because

play04:18

you can fetch data you can pre-render a

play04:21

page that only was pre-rendered on the

play04:23

server and then you don't have to have

play04:24

any additional client.js for that long

play04:27

story short the options for how route

play04:30

handlers work are the same as pages so

play04:32

by default this is cached static which

play04:35

means that anything that I do here to

play04:38

opt into making this Dynamic it will

play04:40

then work the same way as a traditional

play04:42

API route so for a git for example if I

play04:46

were to read request. something so maybe

play04:49

I want to read the incoming search

play04:51

parameters or maybe I want to read uh

play04:54

the headers that would opt it into being

play04:56

Dynamic you can also use the helper

play04:58

functions that we have headers as well

play05:01

as cookies that will read from the

play05:03

incoming request or more commonly what I

play05:07

see is that folks are doing a post

play05:10

request so if you're doing a post

play05:12

request because you're probably um maybe

play05:14

it's something with web hooks again post

play05:16

requests will be dynamic by default as

play05:18

well too now the reason that this git

play05:21

pattern and this is very interesting is

play05:24

because maybe inside of here I want to

play05:27

do let's say data equals await

play05:33

fetch um wow shout out to Luke who has

play05:37

their user named on

play05:40

here and their amazing contributions to

play05:42

open source um let's say I want

play05:45

something like this and then maybe I'll

play05:49

do

play05:50

this and let me just go back to my Deb

play05:54

server

play05:55

here and we're going to see that it

play05:57

prints out some information about my my

play06:00

GitHub profile now the really

play06:03

interesting thing here is in the pages

play06:05

router model having an API route

play06:08

required that you had a server but

play06:10

there's also an option in xgs that

play06:12

allows you to do a static export and

play06:14

basically take the generated files and

play06:16

put them anywhere put them on a server

play06:17

somewhere um put them on an S3 bucket

play06:21

somewhere it doesn't have to be

play06:22

something that's always on right so the

play06:25

cool thing about this again if I do the

play06:27

build and I start it up since I have the

play06:30

ability to Define this arbitrary route

play06:32

that can generate maybe it generates

play06:34

Json maybe it generates an XML file

play06:36

maybe it generates a text file I can do

play06:39

this and it can still be compatible with

play06:40

that static export model so this would

play06:44

work and even if we wanted to do a

play06:45

static export we can still use that now

play06:48

I will say most of the time you probably

play06:51

don't need to do anything like this with

play06:53

route handlers because you can just call

play06:55

that function directly on the page the

play06:58

server comp component instead okay third

play07:01

is thinking that you need a route

play07:02

Handler because you're using a client

play07:04

component so so far I've talked about

play07:06

server components and your next question

play07:08

might be yeah but I'm using route

play07:10

handlers because I have client

play07:11

components let's talk about that one as

play07:13

well too so I change my page to be a

play07:16

client component I added a form and a

play07:19

button that takes some Advent Handler

play07:20

for onsubmit and then in onsubmit I just

play07:24

preventing the default and I'm logging

play07:25

submit so inside of here what you might

play07:28

say is okay so now I need to make a

play07:30

fetch to Local Host API have my route

play07:34

Handler and then I'm in that tricky

play07:36

State again with having to set up route

play07:38

handlers when maybe I I don't need to so

play07:41

this is what happens I click send it I

play07:43

see in the console I hit submitted what

play07:45

if I told you that you didn't need to do

play07:48

it this way and you could skip writing

play07:50

all this additional code and just call a

play07:52

server action instead yes server actions

play07:55

can work with your client components as

play07:58

well too so what if if we delete this

play08:01

and we take this and we say you know

play08:03

what action is going to equal

play08:06

send and we import send from our actions

play08:10

notably we're importing it here and

play08:13

we're not putting it in line inside the

play08:14

file this is a use client file we're in

play08:17

the client uh bound we're on the client

play08:19

boundary here versus this actions on the

play08:21

server so inside of actions we have used

play08:24

server we have this function send it and

play08:27

if we go back here hit save click send

play08:31

it now you notice the logging position

play08:35

was different too I didn't see my client

play08:37

side event handler say that it was

play08:39

submitted in the browser instead it just

play08:41

directly called the server and said send

play08:43

it which is where I would have that

play08:44

logic that was in my route Handler in

play08:46

the first place so this can drastically

play08:48

simplify things uh if you want to take

play08:51

this further as well too there's some

play08:52

cool things you can do with use

play08:55

optimistic and use form State use form

play08:57

status some other built-in utilities to

play09:00

make working with forms better in nextjs

play09:02

so definitely check that out too okay

play09:04

fourth we have using suspense with

play09:06

server components and I'm going to talk

play09:07

about this through the lens of partial

play09:09

pre-rendering which is an upcoming

play09:10

addition to nextjs it's out

play09:12

experimentally right now but you'll

play09:14

start using suspense more and more in

play09:15

the future so it's helpful to start

play09:18

thinking about this now so in this

play09:19

partial pre-rendering demo I reload the

play09:22

browser I see these loading States this

play09:25

is all defined by my suspense boundaries

play09:28

which is super super helpful so

play09:30

understanding how suspense works is a

play09:32

big unlock for the future of nextjs so

play09:35

let's talk about it let me move this

play09:37

back here what I have is a server

play09:41

component it's marked async and I'm

play09:43

making a call to fetch a list of blogs

play09:46

and then I've enumerated them and listed

play09:48

them out on the page so for example if I

play09:50

said Okay I want this function let's

play09:54

just say this is blog

play09:58

post

play09:59

and we're going to say export

play10:02

default function

play10:05

page uh and maybe I want to have some

play10:08

additional information on this page so

play10:10

I've got this section for my page I've

play10:12

got an H1 I've got blog post that all

play10:16

looks fantastic now in a partial

play10:18

pre-rendered World you'll be able to

play10:20

pre-render all of this right now you're

play10:23

pre-rendering everything because there's

play10:24

no suspense ball back but there's a

play10:26

reason why you're moving this data

play10:28

fetching closer to your UI is because

play10:30

this will be pre-rendered when you run

play10:32

your build so you might say okay that

play10:35

means that I want to use suspense with

play10:37

my blog post so that I can have a

play10:38

fallback and let it get pre-rendered or

play10:40

have a loading state so you know what

play10:44

let's do this let's wrap let's do um

play10:49

suspense we'll import that we'll have a

play10:51

fallback cool so we have this fallback

play10:54

loading and then we render this here

play10:57

okay so I reload the page

play10:59

but nothing is happening now the mistake

play11:02

here and I don't know who would make

play11:04

this I've definitely never made this

play11:06

mistake just kidding I've definitely

play11:08

made this mistake uh is that you want

play11:10

your suspense boundary to be higher than

play11:14

your data fetching component seems

play11:16

obvious in retrospect but it definitely

play11:19

happens and I I can understand how

play11:21

people fall into this so in reality

play11:23

you'd want something like

play11:26

this now not only can my blog be

play11:29

pre-rendered in the future but also the

play11:31

fallback State you probably wouldn't say

play11:34

loading in that world you might have um

play11:37

you might have it be empty or you might

play11:39

have a loading skeleton for example but

play11:42

yeah this is this is the difference here

play11:44

now what you're wondering is okay well

play11:47

why am I not seeing that state and

play11:49

that's because this by default is being

play11:52

cached so another thing to prepare us

play11:54

for this partial pre-rendering future is

play11:57

that I can say I want to

play11:59

make this

play12:00

Dynamic and right now this function is

play12:03

called unstable no store uh so I can

play12:06

import this here I can reload and now

play12:09

we're seeing this Flicker and that

play12:11

flicker means that this bit should not

play12:14

be cash it should run dynamically and

play12:16

that means that we are seeing the

play12:18

suspense fall back just to make it more

play12:22

dramatic you see loading as well too so

play12:24

hopefully that helps uh we'll be talking

play12:26

a lot more about suspense in the future

play12:28

but at least for now as you start

play12:30

thinking about your application

play12:31

structure as you start exploring

play12:32

suspense helpful tip to know I think

play12:35

okay the fifth tip here the fifth

play12:36

mistake that I see sometimes is

play12:39

understanding how you can use

play12:40

information about the incoming request

play12:42

in your server component so maybe you

play12:45

want to forward headers to a fetch for

play12:47

example you can use the headers function

play12:50

to read those headers or maybe you want

play12:53

to read the cookies for example because

play12:55

you want to look at an authorization

play12:57

cookie that you've stored or JWT that

play12:59

you've stored um maybe you want to look

play13:03

at the parameters or the route segment

play13:06

parameters in your url those as well as

play13:09

the URL search parameters are actually

play13:12

props on the server component so you

play13:14

have params and you have search params

play13:17

so if I wanted to for example let's say

play13:21

inside of here instead of this let's do

play13:24

a

play13:25

H1 and we're going to read search par

play13:32

dot let's say hello

play13:35

awesome so inside of here I'm going to

play13:38

make a new search program hello and I'm

play13:40

going to say

play13:42

world and now I'm able to read that

play13:44

incoming information from the request or

play13:46

I could read the prams if I have Dynamic

play13:49

route segments in my URL I can read

play13:51

those as well too so there's a couple

play13:53

different ways you can read from that

play13:54

incoming request using some of these

play13:56

built-in functionalities in nextjs okay

play13:59

six and seven for most common mistakes

play14:01

are how to use context providers and

play14:04

where you place them in your application

play14:06

sometimes placed incorrectly and the

play14:07

second is the in weaving or the inter

play14:10

leaving between server and client

play14:13

components so for example if I have my

play14:15

root layout here on the left you might

play14:16

be thinking okay I have some components

play14:19

I have some dependencies that require

play14:21

react context where do I place that

play14:24

provider in my application do I have to

play14:26

put it around the lowest component in

play14:29

the tree do I need to have it at the top

play14:30

of the tree does that mean that

play14:32

everything below it is going to be a

play14:35

client component well this pattern it's

play14:37

explained in the docs I want to visually

play14:39

show it a little bit here let's imagine

play14:41

that I have some theme provider here and

play14:44

this is using react context now this can

play14:47

take in some children and this is a

play14:49

client component but the ideal place to

play14:53

place this is actually in the root

play14:56

layout so what we'd want to do like we

play14:58

show here is actually take this and I

play15:02

think I have my file name differently I

play15:05

think it's called

play15:06

providers but we would actually want to

play15:10

take that theme provider wrap it around

play15:12

the children of our root layout so wrap

play15:15

it around the children of our

play15:16

application this is still a server

play15:18

component and that still allows children

play15:21

of this like the page for example that

play15:25

still allows this to be a server

play15:26

component so the child of a server

play15:28

component can be a client component this

play15:31

works as we would expect this actually

play15:34

goes into the next most common mistake I

play15:37

see which is when you apply used client

play15:40

does that apply for everything does that

play15:43

apply to its children and how does that

play15:45

relationship work and I will say this is

play15:47

all new so while I'm framing these as

play15:50

mistakes I think they're all learning

play15:51

opportunities for us so don't feel harsh

play15:54

you know I've made this I've made all of

play15:56

these mistakes in this video um so this

play15:58

top level layout is a server component

play16:01

but then the child of it is this

play16:04

children prop here that goes to the page

play16:07

so the page is the child of the layout

play16:09

now the child of this page is this

play16:12

button component let's take a look at

play16:14

this button component this button

play16:15

component is a simple client component

play16:18

that has a counter so it has some State

play16:21

you click on it the state increments and

play16:23

we see this new uh this new state

play16:25

reflected in the button text so this is

play16:27

already showing how you can weave server

play16:29

and client components but the question

play16:31

then becomes what about the children of

play16:34

this component so for example let's say

play16:37

that instead here I'll just do a

play16:39

fragment and then I'll have this but

play16:41

then I'll also have another button and

play16:44

this other button is also a client

play16:48

component so I have this button I have

play16:50

another button and another button here

play16:53

do I need to explicitly have used client

play16:56

at the top well the answer

play16:59

let's find out the answer is no and the

play17:02

reason you don't is because you're

play17:03

already in the client boundary here so

play17:06

the child of this component are going to

play17:08

be client components unless for example

play17:13

I take some children and let's say I

play17:15

want to have the children here you can

play17:19

still weave in the server components as

play17:21

well too so then maybe here for

play17:24

example I know this is kind of a

play17:26

contrived example but I think it's still

play17:28

works this is a client component this is

play17:32

a client component this is a server

play17:34

component and they can all work together

play17:36

now the big opportunity here and why yes

play17:39

it's a mistake but it's also an

play17:40

opportunity is that we need to have Dev

play17:42

tools that help you visualize these

play17:44

things and we're definitely working on

play17:45

making this experience better so that

play17:47

you can understand the state of how your

play17:49

server and client components work

play17:51

together okay two more second to last

play17:53

the mistake I see most commonly is just

play17:55

forgetting to revalidate data after a

play17:58

mutation so in the nextjs repo we have

play18:01

this fors example which I'd recommend

play18:02

checking out it shows a server component

play18:05

that fetches a list of to-dos it renders

play18:07

out the list of to-dos it has a form to

play18:10

add a new to-do and inside of this form

play18:12

it uses a lot of the latest features

play18:14

like server actions so I have an action

play18:16

to submit the form to add the new to-do

play18:20

and what I see a lot of folks do is they

play18:22

start using server actions maybe they're

play18:24

moving from the older model where they

play18:26

were trying to map it one to one to

play18:28

Route handlers and they move to this and

play18:30

they hit the button and they hit submit

play18:32

and they don't see that list of to-dos

play18:34

update and they're trying to figure out

play18:36

what exactly is happening well what

play18:38

they're probably missing is inside of

play18:41

their action in this instance I have a

play18:43

SQL statement here that's inserting a

play18:45

new value into the to-dos table what

play18:49

they're probably missing is some

play18:51

revalidation either revalidating the

play18:53

path or by adding a cach tag onto the

play18:55

fetch or onto that bit of data and then

play18:58

revalidating that specific tag so pretty

play19:01

commonly I see this I know that caching

play19:03

is still very new right now and a lot of

play19:05

these are new patterns we're also

play19:07

working on making caching a little bit

play19:09

easier as well too but this is one that

play19:10

I see pretty common okay and while we're

play19:12

here we can talk about the last one

play19:14

which is throwing a redirect inside of a

play19:18

tri catch so I can understand how this

play19:20

happens I definitely made this mistake

play19:22

myself as well too you're inside of here

play19:24

you've revalidated your path and you say

play19:26

okay awesome now I want to

play19:28

redirect back to the index route for

play19:31

example well internally the way this

play19:33

redirect is working is it's actually

play19:35

throwing an xgs specific error so you

play19:37

would actually want this at the

play19:38

conclusion here either that would be

play19:41

after the try catch or in like a finally

play19:44

block um and I think most common where I

play19:47

see this is either in a server action or

play19:50

if you're trying to use it from a client

play19:52

component so I recently updated the docs

play19:54

here to show an example when you're

play19:56

using a server component for example

play19:58

rather than trying to do a redirect

play20:00

inside of an event handler you would

play20:03

want that to be inside of your server

play20:05

action if you're wanting to do a

play20:06

redirect on the client side in an event

play20:08

handler you'd be using the used router

play20:10

hook which does have the ability to

play20:12

programmatically route and

play20:14

programmatically redirect okay those are

play20:16

10 common mistakes or common

play20:18

opportunities to learn more about the

play20:20

nextjs app router that I've seen I'm

play20:22

sure there's others and we're definitely

play20:24

working on making some of these more

play20:25

obvious both in the framework as well in

play20:28

the documentation so would love to hear

play20:30

what other things you'd like to see me

play20:31

talk more about or go more in depth on

play20:34

any of these as well too peace