React 不依赖第三方库怎么做到页面状态的缓存?
很多时候特别是用户从列表点击进入某一项的详情,这时用户点击返回到列表时,依旧保持上一次的一些页面状态如当前页码,查询条件,列表数据等。
Vue 中有官方的 KeepAlive 组件,而 React 中我也尝试了几个第三方库如 react-activation ,效果不是很满意,特别是必须要降为 React17 版才能用。
如果要在离开页面时将状态缓存到 Zustand ,返回时再从 Zustand 中取出回显,如果页面用到的状态很多的话也非常繁琐,想问一下哥哥们有没有什么好的解决方案或者推荐用法。
谢谢哥哥们!
我是自己实现了一套路由,A 跳到 B ,A 页面还在,只是被 B 页面盖住了,返回 A 就把 B 页面移除。
我们用 antd 的全屏 drawer 显示详情,原来的组件还在,没被替换掉
写到 url 里啊,网站这么多年来都是这么做的。别整那些存本地,花里胡哨的。url 最靠谱,跨设备,发给别人也好使。
history or hash
试过很多方式,最简单的就是 zindex 层叠覆盖
根本原因在于 react-router/vue-router 使用的是替换渲染式路由,push route 时旧页面状态会全部丢失
如果是 android 的 activity 这种层叠式渲染路由,push route 时旧页面只是被覆盖,并没有回收,所以不会出现这种情况,缺点是占用内存较多
此外在微信小程序的 taro(也是 react) 框架,微信小程序的路由机制也是 webview 层叠渲染(旧路由不会被销毁),没有你说的这个问题,缺点也是内存占用,但是没人在意。
而 android 的新 ui compose(类似 react) 也切换至 compose-navigation 这种替换式渲染式路由,也是会丢失状态的(不做任何操作的情况下)
但是 compose-navigation 额外对接了 viewModel 框架
开发者需要提升状态声明在 viewModel 中,然后在路由页面里使用它,当发生 push 行为时,页面停止渲染,但是 viewModel 并不会被回收,因为它的生命周期是跟着路由栈存在的,所以当你返回上一个页面时,重新渲染此页面,由于 ui=f(state) ,state 都在,所以状态都在。
并且 compose 还会提供如 rememberSaveable/rememberScrollState 这种保留状态的 hooks ,也是跟着路由栈存在,所以很好的解决了你提出的这个问题。
按照 compose 的解决思路,你必须把所有状态提升到 viewModel 中,也就是 store/url 里,并且你得构建一个和 url 栈联系的 store ,避免内存泄露
另外一个最简单的方法就是
把有关系的页面写在一个 route 下,不要发生 router.push 行为,没有组件销毁,状态自然也不会丢失
会不会太冗余了
那岂不是可以随便改
不要把状态写在组件内部,需"变量提升"
如果是针对“用户从列表点击进入某一项的详情,这时用户点击返回到列表时,依旧保持上一次的一些页面状态如当前页码,查询条件,列表数据等”这个问题,推荐将你的筛选条件缓存到 url 上,然后列表的数据可以使用 tanstack-query 去请求,后台接口的数据会根据你的 key 值进行缓存。
刚好之前搞过,可以用 react-router-dom 的 useOutlet ,返回的 outlet 你自己放到 antd 的 tabs 中保管即可
正好我有自己写的代码专门解列表进详情页的 keepAlive 问题,本来依赖了 react-freeze ,我一看只有 react-freeze 只有几十行代码,直接 copy 到本地了
这时 freeze 的代码。
我现在参与的项目就是,vue2 做的,每点击一次 tab ,页面都要重新刷新一次,然后还要伴随一个从做滑入的动画,真是服了.....
用法也很简单,专门针对列表进详情页 keepalive 的问题
url + react-query
将页面状态保持到 url 里,url state 就是一个天然的全局 state store 。
请求用 react-query ,react-query 会自动缓存住请求的数据。当从 detail 回到 list 时,会马上得到之前缓存的请求数据,react-query 同时会在后台去重新请求并更新。
以前也尝试过其它各种方案,现在下来发现这套是最舒服的。写了一个极轻量的 react url-state-hook ,可以适配任意 react router 库 - github.com/baurine/use-url-state
感谢好哥哥们提出的方案!
还有就是 说的,保存在 url 里可以将状态方便地分享给别人。
tanstack router 的文档上是这么说的: tanstack.com/router/latest/docs/framework/react/overview#1st-class-search-parameters
Let's step back and remember that search params are the most powerful state manager in your entire application. They are global, serializable, bookmarkable, and shareable making them the perfect place to store any kind of state that needs to survive a page refresh or a social share.
对于不需要 shareable 的状态,则可以使用 zustand 。
目前我的状态管理方案:
- context
- url state
- react-query
zustand
window.mycache ={}
你在制造原本就不存在的问题混乱邪恶派:不用 useState ,所有状态都存在 zustand 就可以了
Chrome 会扫盘,不考虑。 duckduckgo.com/?q=chrome+software+reporterEdge 强制上传浏览记录、强制往用户浏览的链接插 aff …
render 页面控制台上会出错,怎么处理? 改成 async: false ,不太优雅。看别人页面上转圈圈,直到数据返回,这个怎么实现的。 不是应该加一个 loading…
有一台服务器,在公网上,带宽限速上行 100Mb ,我经常连上去写代码。以前一直用的是 1080p 或 2K 屏,那会远程连接到服务器上去写代码,觉得很流畅,因为是直连。没有中…