新闻中心

掌握 React useRef 中数组的过滤与更新:避免常见陷阱

2025-10-27
浏览次数:
返回列表

掌握 React useRef 中数组的过滤与更新:避免常见陷阱

在使用 react `useref` 存储数组并尝试对其进行过滤时,一个常见误区是期望 `array.prototype.filter()` 方法能原地修改数组。实际上,`filter()` 会返回一个新数组,因此必须将这个新数组显式地重新赋值给 `ref.current` 才能实现更新。同时,访问 `ref` 中数组的属性(如 `length`)时,务必通过 `ref.current.length` 进行。

理解 useRef 与其在数组操作中的特性

useRef 是 React 提供的一个 Hook,它允许你在函数组件中存储一个可变的引用,这个引用在组件的整个生命周期中都会持续存在,并且更新它不会触发组件的重新渲染。这使得 useRef 非常适合存储那些不需要响应式更新但需要在不同渲染之间保持不变的数据,例如 DOM 元素的引用、计时器 ID,或者像本例中不直接用于渲染的数组。

当我们将一个数组存储在 useRef 中时,我们实际上是通过 ref.current 来访问和操作这个数组。例如:

let items = useRef([]); // 初始化一个空的数组引用
// ...
items.current = data; // 从数据库获取数据后赋值给引用

数组过滤的常见误区:filter() 的非原地修改特性

在 J*aScript 中,Array.prototype.filter() 方法是一个非原地修改(non-mutating)方法。这意味着它不会改变原始数组,而是根据提供的回调函数创建一个包含通过测试的新数组。

考虑以下代码片段:

items.current.filter((item) => item.name !== toy);

这段代码会正确地生成一个不包含指定 toy 的新数组。然而,它并没有将这个新数组重新赋值给 items.current。因此,items.current 仍然指向原始的、未经过滤的数组。这就是为什么在 console.log(items.current) 时会发现数组内容没有变化的原因。

正确更新 useRef 中数组的方法

要正确地从 useRef 存储的数组中移除元素,你需要将 filter() 方法返回的新数组重新赋值给 items.current。

小爱开放平台 小爱开放平台

小米旗下小爱开放平台

小爱开放平台 291 查看详情 小爱开放平台
// 假设 items 是通过 useRef([]) 定义的
// toy 是要移除的元素的名称
items.current = items.current.filter((item) => item.name !== toy);

通过这种方式,items.current 现在指向了经过过滤后的新数组,从而实现了对 useRef 中数组的“更新”。

访问 useRef 中数组属性的正确姿势

另一个常见的错误是直接尝试访问 ref 对象的属性,而不是其 current 属性所指向的值的属性。例如,在检查数组长度时:

// 错误示例:items 是一个 ref 对象,没有 length 属性
if (items.length === 0) {
  console.log('Winner');
  // ...
}

items 本身是一个 RefObject 类型,它只有一个 current 属性。要获取数组的长度,你必须通过 items.current 来访问数组,然后获取其 length 属性。

// 正确示例:通过 items.current 访问数组的 length 属性
if (items.current.length === 0) {
  console.log('Winner');
  n*igate('/leaderboard', { state: time });
}

完整的修正示例

结合上述两点修正,原始 handleAction 函数的正确实现应如下:

function handleAction(click, toy) {
  const item = items.current.find((item) => item.name === toy);

  if (!item) {
    setFound(`Not quite, try again!`);
    return;
  }

  if (click.x > item.left && click.x < item.right) {
    if (click.y < item.bottom && click.y > item.top) {
      setFound(`Well done! You've found Sarah's ${toy}`);
      // 修正1:重新赋值过滤后的数组
      items.current = items.current.filter((i) => i.name !== toy);
      console.log(items.current);

      // 修正2:通过 items.current.length 检查数组长度
      if (items.current.length === 0) {
        console.log('Winner');
        n*igate('/leaderboard', { state: time });
      }
    }
  } else {
    setFound(`Not quite, try again!`);
    return;
  }
}

总结与注意事项

  • filter() 不会原地修改数组:始终记住 Array.prototype.filter() 返回的是一个新数组。如果你想“更新”原始数组,必须将新数组重新赋值给变量。
  • useRef 的访问方式:useRef 存储的值总是通过 .current 属性来访问和修改。无论是读取还是写入,都必须使用 ref.current。
  • useRef 与 useState 的选择
    • 当数据变化不需要触发组件重新渲染时,使用 useRef。例如,本例中 items 数组的改变不直接影响 UI 元素的渲染,它只是一个内部状态管理。
    • 当数据变化需要触发组件重新渲染以更新 UI 时,使用 useState。如果 items 数组的改变直接导致页面上渲染的元素列表发生变化,那么它应该存储在 useState 中。
  • 可变性与不可变性:虽然 useRef 允许你存储可变数据,但在处理数组时,采用 filter() 这种不可变操作(创建新数组)并重新赋值,通常比 splice() 这种原地修改操作更安全、更易于理解和调试,尤其是在大型项目中。

