#javascript #reactjs #react-native
#javascript #reactjs #react-native
Вопрос:
-
У меня есть пользовательский компонент счетчика кнопок, который я создаю:
const ButtonSpinner = ({ onPress, title }) => { const { state } = useContext(AuthContext); const loading = state.loading; return ( <TouchableOpacity style={{ height: 20, width: 300, marginTop: 15, backgroundColor: "red" }} onPress={onPress} title={title} > {loading ? ( <ActivityIndicator size={"large"} color={"black"} /> ) : ( <Text>{title}</Text> )} </TouchableOpacity> ); };
экспортировать ButtonSpinner по умолчанию;
-
у меня есть индикатор состояния загрузки внутри контекста использования
const { state } = useContext(AuthContext);(//which work perfectlly)
-
так что нет, я вызываю buttonSpinner с асинхронной функцией следующим образом :
<ButtonSpinner onPress={() => signHandler(localSign, { loginPage, name, email, password, }) } title={"TITLE"} />
проблема: у меня есть несколько вызовов buttonspinnercomponent, и когда я нажимаю на одну кнопку, загрузчик ссылается на все компоненты «buttonspinner». ИЗОБРАЖЕНИЕ для повторного примера:
перед загрузкой
ВОПРОС: как я могу вызвать, чтобы показать загрузчик только в кнопке, которую я нажал, а не во всех моих кнопках.
Ответ №1:
Проблема в том, что вы используете свойство загрузки AuthContext только для отображения индикатора загрузки. Таким образом, загрузка всех ваших кнопок зависит от одного свойства. Вам нужно обработать свойство загрузки внутри кнопки таким образом, чтобы оно отображалось только при нажатии кнопки:
import React, { useContext, useEffect, useState } from 'react';
const ButtonSpinner = ({ onPress, title }) => {
const [localLoading, setLocalLoading] = useState(false);
const { state } = useContext(AuthContext);
const loading = state.loading;
useEffect(() => {
if (!loading) setLocalLoading(false);
}, [loading]);
const onButtonPress = () => {
setLocalLoading(true);
onPress();
}
return (
<TouchableOpacity
style={{ height: 20, width: 300, marginTop: 15, backgroundColor: "red" }}
onPress={onButtonPress}
title={title}
>
{(loading amp;amp; localLoading) ? (
<ActivityIndicator size={"large"} color={"black"} />
) : (
<Text>{title}</Text>
)}
</TouchableOpacity>
);
};
export default ButtonSpinner;
Редактировать:
Если вы хотите удалить AuthContext, а onPress не возвращает обещание, вы можете передать обратный onPress
вызов функции и обновить localLoading
состояние:
import React, { useContext, useEffect, useState } from 'react';
const ButtonSpinner = ({ onPress, title }) => {
const [localLoading, setLocalLoading] = useState(false);
const onButtonPress = () => {
setLocalLoading(true);
onPress(() => setLocalLoading(false));
}
return (
<TouchableOpacity
style={{ height: 20, width: 300, marginTop: 15, backgroundColor: "red" }}
onPress={onButtonPress}
title={title}
>
{localLoading ? (
<ActivityIndicator size={"large"} color={"black"} />
) : (
<Text>{title}</Text>
)}
</TouchableOpacity>
);
};
export default ButtonSpinner;
И ButtonSpinner:
const handlePress = async (cb) => {
await signHandler(localSign, {
loginPage,
name,
email,
password,
});
cb amp;amp; cb();
}
<ButtonSpinner
onPress={handlePress}
title={"TITLE"}
/>
Это будет работать в предположении, что signHandler
это обещание. Если это не обещание, используйте тот же метод и передайте cb
обработчику подписи и вызовите его, когда он будет завершен.
Комментарии:
1. Спасибо! сработало отлично, есть способ сделать это без контекста? я пробовал так: const onButtonPress = () => { setLocalLoading(true); onPress().затем(setLocalLoading(false)); }; и таким образом const onButtonPress = () => { setLocalLoading(true); onPress() (setLocalLoading(false)); }; но он не ожидает асинхронной функции.. итак, загрузчик не отображается
2. Вероятно, это не сработало, потому
onPress()
что не возвращает обещание. Я включу некоторый код в свой ответ по этому поводу3. большое вам спасибо! я остаюсь в вашем первом решении… кажется более читаемым! еще раз спасибо
4. Нет проблем 🙂 🙂