Как выполнить вызов ajax в стиле useEffect() после нажатия кнопки в React Native?

#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. Спасибо за ответ, этот ответ правильный.