React useRef 中数组操作:正确过滤与更新实践


react useref 中数组操作:正确过滤与更新实践

在使用 React `useRef` 管理非渲染数据时,对其中存储的数组进行过滤或修改需要特别注意。本文将深入探讨 `Array.prototype.filter()` 等方法返回新数组的特性,以及如何正确地将过滤后的新数组重新赋值给 `useRef` 的 `current` 属性,确保数据状态的有效更新。同时,也将指出在访问 `useRef` 中数组长度时常见的错误,并提供正确的访问方式。

在 React 应用开发中,useRef 是一个非常有用的 Hook,它允许我们在组件的整个生命周期中存储和访问可变值,而不会触发组件重新渲染。这对于管理 DOM 元素、存储定时器 ID 或像本例中存储不需要触发 UI 更新的数组数据非常适用。然而,当对 useRef 中存储的数组进行操作时,如果不理解 J*aScript 数组方法的行为特性,很容易遇到数据更新无效的问题。

理解 Array.prototype.filter() 的工作原理

Array.prototype.filter() 是一个非破坏性方法,这意味着它不会修改原始数组。相反,它会遍历数组中的每个元素,并根据提供的回调函数返回一个新数组,其中包含所有通过测试的元素。

考虑以下代码片段,这是在 useRef 中尝试过滤数组时常见的问题:

// 假设 items.current 是一个数组,例如:[{ name: 'toy1' }, { name: 'toy2' }]
// 尝试过滤掉名为 'toy' 的对象
items.current.filter((item) => item.name !== toy);
// 此时,items.current 仍然是原始数组,没有任何改变

这里的 filter 方法确实返回了一个新数组,其中不包含 name 等于 toy 的元素。但是,这个新数组并没有被赋值给任何变量,更没有被重新赋值给 items.current。因此,items.current 仍然指向原始的、未被过滤的数组。

正确更新 useRef 中存储的数组

要正确地更新 useRef 中存储的数组,我们需要将 filter 方法返回的新数组显式地赋值回 ref.current 属性。

// 假设 items 是一个 useRef 实例
// 正确地过滤并更新 items.current
items.current = items.current.filter((item) => item.name !== toy);
// 现在,items.current 已经更新为过滤后的新数组

通过这种方式,我们确保了 items.current 始终指向最新的、经过过滤的数组状态。

Jaaz Jaaz

开源的AI设计智能体

Jaaz 216 查看详情 Jaaz

正确访问 useRef 中数组的长度

另一个常见的错误是,当 items 是一个 useRef 实例时,错误地尝试访问 items.length。useRef 返回的对象本身并没有 length 属性。数组数据实际存储在 items.current 中。

// 错误示例:试图访问 useRef 对象的 length 属性
if (items.length === 0) {
  // 这将永远不会为 true,因为 items 是一个 { current: [...] } 对象
  console.log('Winner');
}

// 正确示例:访问 useRef.current 中数组的 length 属性
if (items.current.length === 0) {
  console.log('Winner');
  // 导航到排行榜页面
  n*igate("/leaderboard", { state: time });
}

始终记住,要访问 useRef 存储的实际值,必须通过其 current 属性。

综合示例:隐藏物品游戏中的应用

结合上述修正,以下是隐藏物品游戏 handleAction 函数的正确实现:

import { useN*igate } from 'react-router-dom';
import { useState, useEffect, useRef } from "react";
import supabase from "../config/supabaseClient";
import Image from "./image";
import Timer from "./timer";

