首页 > web前端 > js教程 > 正文

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

花韻仙語
发布: 2025-10-27 12:54:11
原创
622人浏览过

掌握 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() 的非原地修改特性

在 JavaScript 中,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。

新CG儿
新CG儿

数字视觉分享平台 | AE模板_视频素材

新CG儿147
查看详情 新CG儿
// 假设 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');
  navigate('/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');
        navigate('/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 的工作原理以及 JavaScript 数组方法的特性,可以有效避免在 React 应用中处理可变数据时常见的陷阱。

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

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号