21 params and searchParams

这里的params和searchParams是通过url来实现的,这是一种编程方式,虽然说数据的传递可以使用zod、redux这些第三方库,但是nextjs里面的params和searchParams还有非常重要的作用,是和页面联系起来的。

比如说我经常做的管理系统,真正的url就是一些菜单路径,里面的main部分,table页面和操作页面是通过v-if/v-show来切换的。但是nextjs不一样,我把nextjs学完了,也没有看到它使用判断来切换页面。而是通过路由跳转来切换页面的,那么nextjs里面的main部分应该怎么做呢?我以system页面为例,可以这样:

当打开/system的时候,就是搜索栏和table页面;当导航到/system/create的时候,就是新增页面;当导航到/system/create/1的时候,就是编辑页面;当导航到/system/detail/1的时候,就是详情页面。

image-20250910143246485

那么params和searchParams的准确含义是什么呢?

params指的是nextjs里面的dynamic route parameters,就是使用[productId]这种方式定义的。

searchParams指的是url里面的query参数,就是?key=value这种很熟悉的内容。

image-20250910143525678

下面用一个案例来说明这两个参数怎么获取、使用。

1、在app/page.tsx里面,创建两个Link链接,两个链接的params是相同的,但是searchParams是不同的。

2、在app下创建articles文件夹,并创建[articleId]/page.tsx,这一点之前就学过了,忘记了就回头看一下。

可以看到,params和searchParams参数都正常获取到了。

上面的例子是在server components里面获取参数,那怎么在client component里面获取参数呢?下面先将步骤2中的组件改为client component来试一下,添加use client,会报错:

image-20250910150605131

image-20250910150625045

第二个报错还不知道是什么意思,先看第一报错:only server components can be async at the moment。也就是说client components里面不能使用async,怎么解决呢?

需要用到react提供的usehook,这个use是一个hook,用它来代替async...await。

最后,老师提示,page.tsx里面可以获取params和searchParams,但是layout.tsx里面只能获取到params。

image-20250910144352255

老师留了一个练习,如果在layout.tsx里面获取searchParams,会报什么错误。

报错信息如下:

image-20250910152125154

意思是不能从undefined解构出lang,说明此时的searchParams是undefined。

22- Navigating Programmatically

1、编程式路由跳转

这节课主要讲编程式导航。

想象一下你在Amazon下了一个单,提交了一个form,接着会跳转到confirm page,这个时候应该怎么做呢?

我知道这和我这么多年做的项目完全不一样,我做的最多的就是form页面直接提交,然后弄一个message来提示。

但是国外的项目真的不一样,用户习惯也不一样,不要按照老黄历来想国外的项目怎么做。接受、学习就行了。

image-20240831215255055

这里我们通过案例来学习,案例要求通过点击button跳转到别的路由页面来模拟上面的行为。使用的是programmatically navigation。

image-20240831215615074

这里使用useRouter来进行编程式导航,注意要使用这个hook,必须是在client component里面使用,所以在组件文件的top要加上"use client";

注意useRouter是从next/navigation引入的,从next/router引入的报错。

在app中创建order-product/page.tsx,编写组件。

查看效果:

router.push()里面的参数可以是任何valid的route值,可以是嵌套路由地址、动态路由地址、catch-all-routes。

router.replace()方法,可以采用替换history stack中当前路由地址的方式,进行路由跳转。

router.back()方法,可以返回history stack中的previous page。

router.forward()方法,可以前进到history stack中的next page。

2、路由重定向

之前在学习not-found的时候,在mytest/routing-demo/app/products/[productId]/reviews/[reviewId]/page.tsx我们定义了,如果reviewId大于1000,就触发notFound函数。

现在将逻辑改为,如果reviewId>1000,那么就重定向到/products页面,这时需要使用redirect这个hook。

小结:

这节课主要讲了programmatically navigation。使用useRouter这个hook,有router.push()、router.replace()、router.back()、router.forward()这些方法来帮助我们操作路由。

