Remix约定式路由文件夹仅返回根页面的问题及路由文件区别咨询
你好!刚接触Remix遇到路由问题很正常,我来帮你拆解这两个核心问题:
一、为什么访问/test/dynamic-route总是重定向到/test根页面?
出现这个问题大概率是以下两个原因之一:
父路由缺少
<Outlet />组件
如果你在/test/route.tsx里定义了布局路由,但没有在组件中添加<Outlet />,Remix就无法渲染子路由(比如/test/dynamic-route)的内容。这种情况下,当你访问子路由时,Remix会因为无法正确渲染内容, fallback 到父路由的根页面,看起来就像被重定向了。解决方法很简单,在
/test/route.tsx的JSX中加入<Outlet />即可:import { Outlet } from "@remix-run/react"; export default function TestLayout() { return ( <div> {/* 这里可以放/test下所有页面的公共内容,比如导航栏、侧边栏 */} <Outlet /> {/* 子路由的内容会渲染在这个位置 */} </div> ); }路由结构不符合约定式规则
如果你想创建动态路由/test/:param(也就是你说的接收参数的/test/dynamic-route),对应的文件夹应该命名为/test/$param(前缀$是Remix识别动态参数的约定),再在这个文件夹下创建route.tsx。如果直接用dynamic-route作为文件夹名,它对应的是固定路径/test/dynamic-route,并非动态参数路由。另外,如果子路由的
route.tsx文件没有正确创建,Remix找不到对应的路由处理逻辑,也会 fallback 到父路由的根页面。
二、/test/route.tsx 和 /test._index/route.tsx 的区别?需要同时存在吗?
这两个文件的职责完全不同,属于Remix约定式路由里的两类核心路由:
/test/route.tsx:布局路由(Layout Route)
它是/test路径下所有子路由的“公共容器”,负责渲染所有/test开头页面共享的UI元素(比如页头、侧边栏)。它必须包含<Outlet />才能让子路由的内容显示出来。如果不需要公共布局,你可以完全删除这个文件。/test._index/route.tsx:索引路由(Index Route)
它专门对应/test这个根路径的内容,当用户直接访问/test时,Remix会渲染这个文件里的组件(如果有布局路由的话,会被布局包裹)。如果没有这个文件,访问/test时,布局路由的<Outlet />位置会是空的,页面只会显示布局的公共部分。
是否需要同时存在?
完全取决于你的需求:
- 如果你需要/test路径下的所有页面有公共布局,就保留
/test/route.tsx并添加<Outlet />; - 如果你需要直接访问
/test时显示具体内容,就需要/test._index/route.tsx; - 如果你不需要公共布局,只需要/test页面,那可以直接删除
/test/route.tsx,把内容放在/test._index/route.tsx里,甚至直接把文件命名为/test.tsx(直接对应/test路径)。
总结一下,先检查父路由有没有<Outlet />,再确认动态路由的文件夹命名是否符合$param的约定,就能解决重定向的问题啦。
备注:内容来源于stack exchange,提问作者thathurtabit

