V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lin0912happy
V2EX  ›  React

React 不依赖第三方库怎么做到页面状态的缓存?

  •  
  •   lin0912happy · 1 天前 · 1847 次点击
    很多时候特别是用户从列表点击进入某一项的详情,这时用户点击返回到列表时,依旧保持上一次的一些页面状态如当前页码,查询条件,列表数据等。
    Vue 中有官方的 KeepAlive 组件,而 React 中我也尝试了几个第三方库如 react-activation ,效果不是很满意,特别是必须要降为 React17 版才能用。
    如果要在离开页面时将状态缓存到 Zustand ,返回时再从 Zustand 中取出回显,如果页面用到的状态很多的话也非常繁琐,想问一下哥哥们有没有什么好的解决方案或者推荐用法。
    谢谢哥哥们!
    29 条回复    2025-01-08 19:27:59 +08:00
    ltaoo1o
        1
    ltaoo1o  
       1 天前
    我是自己实现了一套路由,A 跳到 B ,A 页面还在,只是被 B 页面盖住了,返回 A 就把 B 页面移除。
    darkengine
        2
    darkengine  
       1 天前
    我们用 antd 的全屏 drawer 显示详情,原来的组件还在,没被替换掉
    ChefIsAwesome
        3
    ChefIsAwesome  
       1 天前
    写到 url 里啊,网站这么多年来都是这么做的。别整那些存本地,花里胡哨的。url 最靠谱,跨设备,发给别人也好使。
    Gilfoyle26
        4
    Gilfoyle26  
       1 天前   ❤️ 1
    history or hash
    mlracie
        5
    mlracie  
       1 天前 via iPhone
    试过很多方式,最简单的就是 zindex 层叠覆盖
    lisongeee
        6
    lisongeee  
       1 天前   ❤️ 3
    根本原因在于 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 ,避免内存泄露
    lisongeee
        7
    lisongeee  
       1 天前   ❤️ 1
    另外一个最简单的方法就是

    把有关系的页面写在一个 route 下,不要发生 router.push 行为,没有组件销毁,状态自然也不会丢失
    seeu2ex
        8
    seeu2ex  
       19 小时 39 分钟前 via iPhone
    @lisongeee 会不会太冗余了
    superchijinpeng
        9
    superchijinpeng  
       18 小时 53 分钟前
    @ChefIsAwesome 那岂不是可以随便改
    jardel
        10
    jardel  
       18 小时 31 分钟前
    不要把状态写在组件内部,需"变量提升"
    xxgw
        11
    xxgw  
       18 小时 22 分钟前
    如果是针对“用户从列表点击进入某一项的详情,这时用户点击返回到列表时,依旧保持上一次的一些页面状态如当前页码,查询条件,列表数据等”这个问题,推荐将你的筛选条件缓存到 url 上,然后列表的数据可以使用 tanstack-query 去请求,后台接口的数据会根据你的 key 值进行缓存。
    realJamespond
        12
    realJamespond  
       18 小时 19 分钟前
    刚好之前搞过,可以用 react-router-dom 的 useOutlet ,返回的 outlet 你自己放到 antd 的 tabs 中保管即可
    snowlee
        13
    snowlee  
       17 小时 54 分钟前
    正好我有自己写的代码专门解列表进详情页的 keepAlive 问题,本来依赖了 react-freeze ,我一看只有 react-freeze 只有几十行代码,直接 copy 到本地了
    snowlee
        14
    snowlee  
       17 小时 53 分钟前
    这时 freeze 的代码。
    hahaFck
        15
    hahaFck  
       17 小时 52 分钟前
    我现在参与的项目就是,vue2 做的,每点击一次 tab ,页面都要重新刷新一次,然后还要伴随一个从做滑入的动画,真是服了.....
    snowlee
        16
    snowlee  
       17 小时 52 分钟前
    用法也很简单,专门针对列表进详情页 keepalive 的问题
    sparkle2015
        17
    sparkle2015  
       17 小时 27 分钟前
    url + react-query

    将页面状态保持到 url 里,url state 就是一个天然的全局 state store 。

    请求用 react-query ,react-query 会自动缓存住请求的数据。当从 detail 回到 list 时,会马上得到之前缓存的请求数据,react-query 同时会在后台去重新请求并更新。

    以前也尝试过其它各种方案,现在下来发现这套是最舒服的。写了一个极轻量的 react url-state-hook ,可以适配任意 react router 库 - https://github.com/baurine/use-url-state
    lin0912happy
        18
    lin0912happy  
    OP
       17 小时 23 分钟前
    感谢好哥哥们提出的方案!
    sparkle2015
        19
    sparkle2015  
       17 小时 20 分钟前
    还有就是 @ChefIsAwesome 说的,保存在 url 里可以将状态方便地分享给别人。

    tanstack router 的文档上是这么说的: https://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.
    sparkle2015
        20
    sparkle2015  
       17 小时 16 分钟前
    对于不需要 shareable 的状态,则可以使用 zustand 。
    目前我的状态管理方案:
    1. context
    2. url state
    3. react-query
    4. zustand
    heimoshuiyu
        21
    heimoshuiyu  
       17 小时 10 分钟前
    window.mycache ={}
    你在制造原本就不存在的问题
    nulIptr
        22
    nulIptr  
       17 小时 9 分钟前
    混乱邪恶派:不用 useState ,所有状态都存在 zustand 就可以了
    90xchun
        23
    90xchun  
       15 小时 40 分钟前
    考虑需要跨页数据的更新情况,把数据通过自定义 hooks 方法,useCache 去访问,putCache 更新数据(同步 state ),这样就不存在你说的单页应用,页面跳转后列表数据就丢了的情况,useCache 里面把数据存放到 window 上面。目前就是这样解决的
    haodaking
        24
    haodaking  
       13 小时 20 分钟前   ❤️ 1
    URL 状态管理,可以试一下 nuqs
    https://nuqs.47ng.com/
    canvascat
        25
    canvascat  
       12 小时 33 分钟前
    不依赖第三方库=把第三方库功能实现一遍🐱‍👤
    lovessz
        26
    lovessz  
       8 小时 48 分钟前
    楼上的 url+请求缓存是正解
    hedwi
        27
    hedwi  
       8 小时 41 分钟前
    你搞成单页面啊 搞个变量控制 如果是列表就展示列表 如果点到详情了 就隐藏列表 显示详情
    dudubaba
        28
    dudubaba  
       8 小时 33 分钟前
    这个确实没有多优雅的方案,官方的方案也迟迟没出来,全是黑魔法实现的。
    importmeta
        29
    importmeta  
       8 小时 32 分钟前
    好问题, 曾经写过一个国企外包项目, 里面有一个多页签系统.
    网上也有类似的教程, 这个不错.
    https://juejin.cn/post/7269063053878771768
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1008 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 20:00 · PVG 04:00 · LAX 12:00 · JFK 15:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.