23- Templates

概念

这节课主要讲解template.tsx的概念,template用于一些特定的情况,比如说刷新之后不需要保留原始的input数据,反而必须要求重新渲染。

下面用一个案例来理解templates。

在app/(auth)/layout.tsx中,添加一个input元素,设置初始值。重点就是观察切换路由之后,input里面的值还能不能保持住。

查看效果:

可以看到,在切换路由的时候,input里面的值没有变化,the state is preserved,这是因为layouts only mount the part representing the content of the newly loaded page but keep all the common elements untouched, layouts don't remount shared components resulting in the performance.

上面这段话的“newly loaded page”是什么呢?就是{children}表示的部分。那么common elements是什么呢?就是非children的部分。

在大多数情况下,这是程序员需要的效果,但是sometimes you need the layouts to create a new instance for each of their children on navigation.For example, enter exit animations for pages, or running a side effect using the useEffect hook when the route changes.

要实现这种效果,需要将layout文件替换为template文件,实现起来也很简单,就是将layout.tsx改名为template.tsx,就这么简单。

image-20240907091907516

image-20250910160811729

image-20250910161342985

查看效果:

注意

在同一个路由下,可以同时存在layout.tsx和template.tsx文件,此时的执行顺序是什么样的呢?

the layout.tsx renders first and the layout's children is replaced by the component exported from the template components output.

image-20240907092252968

template.tsx用的并不多,大多数情况下应该使用layout.tsx来做shared UI功能,但是特定情况下遇到了可以使用。

24- Loading UI

image-20240907092440345

image-20240907092519033

creating a loading state is pretty straightforward, you just need to add a loading.tsx file in the right folder.

我们在blog文件夹里创建一个loading.tsx文件,来示范。

为了模拟加载缓慢的情况,我们在blog/page.tsx里面添加一段异步代码,看效果。

this file will automatically wrap page.tsx file and all tis nested children within a react suspense boundary.

可以看到loading的效果。

loading.tsx有哪些好处呢?我知道,但是要用英语说出来。

image-20250910162145558

问题:

这里实现loading效果,是通过在具体的route文件夹里面创建loading.tsx文件来实现的,但如果大部分loading效果都相同,我只需要一个loading文件就行了,此时应该怎么做呢?

答案:就在app文件夹或者主要的文件夹里面创建一个loading文件就行了。

25- Error Handling

image-20240907094734369

nextjs默认的报错页面并不友好,是一个单独的报错页面。如果我们设置了error.tsx,那么哪个报错,哪个地方就被这个文件里面的组件所替代,但是其余的部分都可以正常显示。所以我们需要设置error.tsx。

下面以案例来说明:

app/products/[productId]/reviews/[reviewId]/page.tsx文件中, 编写一个函数,这个函数会在特定情况下抛出错误,用来模拟没有检测出的错误情况,无论是开发时或者打包时都可能报错,这就会造成bad user experience。

不断的刷新页面看效果:

可以看到报错情况:

image-20250910164614639

image-20250910164623920

为了解决这个问题,可以create a error.tsx to wrap around our page.tsx file like an error boundary.

在page.tsx同级创建error.tsx文件,用来包裹住page.tsx里面的错误。

效果:

image-20240907100648891

可以看到报错了,原因是error.tsx必须是一个client component。

image-20240907100806111

查看效果:

需要注意的是,error.tsx只包裹了[reviewId]/page.tsx的错误,the rest of the UI remains unaffected.

this component can also receive the error object as a prop to display more information.

可以看到这里的报错信息就是我们在page.tsx里面抛出的错误信息。

image-20250910163928082

tailored:量身定制。hierarchy:层次、层级结构。granularity:粒度。

下面是我们已经学习过的special files,在同一个文件夹中,会最终转为的层级结构。

image-20240907101550798

component hierarchy:组件层次。

