在路线上渲染模态,并在后台渲染父路线

sjb*_*sse 7 reactjs react-router

我正在使用 ReachUIDialog渲染对话框(模态)。正如您在下面的代码中看到的那样,它Dialog可以在路线上进行路由。products/create/

当我路由到时,是否可以同时渲染ProductsTable(位于父路由products/) 和,以便我可以在模式的背景中看到该组件?我希望通过 来实现这一目标。Dialogproducts/createProductsTablereact-router

这就是代码现在的样子:

...
import { Switch, Route, useRouteMatch, match, useHistory, } from "react-router-dom";
import { Dialog } from "@reach/dialog";

export function ProductsPage() {
  const { url }: match = useRouteMatch();
  const { push } = useHistory();

  const gotToCreateProduct = () => push(`${url}/create`);

  return (
      <Switch>
        <Route exact path={url}>
          <Page title="Products" onCreateButtonClick={gotToCreateProduct}>
            <ProductsTable></ProductsTable>
          </Page>
        </Route>
        <Route path={`${url}/create`}>
            <Dialog isOpen={true} onDismiss={() => push(url)}>
                <ProductForm></ProductForm>
            </Dialog>
        </Route>
      </Switch>
  );
}
Run Code Online (Sandbox Code Playgroud)

Aks*_* kn 8

反应路由器 v6

您必须在嵌套组件中使用 Outlet;
<BrowserRouter>
   <Routes>
      <Route path="/home" element={<Home />}>
         <Route path="modal" element={<Modal />} />
      </Route>
   </Routes>
</BrowserRouter>
Run Code Online (Sandbox Code Playgroud)

并在 Home 组件内部添加一个 Outlet;

import { Outlet } from "react-router-dom";
export default function Home(){
   return(
      <>
         Home Code is here
         <Outlet />
      </>
   )
}
Run Code Online (Sandbox Code Playgroud)

所以现在,每当/home/modal打开该路线时,它都会默认打开模式。确保isOpen默认情况下保持 prop true,因为渲染现在将由反应路由器控制。

  • Outlet 组件不应该放在 Home 组件中而不是 Modal 中吗? (2认同)

sjb*_*sse 7

我自己想出来了,基本上你只需要把两个Switch组件放在一起,然后删除exactparent的属性Route。这样,两个Switches 都会匹配并渲染它们的路线。有道理而且有效。

    return (
        <>
            <Switch>
                <Route path={url}>
                    <Page title="Products" onCreateButtonClick={gotToCreateProduct}>
                        <ProductsTable></ProductsTable>
                    </Page>
                </Route>
            </Switch>
            <Switch>
                <Route path={`${url}/create`}>
                    <Dialog show={true} title={'Create product'}
                            onClose={() => push(url)}><CreateProduct></CreateProduct></Dialog>
                </Route>
                <Route path={`${url}/:productId/edit`}>
                    <Dialog show={true} title={'Edit product'} onClose={() => push(url)}><EditProduct></EditProduct></Dialog>
                </Route>
            </Switch>
        </>
    );
Run Code Online (Sandbox Code Playgroud)


小智 5

@Akshay K Nair的答案几乎是完美的,只是 的位置错误<Outlet />。正确的用法<Outlet />是让父路由器组件渲染它(在此处阅读更多内容)。查看这个 React Router Dom v6 示例:

路由器

export const router = createBrowserRouter([
  {
    path: "/",
    element: <Home />,
    children: [
      {
        path: "/:id",
        element: (
          <ModalRoute>
            <Detail />
          </ModalRoute>
        ),
      },
    ],
  },
])

Run Code Online (Sandbox Code Playgroud)

父组件

const Home = () => {
  return (
    <>
      Insert parent code
      <Outlet />
    </>
  )
}
Run Code Online (Sandbox Code Playgroud)

模态路线

const ModalRoute = ({ children }) => {
  const [opened, setOpened] = useState(false)
  const location = useLocation()
  const navigate = useNavigate()

  useEffect(() => {
    const id = location.pathname.split("/")[1]
    if (id) {
      setOpened(true)
    }
  }, [location.pathname])

  const handleClose = () => {
    navigate("/")
    setOpened(false)
  }

  return (
    <Modal opened={opened} onClose={handleClose}>
        {children}
    </Modal>
  )
}
Run Code Online (Sandbox Code Playgroud)