
在使用 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。
// 假设 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.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 中数组的过滤与更新:避免常见陷阱的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1532965.html
微信扫一扫
支付宝扫一扫