这张图不是说代码可以这么写,而是说如果一个文件夹里面同时存在这些文件,nextjs最终将我们的代码组织成了这样。写代码还是按照功能,区分文件来写。

from the top we have the layout component followed by the template component, next we have an error boundary component from error.tsx which handles runtime errors, after that we have a suspense boundary from loading.tsx, another error boundary component from not-found.tsx which handles the scenario when the resource is not found and finally we have the page.tsx.

26- Recovering from Errors

some errors may not be serious and could be fixed by simply trying again.In this lesson we will learn how to recover from such errors.比如说只是因为有时候网速慢了,没有反应过来,就可以重新请求数据试一下。

error.tsx文件的default组件中,除了可以接收props.error参数,它还接收一个参数,props.reset,这是一个函数,可以在出现error的时候,执行reset函数,可以尝试重新渲染page.tsx中的default组件,这就是reset函数的作用。

但在案例中,只有reset函数是不起作用的,因为在这节课笔记的最后面有提到。

to ensure we can recover on client side, we need to convert our page.tsx to a client component.为了能在客户端恢复,需要将同级的page.tsx转为client component,使用"use client";。但是将一个组件转为client component总是复杂的,根据最新的v15.5.2,我们可以在error.tsx中使用react的startTransition和nextjs的useRouter,更为优雅的解决问题。

image-20250910170715934

 

startTransition的作用:

  1. 优先级区分:被 startTransition 包裹的更新优先级低于用户交互(如输入、点击)
  2. 可中断性:如果有更高优先级的更新(如用户继续输入),过渡任务会被中断并重新计算
  3. 不阻塞 UI:即使过渡任务耗时较长,用户也能正常与界面交互
  4. 配合 Suspense:可以与 Suspense 结合使用,实现加载状态的优雅处理

效果:

注意:这里为什么同时使用router.refresh();reset();?如果说按照我的理解,执行了路由刷新,那么页面就会重新加载,rand不为1的话,页面就会正常。

我在视频的评论区找到了答案:

router.refresh() initiates an asynchronous process to update the server component with fresh data.

reset() immediately clears the error state and forces a re-render of the client components under the error boundary.

When called back-to-back without delay, reset() may use outdated server data because the asynchronous refresh triggered by router.refresh() hasn’t completed.

Wrapping reset() in startTransition delays its execution, allowing the asynchronous refresh to complete and ensuring that the re-rendered components use the updated data.

当点击try again并且page.tsx里面的random不为1的时候,就重新渲染成功了。

executing the reset function attempts to render the error boundaries contents, if successful the fallback error component is replaced by the re-rendered content from page.tsx.

27- Handling Errors in Nested Routes

this lesson we will focus on handling errors in nested routes.

image-20250910171655621

cater to:迎合。 granular:粒度。

把error.tsx放到嵌套文件夹的不同层级,能够以不同的粒度来处理error。error.tsx不仅能够处理本文件夹里面的错误,还可以处理下级文件夹里面的错误。

我们将routing-demo/src/app/products/[productId]/reviews/[reviewId]/error.tsx放到routing-demo/src/app/products/error.tsx,看一下效果:

这里有两点需要注意:

1、在本节课的第一张图中可以看到,Errors bubbles up...,所以虽然错误是发生在[reviewId]/page.tsx里面,而error.tsx在它的祖父层级,却仍然可以接收到具体的错误信息Error loading review

2、error.tsx放在嵌套文件夹的不同层级,它所覆盖的UI内容就相应不同。上面动图中可以看到,错误信息把整个products路由的内容都覆盖了。the entire products route is replaced by the UI from the error.tsx file。

the placement of error.tsx file plays a crucial role in determine the scope of error handling, allowing for more precise control over which parts of the UI are affected when errors occur.

The deeper the placement of error.tsx file , more granular is error handling.

28- Handling Errors in Layouts

image-20250910172231408

image-20250910172308911

