我为我的问题准备了a simple test case at Github个:

animated screenshot

在RouterLaye.jsx中,媒体查询会使Outlet在狭窄的屏幕上消失,正如您在动画屏幕截图中所看到的那样,我拖动浏览器端将其缩小:

RootLayout.jsx

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>
  );
}

请我的问题:

small个手机屏幕上,仅应显示主列表.当点击那里的链接时,应该显示Page1或其他页面,并有可能返回到主列表.这还不起作用.

large个平板电脑和电脑屏幕上,主列表和页面1或其他内容都显示在彼此附近.这在我的代码中已经起作用了.

我应该在下面MasterList.jsx中的Link中添加一些属性吗?

MasterList.jsx

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;

App.jsx

import {
  Route,
  RouterProvider,
  createBrowserRouter,
  createRoutesFromElements,
} from "react-router-dom";
import Page1 from "./pages/Page1";
import Page2 from "./pages/Page2";
import Page3 from "./pages/Page3";
import Page4 from "./pages/Page4";
import RootLayout from "./layouts/RootLayout";

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route path="/" element={<RootLayout />}>
      <Route path="page1" element={<Page1 />} />
      <Route path="page2" element={<Page2 />} />
      <Route path="page3" element={<Page3 />} />
      <Route path="*" element={<Page4 />} />
    </Route>
  )
);

const App = () => {
  return <RouterProvider router={router} />;
};

export default App;

推荐答案

在未渲染Outlet的较小视图尺寸上,嵌套的Route组件不再有地方渲染其element内容.如果我正确理解您的帖子,您希望在较大的非"移动"视图大小上使用RootLayoutOutlet,并在移动视图大小上将RootLayout渲染为sibling 路由而不是父路由,因此所有其他路由都是可访问的.

重构示例:

  • 创建两种根布局,移动和非移动.

    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} />;
    }
    

替代

另一种 Select 可能是利用useMatch挂钩来测试根"/"是否是当前匹配的路由和渲染MasterList.逻辑有点复杂,也有点少107.这里的要点是在更大的视图大小上渲染普通MasterListOutlet,并且在移动视图上仅在主页上有条件地渲染MasterList,否则为嵌套路由渲染Outlet.

示例:

import { Outlet, useMatch } from 'react-router-dom';
...

function RootLayout() {
  const isSmallScreen = useMediaQuery("(max-width: 768px)");
  const isHome = useMatch("/");

  return (
    <div
      style={{
        display: "flex",
        justifyContent: "space-around",
        alignItems: "flex-start"
      }}
    >
      {isSmallScreen ? (
        isHome ? (
          <MasterList />
        ) : (
          <div>
            <h3>Detail</h3>
            <Outlet />
          </div>
        )
      ) : (
        <>
          <MasterList />
          <div>
            <h3>Detail</h3>
            <Outlet />
          </div>
        </>
      )}
    </div>
  );
}
const router = createBrowserRouter(
  createRoutesFromElements(
    <Route path="/" element={<RootLayout />}>
      <Route path="page1" element={<Page1 />} />
      <Route path="page2" element={<Page2 />} />
      <Route path="page3" element={<Page3 />} />
      <Route path="*" element={<Page4 />} />
    </Route>
  )
);

export default function App() {
  return <RouterProvider router={router} />;
}

Reactjs相关问答推荐

从另一个组件更改组件中const的状态

Next.js:提交表单时状态尚未就绪

面对动画警告:未指定`useNativeDriver`.这是必需的选项,并且必须在REACT本机中显式设置为`true`或`False`

Reaction中的数据加载不一致

梅X折线图无响应

如何在REACTIVE js中动态添加或删除输入字段?

REACTION-Easy-SORT返回.map错误

如何在中间件中获取 nextAuth 会话

如何使用服务器中的数据自动填充表单字段?

获取 不能显示为 的后代.错误,但不太确定如何构建我的代码以避免此警告

如何更新redux状态存在的输入框

如何将 DocuSign 控制台界面嵌入到 React 应用中

如何处理页面加载时发生的 reactjs 错误?

当我在 useEffect 中使用 useDispatch 时,我的组件继续渲染

调用 Statsig.updateUser 时 UI 不呈现

加密 Django Rest Framework API 响应 + 解密响应应用程序中的响应

react-admin useGetIdentity 只返回全名,id 未定义 头像未定义

如果两个组件在 React 中导入相同的 CSS 文件会发生什么?

你如何使用 refs 访问 React 中映射子项的值?

Context Api React 的问题