Почему моя функция useEffect реагирует на загрузку страницы, хотя я даю ей второй массив значений - PullRequest
0 голосов
/ 07 марта 2020

Почему моя функция реакции useEffect запускается при каждой загрузке страницы, хотя ей присваивается второй массив значений с переменной query?

useEffect( () => {
    getRecipes();
}, [query]);

Разве он не должен запускаться только при изменении переменной состояния query? У меня больше ничего нет при использовании функции getRecipes, кроме функции useEffect.

import React, {useEffect, useState} from 'react';
import './App.css';
import Recipes from './components/Recipes/Recipes';

const App = () => {

    // Constants
    const APP_ID                                = '111';
    const APP_KEY                               = '111'; 
    const [recipes, setRecipes]                 = useState([]);
    const [search, setSearch]                   = useState(''); 
    const [query, setQuery]                     = useState('');
    const [showRecipesList, setShowRecipesList] = useState(false);

    // Lets
    let recipesList                             = null; 

    // Functions
    useEffect( () => {
        getRecipes();
    }, [query]);

    // Get the recipie list by variables
    const getRecipes = async () => {
        const response = await fetch(`https://api.edamam.com/search?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}&from=0&to=3&calories=591-722&health=alcohol-free`); 
        const data     = await response.json(); 
        console.log(data.hits);
        setRecipes(data.hits);
    }

    // Update the search constant 
    const updateSearch = e => {
        console.log(e.target.value);
        setSearch(e.target.value);
    }

    const runQuery = e => {
        e.preventDefault();
        setQuery(search);
    }


    // List recipes if ready
    if (recipes.length) {
        console.log(recipes.length);
        recipesList = <Recipes recipesList={recipes} />
    }

    return (

        <div className="App">

            <form className='search-app' onSubmit={ runQuery }>
                <input 
                    type='text' 
                    className='search-bar' 
                    onChange={ updateSearch } 
                    value={search}/>
                <button 
                    type='submit'   
                    className='search-btn' > Search </button>
            </form>

            <div className='recipesList'>
                {recipesList}
            </div>

        </div>

    );

}

export default App;

После этого: https://www.youtube.com/watch?v=U9T6YkEDkMo

Ответы [ 2 ]

2 голосов
/ 07 марта 2020

A useEffect является эквивалентом componentDidMount, поэтому он запускается один раз при монтировании компонента, а затем перезапускается только при изменении одной из зависимостей, определенных в массиве зависимостей.

Если Вы хотите вызывать getRecipes() только тогда, когда зависимость query имеет значение, вы можете вызывать его условно следующим образом:

useEffect(() => {
  if(query) {
    getRecipes()
  }
}, [query])

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

См. React docs для получения информации о том, почему это важно.

0 голосов
/ 07 марта 2020

Рабочий крючок UseEffect, эквивалентный компоненту componentDidMount, componentDidUpdate и componentWillUnmount, объединяет жизненные циклы компонента класса React. Но время действия в DOM.componentDidMount и время запуска после монтирования различаются. Однако useEffect запускается после фиксации краски на экране, а не до того. Это означает, что вы получите мерцание, если вам нужно прочитать из DOM, а затем синхронно установить состояние, чтобы новый UI.useLayoutEffect был разработан так, чтобы иметь то же время, что и componentDidMount. Так что useLayoutEffect (fn, []) гораздо ближе к componentDidMount (), чем useEffect (fn, []) - по крайней мере, с точки зрения синхронизации. Означает ли это, что мы должны использовать useLayoutEffect? Возможно нет. Если вы хотите избежать этого мерцания, синхронно устанавливая состояние, используйте useLayoutEffect. Но так как это редкие случаи, вы захотите использовать useEffect большую часть времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...