简体   繁体   English

是否可以在React-Router V6中的组件中使用多个插座

[英]Is it possible to use multiple outlets in a component in React-Router V6

I am using React Router v6 in an application.我在应用程序中使用 React Router v6。 I have a layout page, which uses an outlet to then show the main content.我有一个布局页面,它使用一个插座来显示主要内容。 I would also like to include a title section that changes based on which path has been matched, but I am unsure how to do this.我还想包括一个标题部分,该部分根据匹配的路径而变化,但我不确定如何执行此操作。

function MainContent() {
  return (
    <div>
      <div>{TITLE SHOULD GO HERE}</div>
      <div><Outlet /></div>
    </div>
  );
}

function MainApp() {
  return (
    <Router>
      <Routes>
        <Route path="/projects" element={<MainContent />} >
          <Route index element={<ProjectList />} title="Projects" />
          <Route path="create" element={<CreateProject />} title="Create Project" />
        </Route>
      <Routes/>
    </Router>
  );
}

Is something like this possible?这样的事情可能吗? Ideally, I would like to have a few other props besides title that I can control in this way, so a good organization system for changes like this would be great.理想情况下,除了标题之外,我还希望有一些我可以通过这种方式控制的其他道具,所以一个好的组织系统来进行这样的更改会很棒。

The most straightforward way would be to move the title prop to the MainContent layout wrapper and wrap each route individually, but you'll lose the nested routing.最直接的方法是将title属性移动到MainContent布局包装器并单独包装每个路由,但是您将丢失嵌套路由。

An alternative could be to create a React context to hold a title state and use a wrapper component to set the title.另一种方法是创建一个 React 上下文来保存title state 并使用包装器组件来设置标题。

const TitleContext = createContext({
  title: "",
  setTitle: () => {}
});

const useTitle = () => useContext(TitleContext);

const TitleProvider = ({ children }) => {
  const [title, setTitle] = useState("");
  return (
    <TitleContext.Provider value={{ title, setTitle }}>
      {children}
    </TitleContext.Provider>
  );
};

Update MainContent to access the useTitle hook to get the current title value and render it.更新MainContent以访问useTitle挂钩以获取当前title值并呈现它。

function MainContent() {
  const { title } = useTitle();
  return (
    <div>
      <h1>{title}</h1>
      <div>
        <Outlet />
      </div>
    </div>
  );
}

The TitleWrapper component. TitleWrapper组件。

const TitleWrapper = ({ children, title }) => {
  const { setTitle } = useTitle();

  useEffect(() => {
    setTitle(title);
  }, [setTitle, title]);

  return children;
};

And update the routed components to be wrapped in a TitleWrapper component, passing the title prop here.并更新路由组件以包装在TitleWrapper组件中,在此处传递title属性。

<Route path="/projects" element={<MainContent />}>
  <Route
    index
    element={
      <TitleWrapper title="Projects">
        <ProjectList />
      </TitleWrapper>
    }
  />
  <Route
    path="create"
    element={
      <TitleWrapper title="Create Project">
        <CreateProject />
      </TitleWrapper>
    }
  />
</Route>

In this way, MainContent can be thought of as UI common to a set of routes whereas TitleWrapper ( you can choose a more fitting name ) can be thought of as UI specific to a route.这样, MainContent可以被认为是一组路由的通用 UI,而TitleWrapper您可以选择更合适的名称)可以被认为是特定于路由的 UI。

编辑 is-it-possible-to-use-multiple-outlets-in-a-component-in-react-router-v6

I was facing the same issue for a left-right layout: changing sidebar content and main content, without repeating styling, banner, etc.对于左右布局,我遇到了同样的问题:更改侧边栏内容和主要内容,而不重复样式、横幅等。

The simplest approach I found was to remove nested routing, and create a layout component in which I feed the changing content through properties.我发现的最简单的方法是删除嵌套路由,并创建一个布局组件,我在其中通过属性提供不断变化的内容。

Layout component (stripped for this post):布局组件(为这篇文章删除):

export function Layout(props) {

  return (
    <>
      <div class="left-sidebar">
        <img id="logo" src={Logo} alt="My logo" />
        {props.left}
      </div>

      <div className='right'>
        <header className="App-header">
          <h1>This is big text!</h1>
        </header>

        <nav>
          <NavLink to="/a">A</NavLink>
          &nbsp;|&nbsp;
          <NavLink to="/b">B</NavLink>
        </nav>

        <main>
          {props.right}
        </main>
      </div>
    </>
  );
}

Usage in react router:在反应路由器中的用法:

<Route path="myPath" element={
  <Layout left={<p>I'm left</p>}
          right={<p>I'm right</p>} />
} />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM