当前位置: 首页 > article >正文

React Native防止重复点击

项目中遇到了点击按钮重复提交的问题,防止重复点击首先是想到的是给点击事件一个定时,下次触发的条件是要距离上一次点击的时间大于N秒的之后才能再执行。

// 防重复点击函数
export const preventRepeatPress = {
	lastPressTi1me: 0,  	//  上次点击时间      
	repoTime: 2000,   		//  默认间隔时间2000  
	onPress(callback: () => void, waitTime: number = 2000) {
		let currTime = Date.now();
		if (currTime - this.lastPressTime > this.repoTime) {
			this.lastPressTime = currTime;
			this.repoTime = waitTime;         
			callback && callback();
		}
	},
};

在组件上的点击函数onPress中使用preventRepeatPress方法

<Button title="点击按钮" onPress={() => preventRepeatPress.onPress(() => fun())} /> 

在点击的时候可以传入设置间隔时间进行单独控制

() => preventRepeatPress.onPress(() => onCredit(),5000)

第二使用 setTimeout 函数

需要注意的是 timeout 需要放在全局也就是函数外部,否则的话每次调用 timeout 都会重新初始化导致防抖函数失去效果。

定义一个名为 debouncePlus 的函数,它接受一个函数 func,一个等待时间 wait(默认为 1000 毫秒)和一个 immediate 参数

// 定义一个变量 timeout,用于存储定时器的标识,变量作用域需要在函数外部
let timeout: string | number | NodeJS.Timeout | null | undefined = null;

export const debouncePlus = (
	func: { apply: (arg0: any, arg1: IArguments) => void; },
	wait: number | undefined = 1000,
	immediate: any
) => {
	// 变量 result,用于存储函数执行的结果
	let result: any;
	// 定义一个内部函数 debounced,它将作为防抖后的函数被返回
	let debounced = function (this: any) {
		// 获取当前函数执行的上下文(this 指向)
		let context = this;
		// 获取传递给当前函数的参数
		let args = arguments;

		// 如果定时器已经存在,清除之前的定时器
		if (timeout) clearTimeout(timeout);
		// 如果 immediate 为真
		if (immediate) {
			// 如果 timeout 为 null,说明是第一次调用,应该立即执行函数
			let callNow = !timeout;
			// 设置一个新的定时器,在等待时间之后将 timeout 置为 null
			timeout = setTimeout(function () {
				timeout = null;
			}, wait);
			// 如果应该立即执行,则调用原始函数,并将结果存储在 result 中
			if (callNow) result = func.apply(context, args);
		}
		// 如果 immediate 为假
		else {
			// 设置一个新的定时器,在等待时间之后执行原始函数
			timeout = setTimeout(function () {
				func.apply(context, args);
			}, wait);
		}
		// 返回函数执行的结果(如果是 immediate 模式,可能是立即执行的结果;否则可能是 null)
		return result;
	};

	// 给 debounced 函数添加一个 cancel 方法,用于取消正在等待执行的定时器
	debounced.cancel = function () {
		clearTimeout(timeout);
		timeout = null;
	};

	// 返回防抖后的函数
	return debounced;
};

第三使用 hook

/**
 * 防抖hook
 *   
 const { run } = useDebounceFn(
    () => {setValue(value + 1)},
    {wait: 500,},
  );
 */
import { useEffect, useMemo, useRef } from 'react';
import { debouncePlus } from './debounce-plus';

const isDev = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test';
const isFunction = (value: unknown): value is (...args: any) => any => typeof value === 'function';

interface DebounceOptions {
  wait?: number;
  leading?: boolean;
  trailing?: boolean;
  maxWait?: number;
}

type noop = (...args: any[]) => any;

function useDebounceFn<T extends noop>(fn: T, options?: DebounceOptions) {
  if (isDev) {
    if (!isFunction(fn)) {
      console.error(`useDebounceFn expected parameter is a function, got ${typeof fn}`);
    }
  }

  const fnRef = useLatest(fn);

  const wait = options?.wait ?? 1000;

  const debounced = useMemo(
    () =>
      debouncePlus(
        (...args: Parameters<T>): ReturnType<T> => {
          return fnRef.current(...args);
        },
        wait,
        options,
      ),
    [],
  );

  useUnmount(() => {
    debounced.cancel();
  });

  return {
    run: debounced,
    cancel: debounced.cancel,
    // flush: debounced.flush,
  };
}

export default useDebounceFn;


export const useUnmount = (fn: () => void) => {
  if (isDev) {
    if (!isFunction(fn)) {
      console.error(`useUnmount expected parameter is a function, got ${typeof fn}`);
    }
  }

  const fnRef = useLatest(fn);

  useEffect(
    () => () => {
      fnRef.current();
    },
    [],
  );
};

export function useLatest<T>(value: T) {
  const ref = useRef(value);
  ref.current = value;

  return ref;
}

有好的思路欢迎评论交流


http://www.kler.cn/a/308531.html

相关文章:

  • 什么是RAG? LangChain的RAG实践!
  • AI绘画经验(stable-diffusion)
  • 【Hadoop实训】Hive 数据操作①
  • AI写作(二)NLP:开启自然语言处理的奇妙之旅(2/10)
  • LabVIEW 实现 find_nearest_neighbors 功能(二维平面上的最近邻查找)
  • uni-app表单⑪
  • 详解 Pandas 的透视表函数
  • PHP智能化云端培训考试系统小程序源码
  • YOLOv5 Detect.py 改变检测框box线条的粗细,隐藏检测框的检测信息,只显示检测框box
  • PHP在现代Web开发中的高效应用与最佳实践
  • Linux杂项知识
  • 深入解析:如何通过网络命名空间跟踪单个进程的网络活动(C/C++代码实现)
  • Vue3.0组合式API:setup()函数
  • SpringBoot 消息队列RabbitMQ在代码中声明 交换机 与 队列使用注解创建
  • Linux | 进程间通信:管道、消息队列、共享内存与信号量
  • 快速排序
  • 《Oracle(一)- 基础》
  • 【webpack4系列】编写可维护的webpack构建配置(四)
  • COTERRORSET—— LLM训练新基准让模型从自身错误中学习
  • 情系河北 缘聚苏州——2024苏州河北同乡迎国庆贺中秋大团圆联谊活动圆满举办
  • 学习笔记缓存篇(一)
  • HarmonyOS使用LocationButton获取地理位置
  • GBase 8s数据类型与java.sql.Types对应关系
  • 初识网络原理
  • 前端基于Rust实现的Wasm进行图片压缩的技术文档
  • 中间件常见漏洞