#javascript #reactjs #react-native #button #textinput
#javascript #reactjs #react-native #кнопка #textinput
Вопрос:
мой вопрос в том, можно ли установить время перезарядки на кнопку, которую нажимает пользователь, или регистрировать только 1 нажатие за 2 секунды. Я использую React Native (Expo), связанный с REST API и базой данных PostgreSQL.
Моя проблема в том, что у меня есть кнопка, которая отправляет данные в базу данных. При нажатии введенные значения помещаются в базу данных, и пользователь переходит на другой экран, где он может увидеть свою запись.
Я заметил, что когда пользователь достаточно быстр, он может нажать кнопку дважды или 3 раза, и поэтому данные также отправляются 2/3 раза в БД.
Мне понадобилось бы что-то вроде одной секунды перезарядки, чтобы данные публиковались только 1 раз, потому что навигация почти происходит немедленно!
Я ничего не мог найти в Интернете по этому поводу.
Спасибо ~ Исчезло
Комментарии:
1. Миллион способов сделать это — удалить
onPress
после нажатия кнопки, установить отключенное свойство после его нажатия и т. Д. И т. Д. Это похоже на старые времена Интернета: «пожалуйста, нажмите кнопку отправки только один раз»2. @Adam Я не могу удалить нажатие или отключить его, потому что, если пользователь снова войдет в экран, он, очевидно, захочет продолжать использовать форму и кнопку, как раньше, поэтому таймер перезарядки будет идеальным, например, 1 или 2 секунды, этого достаточно.
3. Это абсолютно неправильный способ сделать это — что, если PUT занимает больше времени, чем 1 или 2 секунды? На самом деле вы хотите отключить кнопку ДО завершения ввода.
4. что ж, возможно, вы правы, я мог бы либо показать счетчик в это время, либо отключить кнопку в начале функции и, возможно, включить ее в конце
Ответ №1:
Отключите кнопку, как только она нажата.
const MyComponent = ({makePutCall}) => {
const [disabled,setDisabled] = useState(false);
const doPut = async () => {
setDisabled(true);
await makePutCall();
setDisabled(false);
}
return <Button disabled={disabled} onPress={doPut}/>
}
или используйте ссылку, чтобы предотвратить нажатие более одного раза:
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}/>
}
или сделайте это другим способом — НЕ ИСПОЛЬЗУЙТЕ ТАЙМЕР.
Комментарии:
1. Да, я только что внедрил счетчик на кнопке — довольно просто, я думаю, и это эффективно!
Ответ №2:
На данный момент я могу придумать 2 решения, может быть и много других решений.
Решение 1. Имейте некоторую переменную, которая может сохранять значение, если вызов базы данных уже выполнен, как только вы получите ответ от базы данных, вы можете сбросить эту переменную, и пользователь может снова нажать эту кнопку.
Что-то вроде
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.
}
Вы также можете отключить кнопку, если эта переменная имеет значение true.
Решение 2: вы можете использовать throttle
из lodash
библиотеки.
Ответ №3:
попробуйте использовать debounce / throttle . вот простой пример debounce.
Import * as _ from lodash;
...
...
onPressDebounced = _.debounce(this.onPressed(),500);
render() {
return (
<TouchableHighlight
{ ...this.props }
onPress = { this.onPressDebounced}>
{this.props.children}
</TouchableHighlight>
)
}
Комментарии:
1. отключение / дросселирование — неправильный способ справиться с этим — есть известное время, когда кнопка должна быть повторно включена — когда ответ был возвращен с сервера.
2. @Адам Согласился! Но проблема должна остановить несколько кликов, и пользователь также перенаправляется на новый экран сразу после этого. Если бы случай был другим, чтобы дождаться ответа API, мы могли бы использовать простой async await для завершения задачи!