Closed gwsbhqt closed 4 years ago
可以举个你期望的用例嘛?我看看怎么兼容
@CJY0208 没想到响应速度这么快,我这就去组织详细的问题
引入该插件之前,以下代码的行为符合预期。
// src/app.tsx
import Root from './components/Root'
export function rootContainer(container: JSX.Element): JSX.Element {
return <Root>{container}</Root>
}
// src/components/Root.tsx
import { UseRequestProvider } from 'ahooks'
import React, { FC } from 'react'
const Root: FC = ({ children }) => {
return (
<UseRequestProvider
value={{
manual: true,
loadingDelay: 1e2,
throwOnError: true,
// ...
}}
>
{children}
</UseRequestProvider>
)
}
export default Root
在app.tsx处包裹的全局配置Root组件(Root组件中还有其他ContextProvider未写出),在pages页面内的useRequest Hooks能获取到在Root组件处的配置。
且使用React Devtools的Components能够观察到Root组件被成功渲染,且ContextProvider配置被成功加载。见下图
引入该插件后,以上代码不符合预期。
使用React Devtools的Components能够观察到Root组件没有被渲染,且ContextProvider配置没有被加载。见下图
研究了一番之后发现,引入该插件之后直接使用renderRoutes渲染路由出口,忽视了src/app.tsx的rootContainer函数
其他发现:调整umi plugin的rootContainer执行顺序可以使得src/app.tsx的rootContainer在umi-plugin-keep-alive的rootContainer之前执行,那么可以很好的解决问题。见下代码
// src/.umi/core/plugin.ts
// @ts-nocheck
import { Plugin } from 'D:/Project/TypeScript/my-antd/node_modules/@umijs/runtime';
const plugin = new Plugin({
validKeys: ['patchRoutes','rootContainer','render','onRouteChange','antd','dva','getInitialState','layout','request',],
});
plugin.register({
apply: require('D:/Project/TypeScript/my-antd/src/app.tsx'),
path: 'D:/Project/TypeScript/my-antd/src/app.tsx',
});
plugin.register({
apply: require('../plugin-keep-alive/runtime'),
path: '../plugin-keep-alive/runtime',
});
// ...
export { plugin };
交换src/app.tsx
和插件plugin-keep-alive
顺序,即改为以下代码
// src/.umi/core/plugin.ts
// @ts-nocheck
import { Plugin } from 'D:/Project/TypeScript/my-antd/node_modules/@umijs/runtime';
const plugin = new Plugin({
validKeys: ['patchRoutes','rootContainer','render','onRouteChange','antd','dva','getInitialState','layout','request',],
});
plugin.register({
apply: require('../plugin-keep-alive/runtime'),
path: '../plugin-keep-alive/runtime',
});
plugin.register({
apply: require('D:/Project/TypeScript/my-antd/src/app.tsx'),
path: 'D:/Project/TypeScript/my-antd/src/app.tsx',
});
// ...
export { plugin };
可以通过React Devtools的Components能够观察到Root组件被成功渲染,且ContextProvider配置被成功加载,且AliveScopeContainer无异常,见下图。
但是可惜的是,umi官网没有找到可以调整plugin执行顺序的方法,手动调整src/.umi/core/plugin.ts的代码没有意义,修改代码热部署后会重置.umi该目录
建议可以兼容src/app.tsx的rootContainer函数,让src/app.tsx的rootContainer函数执行优先于umi-plugin-keep-alive的rootContainer函数。如果该方法行不通可以提供另一函数用于取代rootContainer。至少能够有一种方法或途径可以让用户自定义root节点。希望作者能够解决该问题。
最后多谢作者的贡献和回复
注入顺序可以通过 addRuntimePlugin 的 stage 属性进行调整,目前是将 keep-alive 插件的优先级调至最低了,没想到会覆盖用户自定义的 app rootContainer
目前只能快速响应,不过还没时间处理,如果可以的话,可以在找到方案后提个 PR~
umi 目前的自定义运行时执行顺序在最末尾,目前比较难处理,看看 PR 过不过,不过的话处理起来会棘手一些
keep-alive runtime 的目的是在 Router 内部置入 AliveScope,如果使用了自定义 rootContainer,Router 原先所在的 RouterCompoent 组件会被埋到更深的层级中
如果 PR 过了,可以让 keep-alive 的 runtime 置于最底层,这样可以直接获得 RouterComponent 进行替换
如果不过的话,需要在自定义 rootContainer 中进行递归,定位 RouterComponent 后做替换,这个难度比较大,因为 RouterComponent 位置不确定,甚至有可能不被使用
换了个方法,不找 RouterComponent 了,直接把代码 copy 过来用,改动频次应该不大 自定义 rootContainer 使用 fixCustomizedRuntime.tsx 配合 stage 修复
umi的src/app.ts的rootContainer函数还是很有用处的,比如包裹antd和umi request的全局配置等行为。 但是使用了该插件之后,rootContainer的AliveScopeContainer行为会屏蔽app.ts里的rootContainer的渲染,导致没有途径再包裹全局配置。