touchableopacity touchable react onpress disable react-native

touchable - React Native Prevent Double Tap



react navigation (6)

Tengo un TouchableHighlight envolviendo un bloque de texto que cuando se toca, abre una nueva escena (que estoy usando reaccionar-native-router-flux). Todo funciona bien, excepto por el hecho de que si tocas rápidamente el TouchableHighlight, la escena puede reproducirse dos veces. Me gustaría evitar que el usuario pueda pulsar rápidamente ese botón.

¿Cuál es la mejor manera de lograr esto en Native? Busqué en el Sistema de respuesta de gestos, pero no hay ejemplos ni nada por el estilo que, si eres nuevo, como yo, es confuso.


¿Quizás podría usar la nueva característica de inhabilitación introducida para elementos tangibles en 0.22? Estoy pensando algo como esto:

Componente

<TouchableHighlight ref = {component => this._touchable = component} onPress={() => this.yourMethod()}/>

Método

yourMethod() { var touchable = this._touchable; touchable.disabled = {true}; //what you actually want your TouchableHighlight to do }

No lo he probado yo mismo. Entonces no estoy seguro de si funciona.


Podría rebotar el clic en los métodos reales del receptor, especialmente si está tratando con el estado para efectos visuales.

_onRefresh() { if (this.state.refreshing) return this.setState({refreshing: true});


Lo siguiente funciona impidiendo el enrutamiento a la misma ruta dos veces:

import { StackNavigator, NavigationActions } from ''react-navigation''; const App = StackNavigator({ Home: { screen: HomeScreen }, Details: { screen: DetailsScreen }, }); // Prevents double taps navigating twice const navigateOnce = (getStateForAction) => (action, state) => { const { type, routeName } = action; return ( state && type === NavigationActions.NAVIGATE && routeName === state.routes[state.routes.length - 1].routeName ) ? state : getStateForAction(action, state); }; App.router.getStateForAction = navigateOnce(App.router.getStateForAction);


Solucioné este error creando un módulo que llama a una función solo una vez en el intervalo pasado.

Ejemplo: si desea navegar desde Inicio -> Acerca de Y presiona el botón Acerca de dos veces, digamos 400 ms.

navigateToAbout = () => dispatch(NavigationActions.navigate({routeName: ''About''})) const pressHandler = callOnce(navigateToAbout,400); <TouchableOpacity onPress={pressHandler}> ... </TouchableOpacity> The module will take care that it calls navigateToAbout only once in 400 ms.

Aquí está el enlace al módulo de NPM: https://www.npmjs.com/package/call-once-in-interval


yo uso así:

link(link) { if(!this.state.disabled) { this.setState({disabled: true}); // go link operation this.setState({disabled: false}); } } render() { return ( <TouchableHighlight onPress={() => this.link(''linkName'')}><Text>Go link</Text></TouchableHighlight> ); }


Lo que intenta hacer es limitar sus devoluciones de llamada, para que solo se ejecuten UNA VEZ.

Esto se conoce como aceleración, y puede usar underscore para eso: Aquí se muestra cómo:

_.throttle( this.thisWillRunOnce.bind(this), 200, // no new clicks within 200ms time window );

Así es como mi componente de reacción se ve después de todo.

class MyComponent extends React.Component { constructor(props) { super(props); _.throttle( this.onPressThrottledCb.bind(this), 200, // no new clicks within 200ms time window ); } onPressThrottledCb() { if (this.props.onPress) { this.props.onPress(); // this only runs once per 200 milliseconds } } render() { return ( <View> <TouchableOpacity onPress={this.onPressThrottledCb}> </TouchableOpacity> </View> ) } }

Espero que esto te ayude. En caso de que quiera obtener más información, consulte este hilo .