const Game = () => {
  let items = useRef([]); // 使用 useRef 存储物品列表
  const [fetchError, setFetchError] = useState(null);
  const [found, setFound] = useState("");
  const [time, setTime] = useState(0);
  const n*igate = useN*igate();

  useEffect(() => {
    const fetchOptions = async () => {
      const { data, error } = await supabase
        .from('items')
        .select();

      if (error) {
        setFetchError('Could not fetch items');
        items.current = [];
      }

      if (data) {
        items.current = data; // 初始化 useRef 中的数组
        setFetchError(null);
      }
    }
    fetchOptions();
  }, []);

  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}`);
        // 关键修正:重新赋值过滤后的数组
        items.current = items.current.filter((i) => i.name !== toy);
        console.log(items.current);

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

  return (
    <>
      {fetchError && (<p>{fetchError}</p>)}
      <Timer time={time} setTime={setTime} />
      <Image handleAction={handleAction} />
      <p>{found}</p>
    </>
  );
}

export default Game;

注意事项与总结

  1. 数组方法的非破坏性: 记住 filter(), map(), slice() 等方法返回新数组,而不会修改原始数组。如果需要修改原始数组,可以考虑使用 splice() (但它会改变原数组,与 React 的不可变性原则不太符,除非你明确知道自己在做什么) 或者直接重新赋值。
  2. useRef.current 的重要性: 始终通过 ref.current 访问或修改 useRef 存储的值。useRef 本身是一个对象,current 属性才是真正存储你数据的容器。
  3. useRef 与 useState 的选择: 如果数据的改变需要触发组件重新渲染,那么应该使用 useState。如果数据是可变的,但其改变不需要触发重新渲染(例如本例中隐藏的物品列表),那么 useRef 是一个更合适的选择。

通过理解这些核心概念,你可以更有效地在 React 应用中利用 useRef 处理复杂的数据结构,避免常见的陷阱,并编写出更健壮、更专业的代码。

以上就是React useRef 中数组操作:正确过滤与更新实践的详细内容,更多请关注其它相关文章!


# 它会  # 泗水品牌seo工具  # 韩国seo是姓什么  # 微信推广员怎么做好营销  # 网站深圳优化建设  # 生发液的营销推广  # 智慧星SEO  # 上海关键词排名查询软件  # 曲阜营销推广找哪家比较好  # 推动营销推广  # 农业推广 电力营销  # 加载  # 这是  # 本例  # react  # 自定义  # 不需要  # 正确地  # 数据结构  # 回调  # 是一个  # gate  # 应用开发  # win  # ai  # 回调函数  # java  # javascript 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: J*aScript文本高亮功能优化:解决多词匹配错误与精确分割策略  《糖豆》添加舞曲方法  《虎扑》关闭社区内容推荐方法  Yandex浏览器官方入口_Yandex搜索引擎中文版  poki官网最新入口 poki小游戏大全入口  快手极速版在线体验区 快手极速版网页体验入口  微信朋友圈怎么设置三天可见 微信朋友圈设置指定天数可见步骤【教程】  Linux如何开发轻量级数据服务模块_Linux服务化设计  C++二维数组动态分配方法_C++指针与数组内存布局  键盘保修需要什么_键盘售后维修流程  Go Goroutine调度与并发执行深度解析  店铺如何做视频号推广?做视频号推广有用吗?  QQ邮箱手机版网页版 QQ邮箱登录入口地址  Highcharts雷达图轴线交点数值标注指南  《战地6》反作弊已成功拦截240万次作弊 发售第一周98%比赛没有作弊  mysql通配符能用于日志查询吗_mysql通配符在系统日志查询中的实际使用方法  windows server2019显卡驱动怎么安装_winserver2019显卡驱动安装与远程桌面优化  Win10锁屏时间怎么设置 Win10调整自动锁屏时间方法  Golang如何实现HTTP请求重试机制_Golang HTTP请求错误处理策略  wps文字怎么设置文字环绕图片的方式_wps文字如何设置文字环绕图片方式  Python类装饰器动态修改方法时的类型提示:Mypy插件实现精确静态分析  J*aScript 数值去小数位处理:多种方法与实践  告别繁琐SEO!如何使用SyliusSitemap插件自动化生成网站地图,提升搜索引擎排名  以下哪一项是古代兵书三十六计中的计谋  泰拉瑞亚水晶无法放置问题  在PySimpleGUI中实现键盘按键绑定按钮事件  苹果官网国补入口在哪  构建可配置的J*aScript加权点击计数器与共享总计功能  PHP与SQL实践:高效实现数据复制与特定列值修改  CSS如何控制元素外边距_margin实现布局间隔  《狐友》联系客服方法  如何在mysql中设计餐饮点餐系统_mysql点餐系统项目实战  怎么恢复删除的电脑文件_数据恢复软件使用教程  Windows Audio服务启动失败怎么办_电脑没声音的终极服务修复法【修复】  Symfony路由参数转换器:实体存在性验证与错误处理策略  鲁班大师乓乓皮肤获取方法  苹果手机缓存怎么清除_苹果手机缓存如何清除iphone各版本操作步骤  如何在CSS中使用伪类:valid实现表单验证提示_结合:valid改变边框颜色  12306APP选座怎么选充电位置_12306APP带充电插座座位选择方法与技巧  QQ网页版入口导航 QQ网页版在线访问通道  苹果手机聊天记录删除了如何恢复  《随手记》备份数据方法  苹果iPhone14ProMax如何新建AppleID_iPhone14ProMax新建AppleID具体流程  发博客与长微博技巧  秋风萧瑟洪波涌起中的萧瑟指的是什么  PHP页面重载时变量值不重置的实现方法  VBA Outlook邮件自动化:高效集成Excel数据与列标题的策略  《下一站江湖2》大雪山加入方法  被称为海蜈蚣的海洋动物是  《爱笔思画x》涂色教程 

 2025-10-27

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.