从上图可以看出,error.tsx能够处理它所嵌套的所有组件,但是同一层级的layout.tsx和error.tsx,layout组件是在errorBoundary的外层,所以error.tsx是无法捕捉到layouts里面的错误的。

下面用一个案例来说明:

[reviewId]/error.tsx复制到[productId]文件夹里面,在里面的layout.tsx中编写与之前类似的抛出错误的代码。同时为了避免冲突,将routing-demo/app/products/[productId]/reviews/[reviewId]/page.tsx里面抛出错误的代码注释掉。

image-20240907113147822

查看效果:

具体报错信息:There isn't an error boundary to catch the error.Because error boundary will not handle errors thrown in a layout.tsx within the same segment.To solve this problem, we need to place the error.tsx file in the layout's parent segment.

所以为了解决这个问题,需要将error.tsx文件移动到layout.tsx的上一层级,也就是将routing-demo/src/app/products/[productId]/error.tsx移动到routing-demo/src/app/products/error.tsx

查看效果:

29 Handling Global Errors

经过上面的学习,可以看到error boundary无法捕获同级的layout.tsx文件里面的错误,需要放到上级目录。那么app目录里面的layout.tsx,怎么才能捕获它的错误呢?

image-20250910195851851

1、在app文件夹下新建一个error-wrapper的组件,这个组件将包裹app/layout.tsx里面的{children}。这个文件就照抄老师的组件即可。

这个文件的重点就在于有一个触发错误的按钮ErrorSimulator

2、app/layout.tsx里面引入errorWrapper,把{children}包裹住。

image-20250910203257833

3、新建一个app/global-error.tsx的文件,这是处理全局错误的最后一关。这个文件比较简单,其实就是想给用户展示什么信息而已,里面加了一个按钮,可以刷新页面。

运行起来看一下:

可以看到,在开发环境是没有全局错误的页面显示的。这是因为全局错误只能在生产环境显示,使用npm run build进行打包,然后执行npm run start运行生产环境的项目,还是使用localhost:3000来访问。

可以看到是可以的。我的nextjs版本是15.5.2。

但是老师的是不行的,我还是记下来。老师的版本是v15.0.3。原因是全局错误的页面,会整体替换掉app/layout.tsx里面的所有内容,所以必须在global-error.tsx的组件中,使用HTML和body包裹住,这才能显示出来。

image-20250910204621967

image-20250910200621155

最后老师给出了注意事项:

1、global-errors open works in production mode.

2、需要在global-errors里面写html和body,因为它会整体替换掉app/layout.tsx。但这个存疑,v15.5.3没有这个现象。

3、global-errors组件要尽量使用html和css来编写,保持简单,因为你千万不要让global-errors里面也出现错误,那就不好了。

30- Parallel Routes

Starting with this lesson, we will learn some advanced routing concepts in nextjs.

接下来就要讲一下比较复杂的路由了,首先讲“并行路由”。

image-20250910211259506

从下面可以看到,并行路由可以让我们在同一个布局里面同时渲染多个pages。

image-20250910211444478

image-20240907120715879

仔细想一想,我好像从来没有在项目中做这个需求,在案例的dashboard页面里面,我从来没有做“并行渲染”,我所做的就是编写多个组件,然后放到dashboard里面,然后就一起渲染。

这样有什么问题呢?应该没有什么问题,但是既然nextjs提出了这种方式,肯定是有好处的。搜索了一下:

