首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

使用.map呈现组件会在组件内重置setTimeout

基础概念

.map 是 JavaScript 中数组的一个方法,用于遍历数组并对每个元素执行指定的函数,返回一个新的数组。在 React 或其他前端框架中,.map 常用于渲染列表组件。

setTimeout 是 JavaScript 中的一个定时器函数,用于在指定的延迟时间后执行一段代码。

问题描述

在使用 .map 渲染组件时,如果在组件内部使用 setTimeout,可能会遇到定时器被重置的问题。这是因为每次组件重新渲染时,都会创建一个新的 setTimeout 实例,从而覆盖之前的定时器。

原因分析

  1. 组件重新渲染:当父组件的状态发生变化时,使用 .map 渲染的子组件会重新渲染。
  2. 定时器重置:每次重新渲染时,都会创建一个新的 setTimeout,导致之前的定时器被清除。

解决方案

方案一:使用 useRef 保存定时器 ID

useRef 是 React 提供的一个 Hook,用于保存可变的值,并且不会在组件重新渲染时丢失。

代码语言:txt
复制
import React, { useRef } from 'react';

const MyComponent = ({ items }) => {
  const timersRef = useRef({});

  const startTimer = (itemId) => {
    if (timersRef.current[itemId]) {
      clearTimeout(timersRef.current[itemId]);
    }
    timersRef.current[itemId] = setTimeout(() => {
      console.log(`Timer for item ${itemId} finished`);
    }, 1000);
  };

  return (
    <div>
      {items.map((item) => (
        <div key={item.id} onClick={() => startTimer(item.id)}>
          {item.name}
        </div>
      ))}
    </div>
  );
};

export default MyComponent;

方案二:使用 useEffect 管理定时器生命周期

useEffect 可以用来处理副作用,并且在组件卸载时清除定时器。

代码语言:txt
复制
import React, { useEffect } from 'react';

const MyComponent = ({ items }) => {
  useEffect(() => {
    const timers = {};

    const startTimer = (itemId) => {
      if (timers[itemId]) {
        clearTimeout(timers[itemId]);
      }
      timers[itemId] = setTimeout(() => {
        console.log(`Timer for item ${itemId} finished`);
      }, 1000);
    };

    items.forEach((item) => {
      startTimer(item.id);
    });

    return () => {
      Object.values(timers).forEach(clearTimeout);
    };
  }, [items]);

  return (
    <div>
      {items.map((item) => (
        <div key={item.id}>
          {item.name}
        </div>
      ))}
    </div>
  );
};

export default MyComponent;

应用场景

  • 列表渲染:当需要在列表项中设置定时器时,如轮播图、倒计时等。
  • 动态更新:当列表数据动态变化时,需要确保定时器不会被意外重置。

优势

  • 稳定性:通过 useRefuseEffect 管理定时器,可以避免因组件重新渲染导致的定时器重置问题。
  • 可维护性:代码结构清晰,易于理解和维护。

通过上述方法,可以有效解决在使用 .map 渲染组件时遇到的 setTimeout 重置问题。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

小程序内引入使用vant组件操作教程详解

Vant是一套由有赞技术团队精心打造的轻量可靠的移动组件库,包含了按钮、弹层等基础组件,单选、复选、输入框、选择器、评分等表单组件,提示框、折叠面板、轮播图等交互组件还包括了地址编辑、地址列表、商品卡品...、优惠券等电商常用模块,非常好用的一套组件库。...2.终端执行命令 npm init 执行该命令之后直接全部回车进行,成功后会在你的小程序端文件目录里生成一个package.json文件 ?...二、使用 使用非常简单,我们以Toast 轻提示为例 引入组件 在app.json中配置Toast路径 "usingComponents": { "van-toast": "@vant/weapp/...toast" } 2.使用组件 按照文档说明,这里需要配置两次,我们以/pages/zhai/zhai这个目录使用为例 a).zhai.wxml <van-toast id="van-toast"

3.7K20

使用 unplugin-vue-components 按需引入组件(内附实现原理)

我们开发 Vue 项目时,一般会使用组件库进行开发,组件库有两种加载方式:全局引入和按需引入 全局引入组件库,使用起来就非常方便,但是坏处就是产物体积大,对性能要求较高的项目不友好。...,能够让开发者就像全局组件那样进行开发,但实际上又是按需引入,且不限制打包工具,不需要使用 babel 使用效果 以 Antd Vue 和 vite 为例: import AutoImport from...,不需要手动 import 组件以及组件样式,使用起来就像全局组件一样,但这是按需自动引入,可以减少产物大小。...,通过使用对应 UI 组件库的解析器(resolvers),就能自动引入对应的组件库组件及样式。...', sideEffects: 'ant-design-vue/es/button/style/css', } 然后修改 Vue 编译后的代码(**unplugin-vue-components 会在

