React中怎么实现状态自动保存(KeepAlive)?

2023-10-28

什么是状态保存?

移动端中,用户访问了一个列表页,上拉浏览列表页的过程中,随着滚动高度逐渐增加,数据也将采用触底分页加载的形式逐步增加,列表页浏览到某个位置,用户看到了感兴趣的项目,点击查看其详情,进入详情页,从详情页退回列表页时,需要停留在离开列表页时的浏览位置上

类似的数据或场景还有已填写但未提交的表单、管理系统中可切换和可关闭的功能标签等,这类数据随着用户交互逐渐变化或增长,这里理解为状态,在交互过程中,因为某些原因需要临时离开交互场景,则需要对状态进行保存

在 React 中,通常会使用路由去管理不同的页面,而在切换页面时,路由将会卸载掉未匹配的页面组件,所以上述列表页例子中,当用户从详情页退回列表页时,会回到列表页顶部,因为列表页组件被路由卸载后重建了,状态被丢失。


如何实现 React 中的状态保存

在 Vue 中,我们可以非常便捷地通过 <keep-alive> 标签实现状态的保存,该标签会缓存不活动的组件实例,而不是销毁它们

而在 React 中并没有这个功能,曾经有人在官方提过相关 issue ,但官方认为这个功能容易造成内存泄露,表示暂时不考虑支持,所以就需要自己想办法了。


常见的解决方式:手动保存状态

手动保存状态,是比较常见的解决方式,可以配合 React 组件的 componentWillUnmount 生命周期通过 redux 之类的状态管理层对数据进行保存,通过 componentDidMount 周期进行数据恢复

在需要保存的状态较少时,这种方式可以比较快地实现我们所需功能,但在数据量大或者情况多变时,手动保存状态就会变成一件麻烦事

为了不需要每次都关心如何对数据进行保存恢复,研究如何自动保存状态


通过路由实现自动状态保存(通常使用 react-router)

既然 React 中状态的丢失是由于路由切换时卸载了组件引起的,那可以尝试从路由机制上去入手,改变路由对组件的渲染行为

以下的方式去实现这个功能:

  • 重写 <Route> 组件,可参考 react-live-route。重写可以实现想要的功能,但成本也比较高,需要注意对原始 <Route> 功能的保存,以及多个 react-router 版本的兼容
  • 重写路由库,可参考 react-keeper 。重写路由库成本是一般开发者无法承受的,且完全替换掉路由方案是一个风险较大的事情,需要较为慎重地考虑。
  • 基于 <Route> 组件现有行为做拓展,可参考 react-router-cache-route 。在阅读了 <Route> 的源码后发现,如果使用 component 或者 render 属性,都无法避免路由在不匹配时被卸载掉的命运。但将 children 属性当作方法来使用,我们就有手动控制渲染的行为的可能。

上面几种方案,主要通过路由入手实现自动状态保存的可能,但终究不是真实的、纯粹的 KeepAlive 功能。


模拟真实的 <KeepAlive> 功能

function App() {
  const [show, setShow] = useState(true)

  return (
    <div>
      <button onClick={() => setShow(show => !show)}>Toggle</button>
      {show && (
        <KeepAlive>
          <Test />
        </KeepAlive>
      )}
    </div>
  )
}

