Путаница с useState, useEffect и useRef в React - PullRequest
0 голосов
/ 21 октября 2019

Мое приложение - поиск рецептов. Форма поиска и кнопка отправки, а также результаты рецепта я получаю от API. У меня есть переменная состояния запроса (объявлена ​​с помощью useState ()), я пытаюсь обновить ее с помощью функции onSubmit в форме поиска. Итак, моя идея такова: кто-то что-то вводит в строку поиска и отправляет запрос. MY onSubmit принимает текущее значение и пытается установить запрос. Проблема в том, что мои запросы всегда задерживаются на 1 рендер. Запрос по умолчанию - «курица», поэтому, если я добавлю «какао» и нажму «Отправить», API выдаст мне результаты для курицы, а если я добавлю «морковь» после этого, теперь я получу результаты для «какао». Очевидно, я что-то упускаю, потому что мое состояние не успевает за изменениями.

И еще один дополнительный вопрос, если это произойдет, потому что я не вызываю функцию getRecipes в моем useEffect (вместо этого я простоговоря это). Если я его вызываю, я получаю ошибку:

Uncaught TypeError: destroy не является функцией и index.js: 1375 Предупреждение: не удается выполнить обновление состояния React на отключенном компьютересоставная часть. Это не работает, но это указывает на утечку памяти в вашем приложении. Чтобы исправить, отмените все подписки и асинхронные задачи в функции очистки useEffect.

мой код:

import React, { useEffect, useState, useRef } from "react";
import logo from "./logo.svg";
import Recipe from "./Recipe";
import "./App.css";

const App = () => {
  const APP_ID = "c49a2xxx";
  const APP_KEY = "0fbf56f642af60a29a73841f1fbdcxxx";
  const [recipes, setRecipes] = useState([]);
  //const [search, setSearch] = useState("");
  const [query, setQuery] = useState("chicken");
  const search = useRef();
  const exampleRequest = `https://api.edamam.com/search?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`;
  useEffect(() => getRecipes, []);
  useEffect(() => getRecipes, [query]);
  const getRecipes = async () => {
    const response = await fetch(exampleRequest);
    const data = await response.json();
    setRecipes(data.hits);
  };
  const submitSearch = (e) => {
    e.preventDefault();
    setQuery(search.current.value);
  };
  return (
    <div className="App">
      <form onSubmit={submitSearch}>
        <input type="text" ref={search} />
        <button type="submit">Search</button>
      </form>{" "}
      {recipes.map((recipe, key) => (
        <Recipe
          key={key}
          title={recipe.recipe.label}
          calories={recipe.recipe.calories}
          img={recipe.recipe.image}
        />
      ))}
    </div>
  );
};

export default App;

1 Ответ

1 голос
/ 21 октября 2019

Я думаю, что ошибка утечки памяти может быть вызвана двумя эффектами.

// Declared outside the component since it'll never change
const APP_ID = 'c49a2xxx';
const APP_KEY = '0fbf56f642af60a29a73841f1fbdcxxx';

const App = () => {
  const [recipes, setRecipes] = useState([]);
  const [query, setQuery] = useState('chicken');
  const search = useRef();

  // useEffect(() => getRecipes, []); You don't need two effects that does the same task
  useEffect(() => {
    const getRecipes = async () => {
      // request url with params declared inside the function
      // to make sure you're using the updated state variable
      const exampleRequest = `https://api.edamam.com/search?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`;
      const response = await fetch(exampleRequest);
      const data = await response.json();
      setRecipes(data.hits);
    };

    getRecipes();
  }, [query, APP_ID, APP_KEY]);

  const submitSearch = e => {
    e.preventDefault();
    setQuery(search.current.value);
  };

  return (
    <div className="App">
      <form onSubmit={submitSearch}>
        <input type="text" ref={search} />
        <button type="submit">Search</button>
      </form>
      {recipes.map((recipe, key) => (
        <Recipe
          key={key}
          title={recipe.recipe.label}
          calories={recipe.recipe.calories}
          img={recipe.recipe.image}
        />
      ))}
    </div>
  );
};

Если вы хотите узнать больше об отмене прерванных выборок, вот статья, которую я нашел полезной.

https://itnext.io/how-you-can-abort-fetch-request-on-a-flight-830a639b9b92

...