Хук React useState не работает при отправке формы

Я новичок в React, и у меня есть некоторые сомнения относительно хука useState. Недавно я работал над приложением для реагирования на рецепты на основе API. Проблема, с которой я сталкиваюсь, заключается в том, что когда я отправляю что-то в форму поиска, должно произойти изменение состояния, но состояние не меняется но если я повторно отправлю форму, состояние изменится.

   import React,{useState,useEffect} from "react";
   import Form from "./componnents/form";
   import RecipeBlock from "./componnents/recipeblock"
   import './App.css';


   function App() {


     const API_id=process.env.REACT_APP_MY_API_ID;
     const API_key=process.env.REACT_APP_MY_API_KEY;
     const [query,setQuery]=useState("chicken");

    const path=`https://api.edamam.com/search?q=${query}&app_id=${API_id}&app_key=${API_key}`


    const [recipe,setRecipe]=useState([]);

  useEffect(() => {
  console.log("use effect is running")
  getRecipe(query);
  

  }, []);

function search(queryString){

 setQuery(queryString);

 getRecipe();

 }

  async function getRecipe(){
    const response=await fetch(path);
    const data=await response.json();

    setRecipe(data.hits);
    console.log(data.hits);

}

queryString в функции search () содержит значение ввода формы. Каждый раз, когда я отправляю форму, это значение поступает правильно, но setQuery (queryString) не меняет значение или состояние запроса, и если я повторно отправлю форму, он изменит состояние.


person pawan gogoi    schedule 27.11.2020    source источник


Ответы (2)


Код, который вы что-то предоставили, не имеет смысла.

useEffect(() => {
  console.log("use effect is running")
  getRecipe(query);
  

  }, []);

Ваш getRecipe не принимает переменную. Но из того, что я понимаю, всякий раз, когда вы выполняете поиск, вы хотите установить запрос, а затем получить рецепт из этого запроса.

С помощью useEffect вы можете передать параметры, чтобы проверить, изменились ли они перед запуском функции. Поэтому обновите setQuery, и тогда, когда компонент перезагрузится, он запустит useEffect, если запрос изменился. Вот код для объяснения:

  useEffect(() => {
  console.log("use effect is running")
  getRecipe(query);    <-- this doesn't make sense on your code 
  

  }, [query]);

function search(queryString){

 setQuery(queryString);
 }

Делая это, когда состояние обновляется, это вызывает повторный рендеринг компонента, и поэтому, если запрос изменился, он вызовет вашу функцию getRecipe.

person Zodsmar    schedule 27.11.2020
comment
Спасибо. Я забыл обновить функцию getRecipe () - person pawan gogoi; 28.11.2020
comment
Не беспокойтесь, если бы вы могли проголосовать за и принять ответ, который был бы очень признателен - person Zodsmar; 28.11.2020

Основная проблема в вашем коде заключается в том, что вы запускаете getRecipe() сразу после setQuery(queryString). setQuery(queryString) является асинхронным и будет ставить в очередь изменение состояния. Когда вы затем запустите getRecipe() сразу после этого, состояние по-прежнему будет содержать старое значение querypath) и, следовательно, не будет правильно получать новые данные.

Одно из решений - вызвать getRecipe() в useEffect(), зависящем от path.

useEffect(() => {
  getRecipe();
}, [path]);

function search(queryString){
  setQuery(queryString);
  // getRecipe() <- removed
}

Если [path] задано как зависимости для useEffect(), getRecipe() будет вызываться автоматически при изменении path. Таким образом, нам не нужно вызывать его вручную из search() и, следовательно, мы можем удалить getRecipe() из тела функции. Это также делает текущий useEffect() (без зависимости [path]) избыточным, поэтому его можно удалить.

Другое решение - предоставить новое значение query через параметры getRecipe(), удалив зависимость от состояния.

function search(queryString){
  setQuery(queryString);
  getRecipe(queryString);
}

async function getRecipe(query) {
  const path = `https://api.edamam.com/search?q=${query}&app_id=${API_id}&app_key=${API_key}`;
  const response = await fetch(path); // <- is no longer dependent upon the state
  const data = await response.json();
  setRecipe(data.hits);
}

Для этого необходимо переместить определение path внутрь getRecipe().

person 3limin4t0r    schedule 19.04.2021