简单介绍下 react-activation 的实现原理:由于 React 会卸载掉处于固有组件层级内的组件,所以我们需要将 <KeepAlive> 中的组件,也就是其 children 属性抽取出来,渲染到一个不会被卸载的组件 <Keeper> 内,再使用 DOM 操作将 <Keeper> 内的真实内容移入对应 <KeepAlive>,就可以实现此功能

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React中怎么实现状态自动保存(KeepAlive)? 的相关文章

  • 从数据 URI 解码 QR 码

    我尝试从数据 uri 中解码二维码 var dataUri data image gif base64 R0lGODdh9gD2AIAAAAAAAP ywAAAAA9gD2AAAC decodeQrCode dataUri cb 我已经尝试
  • 如何重置使用 JavaScript 更改的 CSS 属性?

    我的导航按钮的宽度从 100px 增加到 150px 当鼠标悬停在 nav li hover width 150px 但是使用 javascript 我已经做到了 无论选择哪个选项 宽度都将继续为 150px 当选择每个选项时 它会使其他选
  • 使用模数按字母顺序对列表进行排序

    我在获取元素列表并按字母顺序对它们进行排序方面没有任何问题 但我很难理解如何使用模数来做到这一点 更新 这是按我的方式工作的代码 但是 我更喜欢下面提供的答案的可重用性 因此接受了该答案
  • jQuery AJAX 调用 Java 方法

    使用 jQuery AJAX 我们可以调用特定的 JAVA 方法 例如从 Action 类 该 Java 方法返回的数据将用于填充一些 HTML 代码 请告诉我是否可以使用 jQuery 轻松完成此操作 就像在 DWR 中一样 此外 对于
  • 使用 JavaScript 使链接保持活动状态并在单击时显示悬停效果

    I am struggling to make this work I d like to make it where if O F is clicked the hover state stays active if another li
  • 如何防止 Iframe 在与浏览器交互后弄乱浏览器的历史记录?

    因此 就我而言 我使用 Iframe 将 Grafana 附加到我的页面 这为我提供了漂亮且易于使用的图表 可以注意到 每次在图表上进行放大或缩小 使用鼠标单击 交互后 Grafana 的 Iframe 都会在我的 Angular 页面上触
  • Node.js:如何在检索数据(块)时关闭响应/请求

    我正在用 node js 构建一个应用程序 它加载多个页面并分析内容 因为 node js 发送块 所以我可以分析这些块 如果一个块包含例如索引 nofollow 我想关闭该连接并继续其余部分 var host example com to
  • 除了更改标题之外,如何在 Firefox 中强制另存为对话框?

    有没有办法在 ff 中强制打开 www example com example pdf 的另存为对话框 我无法更改标题 如果您可以将文件以 Base64 格式输出到客户端 则可以使用 data uri 进行下载 location href
  • 如何将 Google Charts 与 Vue.js 库一起使用?

    我正在尝试使用 Vue js 库使用 Google Charts 制作图表 但我不知道如何添加到 div 这是我尝试做的 这是如何使用普通 javascript 添加图表 这是文档的代码示例 https developers google
  • MVC 在布局代码之前执行视图代码并破坏我的脚本顺序

    我正在尝试将所有 javascript 包含内容移至页面底部 我正在将 MVC 与 Razor 一起使用 我编写了一个辅助方法来注册脚本 它按注册顺序保留脚本 并排除重复的内容 Html RegisterScript scripts som
  • Meteor - 从客户端取消服务器方法

    我正在通过服务器方法执行数据库计数 用户可以选择他们希望如何执行计数 然后调用该方法 我的问题是 计数可能需要一些时间 并且用户可能会在方法运行时改变主意并请求不同的计数 有什么方法可以取消调用的方法并运行新的计数吗 我认为 this un
  • Firefox 书签探索未超过 Javascript 的第一级

    我已经编写了一些代码来探索我的 Firefox 书签 但我只获得了第一级书签 即我没有获得文件夹中的链接 e g 搜索引擎 雅虎网站 谷歌网站 在此示例中 我只能访问 Search engines 和 google com 不能访问 yah
  • firebase :: 无法读取 null 的属性“props”

    你好 我正在尝试将react router与firebase一起使用 但它给了我这个错误 无法读取 null 的属性 props 这正是代码 我正在其中使用我的反应路由器 向下代码位于作为登录面板组件的组件上 else if this em
  • 为 illustrator 导出脚本以保存为 web jpg

    任何人都可以帮我为 illustrator CC2017 编写一个脚本 将文件以 JPG 格式导出到网络 旧版 然后保存文件并关闭 我有 700 个文件 每个文件有 2 个画板 单击 文件 gt 导出 gt 另存为 Web 旧版 然后右键文
  • 在 React 中实现 Google 登录错误 -

    我正在尝试在 React 中实现 google 登录 这是我的组件 import Fragment useEffect from react import GOOGLE CLIENT ID from some file const Goog
  • Javascript转换时区问题

    我在转换当前时区的日期时间时遇到问题 我从服务器收到此日期字符串 格式为 2015 10 09T08 00 00 这是中部时间 但是当我使用 GMT 5 中的 new Date strDate 转换此日期时间时 它返回给我的信息如下 这是不
  • 摆脱node-jsx

    在我的 NodeJS 应用程序的路由器中 我想渲染一个 React 应用程序 由于它没有被浏览器化 并且已反应 因此它返回unexpected token lt 构建时出错 我发现如果我require node jsx install 它不
  • 问题:为什么React Native Video不能全屏播放视频?

    我正在react native 0 57 7 中为android和ios创建一个应用程序并使用反应本机视频 https github com react native community react native video播放上传到的视频
  • 如何在 pg-promise 中设置模式

    我正在搜索的文档pg 承诺 https github com vitaly t pg promise特别是在创建客户端时 但我无法找到设置连接中使用的默认架构的选项 它始终使用public架构 我该如何设置 通常 为数据库或角色设置默认架构
  • 导致回发到与弹出窗口不同的页面

    我有一个主页和一个详细信息页面 详细信息页面是从主页调用的 JavaScript 弹出窗口 当单击详细信息页面上的 保存 按钮时 我希望主页 刷新 是否有一种方法可以调用主页的回发 同时还可以从详细信息页面维护保存回发 Edit 使用win