通过理解 useRef 的工作原理以及 J*aScript 数组方法的特性,可以有效避免在 React 应用中处理可变数据时常见的陷阱。

以上就是掌握 React useRef 中数组的过滤与更新:避免常见陷阱的详细内容,更多请关注其它相关文章!


# 它只  # 河南seo技巧多少钱  # 网站推广点击怎么做  # SEO整站优化收费  # 商务网站怎么建设教程  # 黄冈网站推广排名机构  # 汝阳网站推广工作室  # 安阳网站推广技术  # 网站优化软件测试面试  # 汕头商城网站推广建设  # 优化推广网站的方法  # 移除  # 正确地  # 服务端  # react  # 来访问  # 自定义  # 不需要  # 小爱  # 回调  # 是一个  # gate  # 为什么  # win  # ai  # 回调函数  # java  # javascript 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 解决 Express.js 中 PUT 请求密码修改失败的路由配置指南  深入理解J*a编译器的兼容性选项:从-source到--release  如何在CSS中使用visited与link控制链接颜色_visited link伪类配合  豆包手机助手发布技术预览版:直接嵌入手机系统!努比亚样机发售  品牌机怎么重装系统 联想/戴尔/惠普笔记本恢复出厂系统教程  Sublime Text怎么设置垂直标尺_Sublime配置Rulers规范代码长度  谷歌google账号怎么注册账号 谷歌账号注册官方流程  如何使用spryker/configurable-bundles-products-resource-relationship模块解决复杂产品捆绑关系难题  Android Studio计算器C键功能异常排查与修复教程  163邮箱官方主页登录 直达网易邮箱登录核心页面  4399网页游戏电脑版全新入口 4399电脑端在线玩指南  2025AO3夸克浏览器通道_AO3手机HTTPS安全入口分享  mcjs网页版流畅运行 mcjs低配电脑畅玩入口  C#如何安全地从用户上传的XML文件中读取数据? 验证与清理策略  极兔快递快件信息查询系统 极兔快递官网运单号追踪  天眼查怎么看公司融资情况 天眼查企业融资历史查询步骤【攻略】  CSS布局中意外空白:解决padding-top导致的顶部间距问题  微信怎么把收藏的内容分类管理 微信收藏内容标签分类方法  Excel中VLOOKUP的第四个参数是干什么用的_Excel VLOOKUP第四参数作用解析  文心一言怎样用批量生成做多版文案_文心一言用批量生成做多版文案【批量创作】  如何将HTML表格多行数据保存到Google Sheets  漫蛙网页登录入口 漫蛙漫画官方授权网址  我的世界官方游戏入口 我的世界官网平台直达链接  必由学官方网站入口 必由学学生教师共用登录通道  Go语言中Map值调用指针接收器方法的限制与应对  京东单号查询入口_京东快递订单追踪入口  支付宝碰一碰设备是REDMI手机吗 博主拆机辟谣:处理器、内存都不一样  J*aScriptWebpack优化_J*aScript构建工具实战  TypeScript/J*aScript:高效查找数组中首个唯一ID对象  Spyder启动失败:字体文件权限拒绝错误解决方案  解决Python logging 中 datefmt 导致时间戳固定不变的问题  护手霜蹭到袖口上了如何清洗? 怎样避免留下一圈油印?  QQ官网正版登录链接 QQ在线登录入口最新  css元素hover动画延迟生效怎么办_使用animation-delay调整触发时间  qq音乐在线播放入口_qq音乐电脑版登录链接  HTML长属性值处理:表单action路径优化与代码规范应对  C++如何进行游戏物理模拟_使用Box2D库为C++游戏添加2D物理效果  生成rdflib自定义SPARQL函数:参数匹配与实践指南  Golang如何测试channel通信行为_Golang channel通信测试与分析方法  Go语言中JSON数据解析与字段访问教程  怎么在浏览器上运行HTML文件_浏览器运行HTML文件技巧【技巧】  J*a递归快速排序中静态变量的状态管理与陷阱  网易大神怎么保存别人动态的图片_网易大神动态图片保存方法  优化Django表单:提交验证失败后保留用户输入  微博网页版直接访问 微博网页版账号管理快速入口  微信网页版扫码登录入口 微信网页版二维码登录入口  2026年发布! 美少女养成动作RPG《神剑少女战记》发布实机演示  可靠CSGO开箱平台解析 CSGO开箱网合集  迅雷下载到U盘速度很慢怎么办_迅雷U盘下载慢优化方法  怎样更改Windows系统的默认安装路径_避免C盘爆满的终极设置【技巧】 

搜索