Javascript 防止在React native中双击
如何防止用户在React native中两次点击按钮 i、 e.用户不能在可触摸高光上快速点击两次使用属性Javascript 防止在React native中双击,javascript,react-native,touchablehighlight,Javascript,React Native,Touchablehighlight,如何防止用户在React native中两次点击按钮 i、 e.用户不能在可触摸高光上快速点击两次使用属性 import React,{Component}来自'React'; 从“react native”导入{AppRegistry、样式表、视图、按钮}; 导出默认类应用程序扩展组件{ 陈述={ 残疾人士:错,, } 按按钮(){ 这是我的国家({ 残疾人:对,, }); //5秒后启用 设置超时(()=>{ 这是我的国家({ 残疾人士:错,, }); }, 5000) } render(
import React,{Component}来自'React';
从“react native”导入{AppRegistry、样式表、视图、按钮};
导出默认类应用程序扩展组件{
陈述={
残疾人士:错,,
}
按按钮(){
这是我的国家({
残疾人:对,,
});
//5秒后启用
设置超时(()=>{
这是我的国家({
残疾人士:错,,
});
}, 5000)
}
render(){
返回(
单击此按钮。按按钮()}
title=“了解更多信息”
color=“#841584”
disabled={this.state.disabled}
accessibilityLabel=“了解有关此紫色按钮的详细信息”
/>
);
}
}
//如果使用CreateReact本机应用程序,请跳过此行
AppRegistry.registerComponent('AwesomeProject',()=>App)代码>
使用此HOC扩展可触摸组件,如TouchableHighlight、Button
import debounce from 'lodash.debounce'; // 4.0.8
const withPreventDoubleClick = (WrappedComponent) => {
class PreventDoubleClick extends React.PureComponent {
debouncedOnPress = () => {
this.props.onPress && this.props.onPress();
}
onPress = debounce(this.debouncedOnPress, 300, { leading: true, trailing: false });
render() {
return <WrappedComponent {...this.props} onPress={this.onPress} />;
}
}
PreventDoubleClick.displayName = `withPreventDoubleClick(${WrappedComponent.displayName ||WrappedComponent.name})`
return PreventDoubleClick;
}
从“lodash.debounce”导入去盎司;//4.0.8
const withPreventDoubleClick=(WrappedComponent)=>{
类防止双击扩展React.PureComponent{
debouncedOnPress=()=>{
this.props.onPress&&this.props.onPress();
}
onPress=debounce(this.debouncedOnPress,300,{前导:true,尾随:false});
render(){
返回;
}
}
PreventDoubleClick.displayName=`withPreventDoubleClick(${WrappedComponent.displayName | | WrappedComponent.name})`
返回双击;
}
用法
import { Button } from 'react-native';
import withPreventDoubleClick from './withPreventDoubleClick';
const ButtonEx = withPreventDoubleClick(Button);
<ButtonEx onPress={this.onButtonClick} title="Click here" />
从'react native'导入{Button};
使用PreventDoubleClick从“/使用PreventDoubleClick”导入;
const buttonnex=带防止双击(按钮);
您也可以在等待异步操作的同时显示正在加载的gif。只需确保用async()=>{}
标记您的onPress
,这样它就可以是wait
'd了
import React from 'react';
import {View, Button, ActivityIndicator} from 'react-native';
class Btn extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: false
}
}
async setIsLoading(isLoading) {
const p = new Promise((resolve) => {
this.setState({isLoading}, resolve);
});
return p;
}
render() {
const {onPress, ...p} = this.props;
if (this.state.isLoading) {
return <View style={{marginTop: 2, marginBottom: 2}}>
<ActivityIndicator
size="large"
/>
</View>;
}
return <Button
{...p}
onPress={async () => {
await this.setIsLoading(true);
await onPress();
await this.setIsLoading(false);
}}
/>
}
}
export default Btn;
从“React”导入React;
从“react native”导入{View,Button,ActivityIndicator};
类Btn扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
孤岛加载:false
}
}
异步设置isLoading(isLoading){
const p=新承诺((解决)=>{
this.setState({isLoading},resolve);
});
返回p;
}
render(){
const{onPress,…p}=this.props;
if(此.state.isLoading){
返回
;
}
返回{
等待此消息。setIsLoading(true);
等待按下按钮();
等待此消息。setIsLoading(false);
}}
/>
}
}
导出默认Btn;
我通过参考上面的答案来使用它。”“已禁用”不必是状态
import React, { Component } from 'react';
import { TouchableHighlight } from 'react-native';
class PreventDoubleTap extends Component {
disabled = false;
onPress = (...args) => {
if(this.disabled) return;
this.disabled = true;
setTimeout(()=>{
this.disabled = false;
}, 500);
this.props.onPress && this.props.onPress(...args);
}
}
export class ButtonHighLight extends PreventDoubleTap {
render() {
return (
<TouchableHighlight
{...this.props}
onPress={this.onPress}
underlayColor="#f7f7f7"
/>
);
}
}
import React,{Component}来自'React';
从“react native”导入{TouchableHighlight};
类扩展组件{
禁用=错误;
onPress=(…参数)=>{
如果(本.禁用)返回;
this.disabled=true;
设置超时(()=>{
this.disabled=false;
}, 500);
this.props.onPress&&this.props.onPress(…args);
}
}
导出类按钮高亮显示双击{
render(){
返回(
);
}
}
它可以是其他可触摸组件,如TouchableOpacity。如果使用react导航,则使用此格式导航到其他页面。
this.props.navigation.navigation({key:“any”,routeName:“YourRoute”,params:{param1:value,param2:value}})
StackNavigator将防止具有相同密钥的路由再次被推入堆栈。
如果要将参数传递到另一个屏幕,您可以编写任何唯一的键
,并且参数
属性是可选的。我有一个使用runAfterInteractions的非常简单的解决方案:
_GoCategoria(_categoria,_tipo){
if (loading === false){
loading = true;
this.props.navigation.navigate("Categoria", {categoria: _categoria, tipo: _tipo});
}
InteractionManager.runAfterInteractions(() => {
loading = false;
});
};
我的包装器组件的实现
import React, { useState, useEffect } from 'react';
import { TouchableHighlight } from 'react-native';
export default ButtonOneTap = ({ onPress, disabled, children, ...props }) => {
const [isDisabled, toggleDisable] = useState(disabled);
const [timerId, setTimerId] = useState(null);
useEffect(() => {
toggleDisable(disabled);
},[disabled]);
useEffect(() => {
return () => {
toggleDisable(disabled);
clearTimeout(timerId);
}
})
const handleOnPress = () => {
toggleDisable(true);
onPress();
setTimerId(setTimeout(() => {
toggleDisable(false)
}, 1000))
}
return (
<TouchableHighlight onPress={handleOnPress} {...props} disabled={isDisabled} >
{children}
</TouchableHighlight>
)
}
import React,{useState,useffect}来自“React”;
从“react native”导入{TouchableHighlight};
导出默认按钮nonetap=({onPress,disabled,children,…props})=>{
const[isDisabled,toggleDisable]=useState(disabled);
const[timerId,setTimerId]=useState(null);
useffect(()=>{
切换禁用(禁用);
},[残疾];
useffect(()=>{
return()=>{
切换禁用(禁用);
清除超时(timerId);
}
})
康斯特·汉德莱昂出版社=()=>{
切换禁用(true);
onPress();
setTimerId(setTimeout(()=>{
切换禁用(错误)
}, 1000))
}
返回(
{儿童}
)
}
同意公认的答案,但方法非常简单,我们可以使用以下方法
import debounce from 'lodash/debounce';
componentDidMount() {
this.onPressMethod= debounce(this.onPressMethod.bind(this), 500);
}
onPressMethod=()=> {
//what you actually want on button press
}
render() {
return (
<Button
onPress={() => this.onPressMethod()}
title="Your Button Name"
/>
);
}
从“lodash/debounce”导入去盎司;
componentDidMount(){
this.onPressMethod=debounce(this.onPressMethod.bind(this),500);
}
onPressMethod=()=>{
//按一下按钮你到底想要什么
}
render(){
返回(
this.onPressMethod()}
title=“您的按钮名称”
/>
);
}
公认的解决方案效果很好,但它强制您包装整个组件并导入lodash以实现所需的行为。
我编写了一个定制的React钩子,它只允许包装回调:
useTimeBlockedCallback.js
import { useRef } from 'react'
export default (callback, timeBlocked = 1000) => {
const isBlockedRef = useRef(false)
const unblockTimeout = useRef(false)
return (...callbackArgs) => {
if (!isBlockedRef.current) {
callback(...callbackArgs)
}
clearTimeout(unblockTimeout.current)
unblockTimeout.current = setTimeout(() => isBlockedRef.current = false, timeBlocked)
isBlockedRef.current = true
}
}
用法:
yourComponent.js
import React from 'react'
import { View, Text } from 'react-native'
import useTimeBlockedCallback from '../hooks/useTimeBlockedCallback'
export default () => {
const callbackWithNoArgs = useTimeBlockedCallback(() => {
console.log('Do stuff here, like opening a new scene for instance.')
})
const callbackWithArgs = useTimeBlockedCallback((text) => {
console.log(text + ' will be logged once every 1000ms tops')
})
return (
<View>
<Text onPress={callbackWithNoArgs}>Touch me without double tap</Text>
<Text onPress={() => callbackWithArgs('Hello world')}>Log hello world</Text>
</View>
)
}
从“React”导入React
从“react native”导入{View,Text}
从“../hooks/useTimeBlockedCallback”导入useTimeBlockedCallback
导出默认值()=>{
const callbackWithNoArgs=useTimeBlockedCallback(()=>{
log('在这里做一些事情,比如打开一个新场景')
})
const callbackWithArgs=useTimeBlockedCallback((文本)=>{
console.log(文本+'将每1000ms记录一次')
})
返回(
不要轻触我
callb