#react-native #expo #use-effect #react-native-button
Вопрос:
Я новичок в том, чтобы Реагировать и реагировать по-родному. Попытка создать простое приложение, которое выполняет вызов API по нажатию кнопки.
Мой код ниже работает, но просто «не выглядит правильно» для меня. useEffect() запускается после загрузки страницы? Похоже, выполняется несколько раз. Я считаю щелчки по кнопкам как истинные, а затем у меня есть оператор if внутри useefect. Означает ли это, что приложение постоянно проверяет, нажата ли кнопка?
Я попытался поместить useEffect() в функцию getJoke (), но react native это не понравилось. «Неверный вызов на крючок. Крючки могут вызываться только внутри тела функционального компонента.»
Если я помещу getJoke() внутри useEffect (), он постоянно вызывает api. Я получаю ответ api после ответа после ответа.
Я просто хочу, чтобы одно нажатие кнопки привело к одному вызову API, а текст под кнопкой обновлялся, как в AJAX, если бы это была веб-страница.
import { StatusBar } from 'expo-status-bar';
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View, Button} from 'react-native';
export default function App() {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState();
const [ error, setError ] = useState(false);
const [buttonPress, setButtonPress] = useState(false);
const getJoke = async () => {
try {
const response = await fetch('https://api.chucknorris.io/jokes/random');
const json = await response.json();
console.log(json);
console.log('Joke: ' json.value);
setData(json.value); // Chuck API provides joke in "value" field. Only saving the joke.
// Unfortunately you can't call hooks useEffect from here?
} catch (error) {
console.error(error);
setError(true);
} finally {
setLoading(false);
}
}
// Constant api calls if I do this
/*
useEffect(() => {
getJoke();
});
*/
useEffect(() => {
// Check if button has been pressed, if so update the page
if(buttonPress){
getJoke();
setButtonPress(false);
}
});
return (
<View style={{ flex: 1, padding: 24 }}>
<Text>Press button to get a random joke:</Text>
<Button title="Joke" onPress={setButtonPress}/>
<Text>{data}</Text>
</View>
);
}
Комментарии:
1. Это не лучший вариант использования эффектов. Загрузка при нажатии кнопки-это то, что вы могли бы сделать с обычными старыми функциями. Но приведенные ниже ответы касаются того, что может произойти, если вы все равно попытаетесь. Предполагается, что эффекты автоматически реагируют на изменения в вашей среде состояний (либо переданные свойства, либо локальные состояния состояния использования).
Ответ №1:
выполняется после каждой отрисовки
useEffect(() => {
// Runs after EVERY rendering
});
выполняется один раз после начальной отрисовки.
useEffect(() => {
// Runs ONCE after initial rendering
}, []);
выполняется только при изменении любого значения зависимости.
useEffect(() => {
// Runs ONCE after initial rendering
// and after every rendering ONLY IF `prop` or `state` changes
}, [prop, state]);
Итак, я думаю, вам следует поступить вот так
useEffect(() => {
// Check if button has been pressed, if so update the page
if(buttonPress){
getJoke();
setButtonPress(false);
}
}, [buttonPress]);
И причина недопустимого вызова крючка в том, что существует несколько правил.
Не вызывайте хуки внутри циклов, условий или вложенных функций
Комментарии:
1. Спасибо, я ценю подробное объяснение. Да, «крючки» в react немного сбивали меня с толку.
Ответ №2:
Удалите весь свой useEffect
блок и замените useEffect
его следующим
useEffect(() => {
// Check if button has been pressed, if so update the page
if(buttonPress){
getJoke();
setButtonPress(false);
}
}, [buttonPress]);
В принципе, как useEffect
работает то, что, вводя второй параметр, мы говорим, что запускаемся useEffect
только тогда, когда значение buttonPress
изменилось.
Комментарии:
1. Спасибо за ответ, этот ответ правильный.