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
。
按下按钮后立即将其禁用。
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>
)
}
我的问题是是否可以在用户按下的按钮上设置冷却时间,或者仅注册为 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
。
按下按钮后立即将其禁用。
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>
)
}