随机推荐

  • 第四届蓝桥杯Java B组 马虎的算式

    马虎的算式 Description 小明是个急性子 上小学的时候经常把老师写在黑板上的题目抄错了 有一次 老师出的题目是 36 x 495 他却给抄成了 396 x 45 但结果却很戏剧性 他的答案竟然是对的 因为 36 x 495 396
  • unity航点寻径

    一 游戏框架 设置了六个路标 角色会在这六个路标之间一次移动 当移动到第六个路标后又会返回第一个路标 继续依次移动 road 道路 由五个立方体组成 sign 路标 由六个胶囊组成 enemy 寻路的角色 二 游戏实现 1 创建一个平面 赋
  • RGB颜色对照表大全

    常用颜色rgb 颜色对照表 一 R G B 值 R G B 值 R G B 值 黑色 0 0 0 000000 黄色 255 255 0 FFFF00 浅灰蓝色 176 224 230 B0E0E6 象牙黑 41 36 33 292421
  • pdf预览

    previewSop url axios get url responseType arraybuffer then res gt var data res data var blob new Blob data type applicat
  • 实现多线程爬取数据并保存到mongodb

    多线程爬取二手房网页并将数据保存到mongodb的代码 import pymongo import threading import time from lxml import etree import requests from queu
  • 什么是3d虚拟数字人?对未来发展有什么影响?

    3d虚拟数字人指的是以数字形式存在的人工智能 也被称为数字智能体 无论是在我们的周围 还是我们自己的体内 他们都能够利用数据和代码来进行模拟 操纵和创造各种不同的人类形态 基本上来说 数字人就是指那些具备大脑 眼睛 手和嘴等特性的数字化机器
  • 【Analyzing and Mitigating Interference in Neural Architecture Search】分析与缓解NAS权重共享方法中的子模型之间的干扰问题

    Analyzing and Mitigating Interference in Neural Architecture Search 论文地址 https proceedings mlr press v162 xu22h html 摘要
  • google-app-engine 上传下载 用户文件

    http blog notdot net 2009 9 Handling file uploads in App Engine http hi baidu com zjm1126 item 31d65e31962da022b3c0c56e
  • 数据库中如何将数据库文件转移到其他主机中

    目录 一 数据库文件 二 方法一 分离 gt 附加 三 方法二 脱机 gt 附加
  • VS问题总结记录(持续更新)

    1 error MSB8020 无法找到 v142 的生成工具 平台工具集 v142 若要使用 v142 生成工具进行生成 请安装 v142 生成工具 https blog csdn net weixin 39956356 article
  • 丰田工机安全plc编程软件pcwin safe

    丰田工机安全plc编程软件pcwin safe 14而且还是中文版的 绝对是难得的资源 toyopuc YID 17200678135439768 在现代工业领域 计算机技术的广泛应用已成为了工厂生产和管理的重要组成部分 同时也给工业安全带
  • node.js 如何读取json文件内容

    最简单的方式 const config require config json console log name config name console log age config age require方法的缺点 内容会被缓存 不适合动
  • cocos2d-x 浅析斗地主游戏分牌动作

    cocos2d x 浅析斗地主游戏分牌动作 分类 C C Cocos2d x学习笔记 2013 05 17 13 54 461人阅读 评论 0 收藏 举报 cocos2d x 斗地主 动作 最近在开发一款基于cocos2d x的斗地主棋牌游
  • MATLA技巧

    如何将MATLAB矩阵每列都归一化为单位向量 function matrix normalized norm matrix by column matrix column norms sqrt sum abs matrix 2 1 or v
  • 10款最著名的代码(文本)编辑器

    通常操作系统和软件开发包中都包含文本编辑器 可以用来编辑配置文件 文档文件和源代码 下面是笔者总结的 10 个最好的免费代码文本编辑器 1 NOTEPAD NOTEPAD 是一款免费又优秀的文本编辑器 支持在 MS Windows 环境下运
  • 全网最完整php禁用eval函数讲解

    1 eval是什么 eval是一个语言构造器 并不是系统组件函数 因此我们在php ini中使用disable functions是无法禁止它的 2 eval的危害 eval 对于php安全来说具有很大的杀伤力 因此一般不用的情况下为了防止
  • Linux下 C 遍历目录(opendir,readdir函数)

    opendir 函数 头文件 include
  • 如何用清华 ChatGLM 微调一个私域大模型

    曹政 曹大是我们圈子里公认的大佬 他在技术上不仅早早领先 在思维认知领域更是帮助很多小伙伴快速成长 没有 ChatGPT 之前 我一直在想 能否将曹大的思维 直接植入过来 就跟无崖子传输功力 头碰头就行 当然我多想了 ChatGPT 出来后
  • EXT.JS2.2表单上传文件

    var uploadFile new Ext form TextField fieldLabel 上传文件 id file name uploadFile height 25 width 860 blankText 请上传文件 itemCl
  • React中怎么实现状态自动保存(KeepAlive)?

    什么是状态保存 移动端中 用户访问了一个列表页 上拉浏览列表页的过程中 随着滚动高度逐渐增加 数据也将采用触底分页加载的形式逐步增加 列表页浏览到某个位置 用户看到了感兴趣的项目 点击查看其详情 进入详情页 从详情页退回列表页时 需要停留在