在 Next.js 中,Parallel Routes(并行路由)是 App Router 引入的一项高级路由功能,允许在同一布局中同时或有条件地渲染多个页面或组件。这对于构建动态、复杂的用户界面非常有用。以下是使用 Parallel Routes 的主要好处,结合了来自网络资源的洞见:

  1. 同时渲染多个页面,提升用户体验 Parallel Routes 允许在同一布局中同时渲染多个独立页面(通过 @folder 命名的槽位),例如在仪表板中同时显示团队信息和分析数据。这种方式避免了传统路由中一次只渲染一个页面的限制,用户无需切换页面即可查看多个相关内容,显著提升交互流畅性和信息呈现效率。
  2. 支持复杂动态界面 对于需要高度动态的应用程序部分(如仪表板、社交媒体动态或多栏布局),Parallel Routes 提供了模块化的内容组织方式。通过槽位(slots),开发者可以轻松管理多个独立的内容区域,适用于多区域仪表板或交互式叠加层等场景。
  3. 独立导航与状态管理 每个槽位可以独立导航,互不干扰。例如,在一个社交媒体应用中,@feed 和 @notifications 槽位可以分别加载内容,而不影响其他部分的上下文。这使得用户可以在不同槽位间切换,而无需重新加载整个页面,减少加载时间并提升响应性。
  4. 条件渲染的灵活性 Parallel Routes 支持根据条件(如用户角色、认证状态或其他逻辑)动态渲染槽位内容。例如,可以根据用户权限显示不同的仪表板组件。这种灵活性非常适合需要个性化界面的场景。
  5. 减少代码重复,优化维护 通过在共享布局中管理多个槽位,开发者可以在一个布局组件中统一处理多个页面,减少重复代码。例如,layout.tsx 可以同时接收 @team 和 @analytics 槽位作为 props 并渲染,简化了复杂界面的实现和维护。
  6. 支持模态窗口和上下文保持 当与 Intercepting Routes 结合使用时,Parallel Routes 可以实现类似 Pinterest 的模态窗口效果,即点击内容时显示模态窗口,同时保持当前页面上下文,并在刷新时显示完整页面。这种无缝导航模式显著提升了用户体验。
  7. 更快的页面加载 Parallel Routes 允许同时获取多个路由的数据,优化了服务器端渲染的性能。通过并行处理多个页面或组件的加载,减少了用户等待时间,尤其适用于数据密集型应用。

实际应用场景

image-20240907120808740

场景7:

在访问localhost:3000/dashboard时,我要在dashboard里面同时展示user analytics、notifications、revenue metrics,传统做法是在app/dashboard文件夹里面,定义这些组件,然后统一引入到layout.tsx中来展示。

下面用代码来实现。创建app/complex-dashboard文件夹,创建layout.tsx文件,编写组件。创建page.tsx,编写组件。

再编写子组件,就可以实现功能了。

但是这里可以使用parallel routes来实现同样的功能,下面是parallel routes的定义。

image-20250910213107161

Example

以案例来说明,parallel routes可以这么做:

image-20240907141134865

在app/complex-dashboard文件夹里面创建@revenue文件夹,创建page.tsx文件,编写组件。

同样创建@notifications@users

Now we have created three slots within our complex-dashboard folder, each slot is automatically passed to the layout.tsx file component as a prop and no imports are needed.which we can then use to structure the dashboard component.

创建了parallel routes之后,它们会自动作为本文件夹的layout.tsx的props来供使用。所以不需要引入就可以使用,做法是在layout.tsx里面的组件参数,解构出来,注意,这里解构的variable name是文件夹的name,不是page.tsx中定义的component name。

为了让展示效果更好,这里定义一个Card组件。

@users@revenue@notifications的page.tsx里面的组件,div替换为Card组件:

image-20240907143618396

查看效果:

注意:

slots不是路由片段,虽然是文件夹,但是Nextjs并不会将它们加入到路由中去,所以当你访问/complex-dashboard/users或者/complex-dashboard/@users,都会返回not found。

slots are not route segments and do not affect the URL structrue.If you navigate to localhost:3000/complex-dashboard/@users,you will see page not found.

image-20240907144116997

为什么老师会提示这一点?想一想。

因为按照nextjs的route mechanism,文件夹一般对应一个route,所以访问这个route,会展示这个文件夹的内容。但是slots不是route segments。

实际上children是一个隐藏的slot,只不过这个slot并没有单独的文件夹。这个概念在后面的学习中会用到。