4.3K40
  • React-Hooks怎样封装防抖和节流-面试真题

    防抖函数,我们需要做的是在一件事触发的时候设置一个定时器使事件延迟发生,在定时器期间事件再次触发的话则清除重置定时器,直到定时器到时仍不被清除,事件才真正发生。...如果是class组件,新函数可以挂载到组件this上,但是函数式组件局部变量每次render都会创建,debounce失去作用,这时需要通过useRef来保存成员函数(下文throttle通过useRef...,可以将目标变量通过useDebounceHook转化一次,只有在满足delay的延迟之后,才会触发,在delay期间的触发都会重置计时。...---Throttlethrottle 原意节流阀,对于事件频繁触发的场景,采用的另一种降频策略,一个时间段内只能触发一次。...但是这里搜索框的例子并不好,对值变化之后发起的请求可以进行节流,但是因为搜索框需要实时呈现输入的内容,就需要实时的text值。

    50630

    React-Hooks怎样封装防抖和节流-面试真题

    防抖函数,我们需要做的是在一件事触发的时候设置一个定时器使事件延迟发生,在定时器期间事件再次触发的话则清除重置定时器,直到定时器到时仍不被清除,事件才真正发生。...如果是class组件,新函数可以挂载到组件this上,但是函数式组件局部变量每次render都会创建,debounce失去作用,这时需要通过useRef来保存成员函数(下文throttle通过useRef...,可以将目标变量通过useDebounceHook转化一次,只有在满足delay的延迟之后,才会触发,在delay期间的触发都会重置计时。...---Throttlethrottle 原意节流阀,对于事件频繁触发的场景,采用的另一种降频策略,一个时间段内只能触发一次。...但是这里搜索框的例子并不好,对值变化之后发起的请求可以进行节流,但是因为搜索框需要实时呈现输入的内容,就需要实时的text值。

    1.1K30

    【小家Spring】Spring环境中(含Boot环境),web组件(Servlet、Filter)内注入使用Spring容器里的Bean

    前言 在日常web开发中,我们经常会使用到Filter,这个组件最经典的使用场景就是鉴权。...组件的加载顺序应该是: ServletContext -> Listener -> Filter -> Servlet 由于Spring bean的初始化是在listener中声明的,因此Filter时...helloService); //null chain.doFilter(request, response); } 从输出的内容里可以看出,其实doFilter的时候,该Bean已经存在于该容器内了...时,都可以直接@Autowired注入Service了,因为Boot环境下,三大组件都是以Spring Bean的形式存在于容器内的~ 解决方案: 问题就来了,现在我的项目较老,就是传统的Spring环境...另外,有小伙伴说没有说在Spring Boot环境下的没有说明,其实这个看这篇博文就够了: 【小家Spring】SpringBoot中使用Servlet、Filter、Listener三大组件的三种方式以及原理剖析

    2.5K21

    腾讯原生小程序框架 OMIX 2.0 发布

    store 和 data,页面和页面所有组件可以拿到, 操作 data 会自动更新视图 不需要注入 store 的页面或组件用使用Page和Component 构造器, Component 通过 triggerEvent...{{log}} 定义 test-store 组件, 组件内也可以组件使用全局的 logs,组件源码: import create from '../..../utils/create' create({ use: ['map'] }) map 代表依赖 store.data.map,map 更新会自动更新视图。...this.paused) { //核心循环逻辑 this.tick() } } }, 16) 用法和 setInterval 一致,只是内部使用 setTimeout...,可能在很多页面使用,也可能在同一个页面使用多次;如果使用store来作为组件间通信的话,怎么应用可以实现组件是纯组件而不跟业务相关呢A: 纯组件不用不用 create 创建,且该组件内使用 triggerEvent

    2.3K63

    React 中高阶函数与高阶组件(上)

    函数可以被作为参数传递 如下:经常用到的setTimeout,setInterval setTimeout(function() { console.log('itclanCoder'); },...false; }, duration); }; } 函数节流保证一段时间内只执行一次核心代码,连续每隔一定的时间触发执行的函数 上面使用的是重置一个开关变量+定时器的方式实现函数节流 函数防抖应用...在components中创建一个highcomponent,同时在该文件夹内创建ComponentA.js,ComponentB.js,ComponentC.js 组件 A 公共组件 import React..., mapDispatchToProps)(Header); 05 高阶组件的实现 ⒈ 如何编写高阶组件 ⒉ 如何使用高阶组件 ⒊ 如在高阶组件中实现传递参数 如何编写高阶组件 ⒈ 实现一个普通组件...使用高阶组件,还有另外一种方式,就是使用装饰器方式,即@+函数名,它是一个语法糖,简化了我们的写法 方式 1-安装 babel 插件在 babelrc 中配置 在使用这种装饰器方式时,需要对create-react-app

    2K10

    1000个项目中前10名的JavaScript错误介绍

    发生这种情况的原因很多,但常见的一种是在渲染 UI 组件时对于状态的初始化操作不当。...当异步获取数据时,不管它是在构造函数componentWillMount还是componentDidMount中获取的,组件在数据加载之前至少会呈现一次,当 Quiz 第一次呈现时,this.state.items...在这个例子中,我们可以通过添加一个事件监听器来解决这个问题,这个监听器会在页面准备好的时候通知我们。 一旦 addEventListener被触发,init() 方法就可以使用 DOM 元素。...你得到上述错误的原因是,当你调用setTimeout()时,实际上是调用window.setTimeout()。...this.timer = setTimeout(function(){ self.clearBoard(); }, 0); }; 或者,在较新的浏览器中,可以使用bind

    6.2K10

    10 种最常见的 Javascript 错误

    发生这种情况的原因很多,但常见的一种是在渲染 UI 组件时对于状态的初始化操作不当。...当异步获取数据时,不管它是在构造函数componentWillMount还是componentDidMount中获取的,组件在数据加载之前至少会呈现一次,当 Quiz 第一次呈现时,this.state.items...在这个例子中,我们可以通过添加一个事件监听器来解决这个问题,这个监听器会在页面准备好的时候通知我们。 一旦 addEventListener被触发,init() 方法就可以使用 DOM 元素。...你得到上述错误的原因是,当你调用setTimeout()时,实际上是调用window.setTimeout()。...this.timer = setTimeout(function(){ self.clearBoard(); }, 0); }; 或者,在较新的浏览器中,可以使用bind()方法传递适当的引用

    6.8K80

    【React】417- React中componentWillReceiveProps的替代升级方案

    componentWillReceiveProps 1.介绍 componentWillReceiveProps是React生命周期函数之一,在初始props不会被调用,它会在组件接受到新的props时调用...2.使用 static getDerivedStateFromProps(nextProps,prevState){ //该方法内禁止访问this if(nextProps.email...3.常见误区 当我们在子组件内使用该方法来判断新props和state时,可能会引起内部更新无效。...并且如果组件具有很多更新上的逻辑,使用key甚至可以更快,因为该子树的diff得以被绕过。 3.通过唯一属性值重置非受控组件。...因为使用key值我们会重置子组件所有状态,当我们需要仅重置某些字段时或者子组件初始化代价很大时,可以通过判断唯一属性是否更改来保证重置组件内部状态的灵活性。 4.使用实例方法重置非受控组件。

    2.9K10

    useLayoutEffect的秘密

    因为,这些概念在下面文章中会有出现,为了让行文更加的顺畅,所以将本该在文内的概念解释放到前面来。...如果,容器不能容纳这些组件,那么它会在容器的右侧显示一个“更多”按钮,点击后会显示一个下拉菜单,其中包含剩余未展示的子项目 让我们先从简单的逻辑入手,先创建一个简单的导航组件,它将呈现一个链接列表:(直接遍历...*/} {filteredItems.map(item => {item.name})} {/* 有条件地呈现“更多” */}...与setTimeout内的边框情况完全相同。 所以回答我们一开始的问题。使用 useLayoutEffect它会影响性能!我们最不希望的是我们整个 React 应用程序变成一个巨大的同步任务。...在 Next.js 和其他 SSR 框架中使用 useLayoutEffect 当我们将使用useLayoutEffect处理过的自适应导航组件写入到任何一个SSR框架时,你会发现它还是会产生闪烁现象。

    29110

    关于React18更新的几个新功能,你需要了解下

    它还可以防止你的组件呈现仅更新一个状态变量的“半完成”状态,这可能会导致错误。 这可能会让你想起餐厅服务员在你选择第一道菜时不会跑到厨房,而是等你完成订单。 然而,React 的批量更新时间并不一致。...这意味着超时、承诺、本机事件处理程序或任何其他事件内的更新将以与 React 事件内的更新相同的方式进行批处理。...React 将在稍后处理更新时使用此信息来决定如何呈现更新。这意味着我们比在超时中包装更新更早地开始呈现更新。 在快速设备上,两次更新之间的延迟非常小。...另一个重要的区别是 a 内的大屏幕更新setTimeout仍然会锁定页面,只是在超时之后。 如果用户在超时触发时仍在键入或与页面交互,他们仍将被阻止与页面交互。...它们让浏览器在呈现不同组件之间的小间隙中处理事件。 如果用户输入发生变化,React 将不必继续渲染用户不再感兴趣的内容。

    5.5K30

    React的操作系统梦,任重道远

    高优先级意味着该更新对DOM产生的影响会更快呈现在用户面前。...let externalSource = 1; setTimeout(() => { externalSource = 2; }, 1000) 我们有个组件A,他渲染的DOM依赖于externalSource...的值: function A() { return {externalSource}; } 在当前版本的React中,在我们的应用中组件树的不同地方使用A组件,会出现某些地方的DOM...因为当前React的如下运行流程是同步的: 状态更新 --> render --> 视图渲染 使externalSource变为2的setTimeout会在这个流程对应的task(宏认为)执行完后再执行...这样可能不同的A组件渲染出的p标签内的数字不一样。 这种由于React运行流程变化,导致依赖外部资源时,状态与视图不一致的现象,就是tearing。

    59710

    关于React18更新的几个新功能,你需要了解下

    它还可以防止你的组件呈现仅更新一个状态变量的“半完成”状态,这可能会导致错误。 这可能会让你想起餐厅服务员在你选择第一道菜时不会跑到厨房,而是等你完成订单。 然而,React 的批量更新时间并不一致。...这意味着超时、承诺、本机事件处理程序或任何其他事件内的更新将以与 React 事件内的更新相同的方式进行批处理。...React 将在稍后处理更新时使用此信息来决定如何呈现更新。这意味着我们比在超时中包装更新更早地开始呈现更新。 在快速设备上,两次更新之间的延迟非常小。...另一个重要的区别是 a 内的大屏幕更新setTimeout仍然会锁定页面,只是在超时之后。 如果用户在超时触发时仍在键入或与页面交互,他们仍将被阻止与页面交互。...它们让浏览器在呈现不同组件之间的小间隙中处理事件。 如果用户输入发生变化,React 将不必继续渲染用户不再感兴趣的内容。

    5.9K50

    React基础(7)-React中的事件处理

    bind直接的绑定,每次渲染组件,都会创建一个新的函数,一般而言,这种写法也没什么问题,但是如果该回调函数作为prop值传入子组件时,这些组件就会进行额外的重新渲染,会影响性能,这与使用箭头函数同样存在这样的问题...,React的事件对象会被作为第二个参数传递,而且也必须显示的传递进去 而通过bind的方式,事件对象以及更多的参数将会被隐式的传递进去 在render函数中直接的通过bind方法的绑定,会在每次组件渲染时都会创建一个新的函数...这样就可以保证500毫秒秒内函数只会被触发一次,达到了函数节流的目的 clearTimeout(timer); timer = setTimeout(function(){...,增加服务器的压力,使用防抖后,会在用户输入要查询的关键词后才发送请求,百度搜索就是这么实现的 * * */ function debounce(method, duration) { var timer...,增加服务器的压力 * 使用防抖后,会在用户输入要查询的关键词后才发送请求,百度搜索就是这么实现的 */ function debounce(method, duration) { var timer

    8.4K41

    Vue源码阅读 - 批量异步更新与nextTick原理

    map用来检查是否当前watcher的id是否存在,若已存在则跳过,不存在则就push到 queue 队列中并标记哈希表has,用于下次检验,防止重复添加。...waiting 会被置回 false 允许 flushSchedulerQueue 被传递给下一个tick的回调,总之保证了 flushSchedulerQueue 回调在一个tick内只允许被传入一次...我们看到在首先有个 queue.sort() 方法把队列中的watcher按id从小到大排了个序,这样做可以保证: 组件更新的顺序是从父组件到子组件的顺序,因为父组件总是比子组件先创建。...setTimeout ; 为什么优先使用 setImmediate 与 MessageChannel 而不直接使用 setTimeout 呢,是因为HTML5规定setTimeout执行的最小延时为...macroTimerFunc、microTimerFunc 方法前被置为 true,因此下次调用 nextTick 就不会进入 macroTimerFunc、microTimerFunc 方法,这两个方法中会在下一个

    1.1K30

    React学习(七)-React中的事件处理

    bind直接的绑定,每次渲染组件,都会创建一个新的函数,一般而言,这种写法也没什么问题,但是如果该回调函数作为prop值传入子组件时,这些组件就会进行额外的重新渲染,会影响性能,这与使用箭头函数同样存在这样的问题...,React的事件对象会被作为第二个参数传递,而且也必须显示的传递进去 而通过bind的方式,事件对象以及更多的参数将会被隐式的传递进去 在render函数中直接的通过bind方法的绑定,会在每次组件渲染时都会创建一个新的函数...这样就可以保证500毫秒秒内函数只会被触发一次,达到了函数节流的目的 clearTimeout(timer); timer = setTimeout(function(){...,增加服务器的压力,使用防抖后,会在用户输入要查询的关键词后才发送请求,百度搜索就是这么实现的 * * */ function debounce(method, duration) { var...,增加服务器的压力 * 使用防抖后,会在用户输入要查询的关键词后才发送请求,百度搜索就是这么实现的 */ function debounce(method, duration) { var timer

    7.4K40
    领券