React Native 在 Button 上放一个 "Cooldown"

React Native put a "Cooldown" on a Button

我的问题是是否可以在用户按下的按钮上设置冷却时间,或者仅注册为 2 秒内按下 1 次。我正在使用与 REST API 和 PostgreSQL 数据库连接的 React Native (Expo)。

我的问题是我有一个将数据发送到数据库的按钮。 OnPress 输入的值被 PUT 到数据库,用户被导航到另一个屏幕,在那里他可以看到他的条目。

我注意到当用户速度足够快时,他可以按按钮两次或 3 次,因此数据也将 2/3 次发布到数据库。

我需要大约一秒的冷却时间,这样数据只发布 1 次,因为导航几乎是立即发生的!

我在互联网上找不到任何关于此的内容。

谢谢~Faded

目前我能想到的有2种解决方案,可能还有很多其他的解决方案。

解决方案一: 如果数据库调用已经完成,有一些变量可以保留一个值,一旦你从数据库获得响应,你可以重置该变量,用户可以再次按下该按钮。

类似

onPress = {this.state.isPressed ? null : <this.writeTodatabase>}

writeTodatabase = () => {
    this.setState({ isPressed:true })
    // code to write to database
    // once you have response from database you can set isPressed to false.
}

如果该变量为真,您也可以禁用按钮。

解决方案 2: 您可以使用 lodash 库中的 throttle

Reference Document

按下按钮后立即将其禁用。

const MyComponent = ({makePutCall}) => {
   const [disabled,setDisabled] = useState(false);

   const doPut = async () => {
       setDisabled(true);
       await makePutCall();
       setDisabled(false);
   }

   return <Button disabled={disabled} onPress={doPut}/>
 
}

或者使用 ref 来防止多次推送:

const MyComponent = ({makePutCall}) => {
   const disabled = useRef(false);

   const doPut = async () => {
       if(disabled.current) return;
       disabled.current = true;
       await makePutCall();
       disabled.current = false;
   }

   return <Button onPress={doPut}/>
 
}

我个人最喜欢的是旋转器,就像你说的:

const MyComponent = ({makePutCall}) => {
   const [showSpinner,setShowSpinner] = useState(false);

   const handlePress = async () => {
      setShowSpinner(true);
      await makePutCall();
      setShowSpinner(false);
   }

   return showSpinner ? <Spinner/> : <Button onPress={handlePress}/>
}

或者换一种方式——不要使用定时器。

尝试使用 debounce/throttle。这是去抖动的基本示例。

Import * as _ from lodash;
...
...

      
onPressDebounced = _.debounce(this.onPressed(),500);

render() { 
  return ( 
    <TouchableHighlight 
      { ...this.props } 
      onPress = { this.onPressDebounced}> 
      {this.props.children} 
    </TouchableHighlight>
  )
}