what you should also know is that the children prop is equivalent to complex-dashboard/@children/page.tsx, so technitally we have four slots in layout.tsx file in this case.

image-20240907144551822

Benefits

image-20250910213909861

image-20250910213959406

老师说了,第一点benefit并不是parallel routes的super power,我同样可以使用普通组件做到。真正的benefits是第2、3点。下面详细说明。

image-20240907144801604

image-20250910214140593

image-20240907144826035

上面的图中,展示了parallel routes的好处,如果user analytics组件渲染较慢或者获取数据较慢,那么可以在@users文件夹里面创建loading.tsx文件,专门用来展示loading状态,别的组件很快的话,那就不用管。

If there is an error in fetching revenue metrics data, you can show an error message in that specific section without affecting the rest of the dashboard.

image-20250910214308513

image-20250910214339691

比如说可以在@notifications里面创建子路由,用户可以切换查看默认通知和已存裆的通知。这一点其实使用路由就可以办到。我知道你肯定在想v-if/v-show,但nextjs里面有独特的写法,要尊重它的最佳实践。

image-20250910214556832

image-20250910214626484

This approach allows for a more dynamic and interactive user experience as users can navigate through different parts of the application without unnecessary page reloads or layout shifts.

小结:

parallel routes allow simultaneous rendering of different pages within the same layout.Use slots to define parallel routes, slots organize content in a modular fashion, making code more manageable.

31- Unmatched Routes

这一节课到底讲了什么?注意 unmatched routes不是一种方法,而是一种现象,一种concept。我搜索了一下grok:

Unmatched routes 指的是当用户访问的 URL 无法直接映射到某个预定义的路由或 slot(插槽,Next.js 并行路由中的术语)时的情况。这种情况可能发生在以下场景:

  1. 并行路由中的未匹配插槽:在并行路由中,Next.js 允许同时渲染多个页面或组件(通过 @folder 命名的插槽)。如果某个插槽对应的 URL 路径没有定义相应的 page.js 文件,Next.js 会认为这是一个未匹配的路由。
  2. 页面导航或刷新:当用户通过 UI 导航或直接刷新页面时,URL 可能指向一个没有明确定义的路由。
  3. 动态路由未匹配:在动态路由中,如果 URL 参数无法匹配到预定义的路由结构,也可能触发未匹配路由的情况。

课上老师提到了当出现unmatched routes时,根据navigating的类型,unmatched slots有两种表现。

image-20250911100303544

第一种是通过UI来跳转,那么此时的unmatched slots保持原有状态。

第二种就是page reload或者直接输入url访问,那么此时的unmatched slots必须有一个default.js文件,否则会出现404。

那么本节课就是学习怎么避免第二种情况的发生。

 

通过上面可以知道,unmatched routes 是一种情况。这种情况是需要被考虑到的,所以有以下四种方法来处理:

1、使用 default.js 提供并行路由插槽的回退内容。

2、创建 not-found.js 定义自定义 404 页面。

3、使用 catch-all 路由([...slug])捕获未定义路径。

4、在布局中动态处理未匹配插槽。

 

本节课就是讲了使用 default.js 来处理unmatched routes。

Introduction

image-20240907151011547

在上节课中,我们学习了parallel routes,并且知道了它的好处之一:sub-navigation。但是怎么实现sub-navigation呢?下面就来实现。

Implement the Scenario

1、首先在@notifications/page.tsx里面编写跳转路由,让我们能够跳转到Archived。

2、创建Archived路由,编写组件。

注意:

虽然archived文件夹是定义在 @notifications 文件夹里面的,but this is a regular route folder, not a slot.

查看效果:

sub-navigation within the notifications is working as expected.

Unmatched Routes

这里的unmatched routes应该不属于一个专门的名词,因为我在Nextjs官网上并没有找到。用unmatched slots应该更准确一点。官网信息如下:

