我正在用react-navigation-4.2.1构建一个应用。这个应用有多个堆栈导航器。所以有很多navigation.push('Routename')调用。问题是当控制面(即TouchableOpacity)被快速点击多次(第一次,其余的在屏幕转换过程中)我最终将多个屏幕推送到堆栈中。是否有办法将表面限制为第一次点击/调用push()?
navigation.push('Routename')
webghufk1#
下面的组件是我用来让东西可以触摸的。它可以在很短的时间内处理多个触摸。
TouchableOpacity
<SafeTouch onPress={...} > <Text> hey! im a touchable text now</Text> </SafeTouch>
TypeScirpt
import * as React from 'react' import { TouchableOpacity } from 'react-native' interface ISafeTouchProps { onPress: () => void onLongPress?: () => void onPressIn?: () => void onPressOut?: () => void, activeOpacity?: number, disabled?: boolean, style: any } export class SafeTouch extends React.PureComponent<ISafeTouchProps> { public static defaultProps: ISafeTouchProps = { onPress: () => { }, onLongPress: () => { }, onPressIn: () => { }, onPressOut: () => { }, disabled: false, style: null } private isTouchValid: boolean = true private touchTimeout: any = null public constructor(props: ISafeTouchProps) { super(props) {// Binding methods this.onPressEvent = this.onPressEvent.bind(this) } } public render(): JSX.Element { return ( <TouchableOpacity onPress={this.onPressEvent} onLongPress={this.props.onLongPress} onPressIn={this.props.onPressIn} onPressOut={this.props.onPressOut} activeOpacity={this.props.activeOpacity} disabled={this.props.disabled} style={[{minWidth: 24, minHeight: 24}, this.props.style]} > { this.props.children } </TouchableOpacity> ) } public componentWillUnmount() { this.clearTimeoutIfExists() } private onPressEvent(): void { requestAnimationFrame(() => { if (this.isTouchValid === false) { return } this.isTouchValid = false this.clearTimeoutIfExists() this.touchTimeout = setTimeout(() => { this.isTouchValid = true }, 300) if (typeof this.props.onPress === 'function') { this.props.onPress() } }) } private clearTimeoutIfExists(): void { if (this.touchTimeout != null) { clearTimeout(this.touchTimeout) this.touchTimeout = null } } }
khbbv19g2#
这是Push的正确行为,如果您想避免双选项卡上的重复屏幕,可以使用navigation.navigate。
ldioqlga3#
为了避免在短时间内点击同一个按钮时多次按下屏幕,我创建了一个通用钩子来避免多次运行一个函数(接受一个允许再次运行的间隔):
export const useCallOnce = <T extends unknown[], K>( fn: (...args: T) => K, allowAfter?: number, ) => { const ref = React.useRef<number | undefined>(); const resultFn = (...args: T) => { const now = new Date().getTime(); if (!ref.current || (allowAfter && ref.current + allowAfter < now)) { ref.current = now; return fn(...args); } }; return resultFn; };
然后,您可以像下面的示例那样调用它:
const navigation = useNavigation<NativeStackNavigationProp<{ ExampleScreen: undefined }>>(); const push = useCallOnce(() => navigation.push('ExampleScreen'), 500); // just call on the button click event as: onSomeEvent={() => push()}
您可以创建一个通用按钮组件,它接受带有钩子的push参数(类似于上面的示例),并在希望按钮在页面之间导航时使用此按钮。
3条答案
按热度按时间webghufk1#
下面的组件是我用来让东西可以触摸的。它可以在很短的时间内处理多个触摸。
TouchableOpacity
。用这个组件 Package 你想要的任何东西,它将是可触摸的。TypeScirpt
编写。khbbv19g2#
这是Push的正确行为,如果您想避免双选项卡上的重复屏幕,可以使用navigation.navigate。
ldioqlga3#
为了避免在短时间内点击同一个按钮时多次按下屏幕,我创建了一个通用钩子来避免多次运行一个函数(接受一个允许再次运行的间隔):
然后,您可以像下面的示例那样调用它:
您可以创建一个通用按钮组件,它接受带有钩子的push参数(类似于上面的示例),并在希望按钮在页面之间导航时使用此按钮。