Ich bin sicher, es ist ein sehr einfaches Problem, aber ich habe so viele verschiedene Dinge ausprobiert und ich mache es nur noch schlimmer. Ich baue eine Ernährungs-App mit Gesamtkalorien. Es soll die Gesamtkalorien basierend auf den Kalorien aus dem API-Aufruf berechnen und funktioniert nach dem zweiten Mal hervorragend. Aber das erste Mal zeigt es 0

Nährstoffkomponente

const [search, setSearch] = useState("");
  const [isLoaded, setIsLoaded] = useState(false);
  const [foodId, setFoodId] = useState("");
  const [foodList, setFoodList] = useState([]);
  const [totalCal, setTotalCal] = useState(0);

  const addCal = (cal, totalCal) => {
    const total = cal + totalCal;
    setTotalCal(total);
  };

  // Getting user input for an argument to be used later in API call
  const getInput = e => {
    e.preventDefault();
    setSearch(e.target.value);
  };

  // Submitting user input / starting API call / setting food to be searched
  const handleSubmit = e => {
    e.preventDefault();
    setIsLoaded(true);
    // console.log(list);
  };

  // Function that holds API call using form input
  const getNutrition = food => {
    const appId = "e124e5bc";
    const appKey = "fd3e0319818416b4e8496e3502bcb565";
    fetch(
      `https://api.nutritionix.com/v1_1/search/${food}?&appId=${appId}&appKey=${appKey}`
    )
      .then(response => {
        return response.json();
      })
      .then(responseData => {
        let foodId = responseData.hits[0].fields.item_id;
        fetch(
          `https://api.nutritionix.com/v1_1/item?id=${foodId}&appId=${appId}&appKey=${appKey}`
        )
          .then(response => {
            return response.json();
          })
          .then(responseData => {
            setFoodId(foodId);
            const foodObject = {
              calories: responseData.nf_calories,
              protein: responseData.nf_protein,
              food: responseData.item_name,
              key: foodId,
              totalCal: totalCal
            };
            addCal(foodObject.calories, totalCal);
            setFoodList([...foodList, foodObject]);
            setIsLoaded(false);
          });
      });
    console.log(isLoaded);
  };

  // Calling nutrition function that holds API
  useEffect(() => {
    if (isLoaded) {
      getNutrition(search);
      setFoodId(foodId);
    }
    // eslint-disable-next-line
  }, [isLoaded]);

  return (
    <div className={styles.nutritionContainer}>
      <FoodForm submit={handleSubmit} input={getInput} />
      <table className={styles.center}>
        <thead>
          <tr>
            <th>Food Item</th>
            <th>Calories</th>
            <th>Protein</th>
            <th>Total Calories</th>
            <th>Total Protein</th>
          </tr>
        </thead>
        <tbody>
          <TableList foodList={foodList} />
        </tbody>
      </table>
    </div>
  );
};

export default Nutrition;


Liste mit dynamischen Tabellendaten aus dem API-Aufruf in Nutrition Component

const TableList = ({ foodList }) => {
  return foodList.map(item => (
    <tr key={item.key}>
      <td>{item.food}</td>
      <td>{item.calories}</td>
      <td>{item.protein}</td>
      <td>{item.totalCal}</td>
    </tr>
  ));
};

export default TableList;
0
Austin Lee 23 Feb. 2020 im 01:03

3 Antworten

Beste Antwort

Ich denke, Ihr Code hat ein kleines Problem damit, denselben Variablennamen wiederzuverwenden und den folgenden Code zu überprüfen, den ich behoben habe. Wenn Sie standardmäßig den Wert isLoaded verwenden, fügen Sie standardmäßig einen Suchwert zu etwas hinzu.

Ich hoffe es wird geholfen. Aber im Moment ist Ihr API-Limit vorbei, weil ich es viel getestet habe. : P.

FIX 1

useEffect(() => {
if (isLoaded) {
  getNutrition(search);
}}, [isLoaded]);

FIX 2

const getNutrition (food)=> {
 const appId = "e124e5bc";
 const appKey = "fd3e0319818416b4e8496e3502bcb565";
 fetch(
  `https://api.nutritionix.com/v1_1/search/${food}?&appId=${appId}&appKey=${appKey}`
 )
  .then(response => {
    return response.json();
  })
  .then(responseData => {
    let fId = responseData.hits[0].fields.item_id;
    setFoodId(fId);

    fetch(
      `https://api.nutritionix.com/v1_1/item?id=${fId}&appId=${appId}&appKey=${appKey}`
    )
      .then(response => {
        return response.json();
      })
      .then(responseData => {
        console.log("DATA", responseData);
        const foodObject = {
          calories: responseData.nf_calories,
          protein: responseData.nf_protein,
          food: responseData.item_name,
          key: foodId,
          totalCal: totalCal
        };
        addCal(foodObject.calories);
        setFoodList([...foodList, foodObject]);
        setIsLoaded(false);
      });
  });
console.log(isLoaded);};

FIX 3

const addCal = cal => {
const total = cal + totalCal;
setTotalCal(total);};
0
Ko Nyan 23 Feb. 2020 im 20:31

Ich kann nicht mit Sicherheit sagen, warum Ihr erster API-Anruf nicht funktioniert, aber ich habe ein paar Vorschläge für die nächtliche Hilfe.

Zunächst einmal würde ich den useEffect-Hook überhaupt nicht verwenden. Dies kompliziert Ihren Code unnötig. Sie müssen die API nur jedes Mal aufrufen, wenn das Formular gesendet wird. Warum also nicht einfach dann? Anstatt den geladenen Wert usw. zu ändern, stellen Sie möglicherweise fest, dass Ihr Fehler behoben ist, oder es ist zumindest einfacher zu verstehen, was in Ihrem Code passiert.

Das andere, was ich tun würde, ist totalCals aus dem Status zu entfernen. Stattdessen würde ich es jedes Mal berechnen, es sei denn, Sie haben Tausende oder Hunderte von Tonnen von Gegenständen, es wird wirklich kein Leistungsproblem sein. Dies hat den Vorteil, dass Ihr Code leichter zu verstehen ist. Wenn Sie sagten, dass das Problem darin bestand, dass die Kalorien nicht aktualisiert wurden, sollte dies behoben werden. Es bedeutet auch, dass Ihr Zustand nicht denormalisiert ist. Wenn Sie es jedes Mal berechnen und dann ein Element aus dem Array entfernen, müssen Sie sich keine Gedanken über das Vergessen machen, um auch die Gesamtsumme usw. zu reduzieren.

Viel Glück!!

0
Michael Knight 23 Feb. 2020 im 18:14

Da isLoaded anfänglich auf false gesetzt ist und daher getNutrition(search); setFoodId(foodId); in useEffect nicht aufruft

0
Sipex 22 Feb. 2020 im 22:53