https://nextjs.org/docs/app/building-your-application/routing/parallel-routes

image-20240907162504722

 

image-20240907153135300

在上节课中,我们知道,在案例中有四个slot,分别是@children、@users、@revenue和@notifications。

By default, the content rendered within a slot matches the current url, in the case above, all the four slots render their defined content when visit localhost:3000/complex-dashboard.However, when navigating to localhost:3000/complex-dashboard/archived, only the notifications slot has a matching route, other slots become unmatched.When dealing an unmatched slot, the content rendered by nextjs depends on the routing approach.

So there are two cases, you can see the above picture, one is 'Navigation from the UI', the other is 'Page reload'.

那么上面的案例就是符合第一种情况的,@children、@users、@revenue will remain unaffected。

Default Views

这里讲unmatched routes的第二种情况,就是page reload,无论是直接访问http://localhost:3000/complex-dashboard/archived,还是刷新这个页面,都会出现:

image-20240907154716965

首先我要明确一点,unmatched routes是在parallel routes概念之后讲解的,说明unmatched routes概念和parallel routes概念是分不开的,所以使用场景一定要记清楚,因为概念实在是太多了。方便是方便,但是要下苦功夫才能用好。

image-20240907155229627

为什么需要default.tsx?是谁需要default.tsx?

是unmatched routes需要default.tsx。为什么需要呢?因为在page reload的时候,nextjs会在每个unmatched slot里面寻找default.tsx,如果没有找到,会报错。

image-20240907160630530

解决方法:

在complex-dashboard文件夹里面创建default.tsx,this will serve as the fallback view for the children's slot。default.tsx里面的内容一般来说都是直接copy page.tsx的内容,只需要把组件的名称改一下就行了。

@users@revenue里面进行同样的操作,查看效果:

可以看到,当page reload之后,children、users、revenue显示的就是default.tsx里面的内容。

Summary

这节课对unmatched slots进行了讲解,the content rendered within a slot depend on the type of navigation。

感想:

这里的default.tsx感觉代码很冗余,如果slots里面的内容很丰富呢?那不是代码量倍增了。

不用管,代码量倍增不是更容易出KPI吗?不是更好吗?说不定组件化的代码,就不允许一个文件里面的代码很长,都是直接引用的。反正知道什么情况该用slots就行了,我所想象的在首页使用slot看来值得商榷了。

32- Conditional Routes

conditional routes应该属于应用场景概念,不属于专有名词。还是属于parallel routes的应用,用条件判断来实现的。

根据这节课的案例,按照我以前的习惯,我肯定是将login和dashboard做成不同的route,然后在用户进入/dashboard时校验权限,如果没有权限就跳转到/login

但是conditional routes提供了完全不同的解决方案,页面的一些部分是可以给用户看到的(比如说一些通用的页面内容,不涉及到数据方面的),然后只有其中重要的部分只有登录之后才能查看。那么就在这一部分显示login页面,是这么一个场景。

image-20250911102723842

https://nextjs.org/docs/app/building-your-application/routing/parallel-routes

image-20240907163029374

下面举一个案例来说明,based on the user's authentication state, you can choose to render the dashboard for authenticated users or a login page for those who are not authenticated.This is powerful as it enables fully separated code on the same URL.

在app/complex-dashboard文件夹中创建@login文件夹,创建page.tsx,编写组件。

routing-demo/src/app/complex-dashboard/layout.tsx文件中,使用login的slot,知识点如果忘记了,就看一下parallel routes这一小节。

切换isLogin的值,来看一下效果:

image-20250911103323198

 

提示:

如果代码写好了之后,login没有渲染出来,需要重新启动npm run dev。

课后习题:

代码都写好了之后,访问http://localhost:3000/complex-dashboard/archived会报错。怎么解决?

image-20240907173408037

解决办法:

@login文件夹中新增default.tsx文件,内容可以和@login/page.tsx保持一致。

访问没有问题:

image-20240907173621382