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

icejs 支持路由级别的React Keep Alive #3875

Open
MarshalShan opened this issue Dec 1, 2020 · 10 comments
Open

icejs 支持路由级别的React Keep Alive #3875

MarshalShan opened this issue Dec 1, 2020 · 10 comments

Comments

@MarshalShan
Copy link

发生了什么?

当前开发的的产品中有使用到icework 和 icestark 所提供的技术能力,目前需求提出需要保障页面在切换后保留上一次的操作内容。

复现步骤,错误日志以及相关配置

需求举例:A页面路由到B页面再从B页面返回A页面希望保留A页面上一次的状态数据。

期望的结果是什么

希望ICE框架能够支持路由级别的 React Keep Alive。

相关环境信息

  • ice.js 版本:1.7.0
  • build.json 配置
  • Node 版本:10.16.0
  • 操作系统:mac os
@imsobear imsobear changed the title Ice Work 支持路由级别的React Keep Alive icejs 支持路由级别的React Keep Alive Dec 1, 2020
@rootsli
Copy link

rootsli commented Jan 11, 2021

@imsobear 有相同场景诉求,微前端由A页面(or 子应用)切换到B页面再切回A页面时,希望页面保持上次的状态,例如:当前选中第几个tab状态,table翻页停留在第几页状态,搜索框状态。总之,所有状态不需要重置。目前,感觉没有好的通用方案。

@rootsli
Copy link

rootsli commented Jan 12, 2021

@imsobear 类似umi的umi-plugin-keep-alive功能,借助react-activation实现的

@ClarkXia
Copy link
Collaborator

ClarkXia commented Jan 21, 2021

Keep Alive 方案

对于路由级别的 Keep Alive 方案,常见的场景会有三种情况:

  • 结合状态管理的 Keep Alive
  • 组件级别 Keep Alive 方案(组件内部 state 状态缓存)
  • 基于微前端的 Keep Alive 方案

结合状态管理的 Keep Alive

如果组件内大部分状态均通过状态管理方案进行维护,可以保持状态不销毁

每次组件切换后均从 store 中读取上一次的状态数据进行渲染

要求开发者在开发项目过程中设计好状态管理的数据结构,手动保存状态,比如 /app/${id} 的路由切换想按 id 缓存 app 信息,那么 app 的信息需要通过{[id]: appInfo} 的方式缓存,而不是每次都仅记录当前页面的 app 信息

组件级别 Keep Alive

组件级别 Keep Alive 最大的问题在于,部分组件的数据逻辑相对比较复杂:组件内部通过 useState 维护了自身的状态,包括一些表单输入状态。如果这些状态均通过手动保存状态的方式来 Keep Alive,将会有较大的成本。

方案

社区常见做法将渲染组件缓存在一个不会被卸载的组件内部,等下一次目标组件重新渲染时,再通过 DOM 操作将缓存的真实内容移入到对应的组件节点下。比如 react-activation

结合 icejs 一键开启能力参见PR

微前端 Keep Alive

微前端架构中的每次应用切换都将会执行上一个微应用的卸载的生命周期,如果想对微应用 Keep Alive 需要进行如下改造:

  • 微应用切换时不执行 unmount 生命周期
  • 将微应用当前渲染的组件实例进行缓存
  • 微应用再次渲染时,如果存在缓存内容,则直接通过 DOM 操作渲染缓存组件

方案

针对 icestark 微前端方案在 React 主应用使用场景上封装了 AppRouter 的方式,如果需要一键启用 Keep Alive 能力,则需要 AppRouter 内部支持或者提供相应的钩子函数来完成上述改造要点

使用方式:

<AppRouter>
  <AppRoute {...rest} keepAlive />
</AppRouter>

存在的问题:

  • 微应用切换后,实际没有进行卸载,会出现多应用共存的问题,导致脚本和样式的冲突问题凸显
  • cache 整体应用的 node,对于内存会有比较高的占用

@caojinjie
Copy link

请问一下当前是否能够解决在ice +icestark的场景下当切换不同的icestark支持子应用的keep-alive @ClarkXia

@MarshalShan
Copy link
Author

请问当前所使用的ice+icestark 主应用和子应用都有需要使用到keep-alive 时应该如配合呢

@ClarkXia
Copy link
Collaborator

请问当前所使用的ice+icestark 主应用和子应用都有需要使用到keep-alive 时应该如配合呢

主应用使用 keep-alive 的方式 应该是应用间相互切换的时候保留数据,这块会涉及多应用共存冲突以及路由响应的解决,近期我们会整体设计下

@caojinjie
Copy link

请问一下build-plugin-keep-alive有清理的配置吗?

场景是这样的:Tab导航模式,切换导航时,会回到keepalive的页面,关闭该导航重新打开菜单时,需要重新mount

@imsobear
Copy link
Collaborator

keep-alive 的使用单独整理个文档吧

@zh-rocco
Copy link
Contributor

结合 icestark 使用时,仅启动主项目,遇到这个报错 You should not use <KeepAlive /> outside a <AliveScope>

@xinyiPig
Copy link

结合 icestark 使用时,仅启动主项目,遇到这个报错 You should not use <KeepAlive /> outside a <AliveScope>

@zh-rocco 请问这个问题解决了吗?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants