我在 Github 上准备了 一个简单的测试用例来回答我的问题:
在 RouterLayout.jsx 中,媒体查询使
Outlet
在窄屏幕上消失,如动画屏幕截图中所示,我拖动浏览器一侧以使其变小:
import { Outlet } from "react-router";
import { useMediaQuery } from "@react-hook/media-query";
import MasterList from "../components/MasterList";
export default function RootLayout() {
const isSmallScreen = useMediaQuery("(max-width: 768px)");
return (
<div
style={{
display: "flex",
justifyContent: "space-around",
alignItems: "flex-start",
}}
>
<MasterList />
{!isSmallScreen && (
<div>
<h3>Detail</h3>
<Outlet />
</div>
)}
</div>
);
}
我的问题:
在小手机屏幕上仅应显示主列表。当点击那里的链接时,应该显示 Page1 或其他页面,并且可以返回到主列表。这还行不通。
在大平板电脑和计算机屏幕上,主列表和第 1 页或其他内容彼此靠近显示。这已经在我的代码中起作用了。
我应该向下面的
MasterList.jsx中的
Link
添加一些属性吗?
import { Link } from "react-router-dom";
const MasterList = () => {
const pages = [
{ id: 1, title: "Page 1" },
{ id: 2, title: "Page 2" },
{ id: 3, title: "Page 3" },
{ id: 4, title: "Page 4" },
];
return (
<div>
<h2>Master List</h2>
<nav>
<ul>
{pages.map((page) => (
<li key={page.id}>
<Link to={"/page" + page.id}>{page.title}</Link>
</li>
))}
</ul>
</nav>
</div>
);
};
export default MasterList;
在未渲染
Outlet
的较小视图尺寸上,嵌套的 Route
组件不再有地方渲染其 element
内容。如果我正确理解你的帖子,你想在较大的非“移动”视图尺寸上使用 RootLayout
和 Outlet
,并且在移动视图尺寸上将 RootLayout
渲染为同级路线而不是父路线,所以所有其他路线都可以到达。
重构示例:
创建两个根布局,移动和非移动。
function RootLayout() {
return (
<div
style={{
display: "flex",
justifyContent: "space-around",
alignItems: "flex-start"
}}
>
<MasterList />
<div>
<h3>Detail</h3>
<Outlet />
</div>
</div>
);
}
function MobileLayout() {
return (
<div
style={{
display: "flex",
justifyContent: "space-around",
alignItems: "flex-start"
}}
>
<div>
<h3>Detail</h3>
<Outlet />
</div>
</div>
);
}
更新
App
以使用媒体查询挂钩并有条件地渲染一个根布局或另一种,并有条件地将 MasterList
渲染为较小屏幕上的索引路由。
export default function App() {
const isSmallScreen = useMediaQuery("(max-width: 768px)");
const router = React.useMemo(
() =>
createBrowserRouter(
createRoutesFromElements(
<Route
path="/"
element={isSmallScreen ? <MobileLayout /> : <RootLayout />}
>
{isSmallScreen && <Route index element={<MasterList />} />}
<Route path="page1" element={<Page1 />} />
<Route path="page2" element={<Page2 />} />
<Route path="page3" element={<Page3 />} />
<Route path="*" element={<Page4 />} />
</Route>
)
),
[isSmallScreen]
);
return <RouterProvider router={router} />;
}
我不知道实现此目的的最佳方法是什么,但它需要结合 Outlet 在父组件中渲染子路由的事实。
我会探索 useMatches 看看是否可以使用它来确定父组件是在
/parent
还是 /parent/child
上渲染。有了这些信息,您就可以有条件地渲染导航元素: