Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] 约定式路由无法生成嵌套路由!! #8850

Closed
Pszz opened this issue Aug 3, 2022 · 18 comments
Closed

[Bug] 约定式路由无法生成嵌套路由!! #8850

Pszz opened this issue Aug 3, 2022 · 18 comments

Comments

@Pszz
Copy link

Pszz commented Aug 3, 2022

  • 这是UMi3.x 的文档
    image

  • 最小化复现代码

  • src/pages/ui/_layout.tsx

import React from 'react';
import { Outlet } from 'umi';

export default function () => {
  return (
    <>
        <div>父层内容</div>
        <div>
          /* 无效 */
          <Outlet />
        </div>
    </>
  );
}
@github-actions
Copy link

github-actions bot commented Aug 3, 2022

由于缺乏足够的信息,我们暂时关闭了该 Issue。请修改(不要回复) Issue 提供最小重现以重新开启。谢谢。

@github-actions github-actions bot closed this as completed Aug 3, 2022
@sherry007
Copy link

+1 !

@sherry007
Copy link

而且这个 Outlet 组件感觉也不起作用

@Pszz
Copy link
Author

Pszz commented Aug 5, 2022

而且这个 Outlet 组件感觉也不起作用

去掉约定式路由,就可以支持。

  • .umirc.ts
    { path: '/ui', component: 'ui', routes: [ { path: '/ui/button', component: 'ui/button', }, ] }

  • /pags/ui/index.tsx
    import { useOutlet } from 'umi'; export default () => { const outlet = useOutlet(); return <> <div>父层内容</div> <div>嵌套内容{ outlet }</div> </> }

@sherry007
Copy link

而且这个 Outlet 组件感觉也不起作用

去掉约定式路由,就可以支持。

  • .umirc.ts
    { path: '/ui', component: 'ui', routes: [ { path: '/ui/button', component: 'ui/button', }, ] }
  • /pags/ui/index.tsx
    import { useOutlet } from 'umi'; export default () => { const outlet = useOutlet(); return <> <div>父层内容</div> <div>嵌套内容{ outlet }</div> </> }

但是我们项目太大了,一直都用的是约定式路由,现在改成配置式的,改动量太大了;

@sherry007
Copy link

而且这个 Outlet 组件感觉也不起作用

去掉约定式路由,就可以支持。

  • .umirc.ts
    { path: '/ui', component: 'ui', routes: [ { path: '/ui/button', component: 'ui/button', }, ] }
  • /pags/ui/index.tsx
    import { useOutlet } from 'umi'; export default () => { const outlet = useOutlet(); return <> <div>父层内容</div> <div>嵌套内容{ outlet }</div> </> }

可以再打开这个 issue 吗?我看最小复现代码也有了的 @sorrycc

@xiaohuoni xiaohuoni reopened this Aug 5, 2022
@fz6m
Copy link
Contributor

fz6m commented Aug 5, 2022

现在没有 _layout 了,你需要的可能是:

./src/pages
├── nested
   └── a.tsx
└── nested.tsx
// nested.tsx

import { Outlet } from 'umi'

export default function N() {
  return (
    <div>
      wrapper :
      <Outlet />
    </div>
  )
}
// nested/a.tsx

export default function N() {
  return <div>aaa</div>
}

@sherry007
Copy link

现在没有 _layout 了,你需要的可能是:

./src/pages
├── nested
   └── a.tsx
└── nested.tsx
// nested.tsx

import { Outlet } from 'umi'

export default function N() {
  return (
    <div>
      wrapper :
      <Outlet />
    </div>
  )
}
// nested/a.tsx

export default function N() {
  return <div>aaa</div>
}

这个我试了, 外层的 layout 的命名是有什么要求吗(都得是 nested ?)?我这么写之后, Outlet 拿到的属性是空的

@fz6m
Copy link
Contributor

fz6m commented Aug 9, 2022

文件夹和当级路由的名字一样即可。

./src/pages
├── ${name}
   └── a.tsx
└── ${name}.tsx

@sherry007
Copy link

好的,我试试哦,非常感谢!

@sherry007
Copy link

以下是报错
image

我的目录结构如下:
image

另外,我还想问一下,如上所示的目录,如果我想要 projects 目录下的三个文件 metadata| resources | roles 都能有一个一样的 layout 文件,应该要怎么做呢

@fz6m
Copy link
Contributor

fz6m commented Aug 10, 2022

给一个最小复现。

@ghost
Copy link

ghost commented Aug 12, 2022

@fz6m
image
um4 里面 这个规则失效了 下划线开头的目录和文件也被注册为路由了

@sherry007
Copy link

以下是报错 image

我的目录结构如下: image

另外,我还想问一下,如上所示的目录,如果我想要 projects 目录下的三个文件 metadata| resources | roles 都能有一个一样的 layout 文件,应该要怎么做呢

repo 我后面有时间了整一个;
请问第二个问题:「如果我想要 projects 目录下的三个文件 metadata| resources | roles 都能有一个一样的 layout 文件」 有什么解决方案吗

@laeni
Copy link

laeni commented Aug 19, 2022

而且这个 Outlet 组件感觉也不起作用

去掉约定式路由,就可以支持。

  • .umirc.ts
    { path: '/ui', component: 'ui', routes: [ { path: '/ui/button', component: 'ui/button', }, ] }
  • /pags/ui/index.tsx
    import { useOutlet } from 'umi'; export default () => { const outlet = useOutlet(); return <> <div>父层内容</div> <div>嵌套内容{ outlet }</div> </> }

但是我们项目太大了,一直都用的是约定式路由,现在改成配置式的,改动量太大了;

我们的情况和你们差不多,不过我们的情况是子路由下一般会有一个index.tsx页面,用<Outlet />和这下面种方式的话,会导致${name}.tsx的优先级高于${name}/index.tsx而导致index.tsx不生效。

./src/pages
├── ${name}
│   ├── index.tsx
│   └── a.tsx
└── ${name}.tsx

我们的解决方案如下,你可以参考下:在_layout.tsx所在的目录下创建components目录,并将_layout.tsx移动到该目录下,这样自动生成的路由就会忽略掉_layout.tsx;然后将每一个子页面都包裹在_layout.tsx组件下。

./src/pages
└── ${name}
    ├── components
    │   └── _layout.tsx
    ├── index.tsx
    └── a.tsx

index.tsx and a.tsx

import Layout from './components/_layout';

export default function TestPage() {
    return (
        <Layout>
            // 原本的子组件内容
        </Layout>
    )
}

@sherry007
Copy link

而且这个 Outlet 组件感觉也不起作用

去掉约定式路由,就可以支持。

  • .umirc.ts
    { path: '/ui', component: 'ui', routes: [ { path: '/ui/button', component: 'ui/button', }, ] }
  • /pags/ui/index.tsx
    import { useOutlet } from 'umi'; export default () => { const outlet = useOutlet(); return <> <div>父层内容</div> <div>嵌套内容{ outlet }</div> </> }

但是我们项目太大了,一直都用的是约定式路由,现在改成配置式的,改动量太大了;

我们的情况和你们差不多,不过我们的情况是子路由下一般会有一个index.tsx页面,用<Outlet />和这下面种方式的话,会导致${name}.tsx的优先级高于${name}/index.tsx而导致index.tsx不生效。

./src/pages
├── ${name}
│   ├── index.tsx
│   └── a.tsx
└── ${name}.tsx

我们的解决方案如下,你可以参考下:在_layout.tsx所在的目录下创建components目录,并将_layout.tsx移动到该目录下,这样自动生成的路由就会忽略掉_layout.tsx;然后将每一个子页面都包裹在_layout.tsx组件下。

./src/pages
└── ${name}
    ├── components
    │   └── _layout.tsx
    ├── index.tsx
    └── a.tsx

index.tsx and a.tsx

import Layout from './components/_layout';

export default function TestPage() {
    return (
        <Layout>
            // 原本的子组件内容
        </Layout>
    )
}

非常感谢你的解答和方案!我后面就是这么做的,但是这样有一个点不太好,就是layout里的内容一般是公用的对吧,就比如我 detail 的页面里有四个 tab 页,每次进到一个 tab(对应不同路由),layout 里的内容就会刷新一次,而实际上这些内容第一次进来的时候就应该已经渲染好了的,不知道我有没有讲明白

@Zhhanou
Copy link
Contributor

Zhhanou commented Sep 4, 2023

同样的问题,约定式路由下,umi4没有办法使用umi3 _layout嵌套路由的功能。

@fz6m
Copy link
Contributor

fz6m commented Sep 5, 2023

目前 umi 3 升 umi 4 需要自己处理下 layout 的问题,主要关心两个变化:

第一是 umi 4 是用的 react router v6 ,嵌套路由的出口是 <Outlet /> ,当使用嵌套路由的时候,需要在展示子嵌套内容的位置加上 <Outlet /> (从 umi 导入),这样才能有子级内容。

第二是 umi 4 里没有 _layout ,可以自己改代码把 <Layout></Layout> 套上或者使用 wrappers 配置,另外也可以在运行时 patch 路由加上 layout 。

@fz6m fz6m closed this as completed Sep 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants