为什么我的 useEffect 在页面加载时反应函数 运行 尽管我给它第二个值数组

Why does my useEffect react function run when the page loads although I am giving it a second value array

为什么我的 useEffect 反应函数 运行 在每个页面加载时都在使用 运行 宁,尽管给它一个带有 query 变量的第二个值数组?

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

query 状态变量改变时,它不应该只 运行 吗?除了 useEffect 函数之外,我没有使用 getRecipes 函数。

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

UseEffect hook 相当于 componentDidMount、componentDidUpdate 和 componentWillUnmount 组合的 React class 组件 lifecycles.but DOM.componentDidMount 和 useEffect 运行 的作用时间不同安装后。但是,与之前相比,在绘画提交到屏幕之后使用 Effect 运行s。这意味着如果你需要从 DOM 读取,你会得到一个闪烁,然后同步设置状态以使新的 UI.useLayoutEffect 被设计为与 componentDidMount 具有相同的时序。所以 useLayoutEffect(fn, []) 比 useEffect(fn, []) 更接近于 componentDidMount() —— 至少从计时的角度来看是这样。 这是否意味着我们应该改用 useLayoutEffect? 可能不会。 如果您确实想通过同步设置状态来避免闪烁,请使用 useLayoutEffect。但由于这些情况很少见,所以大多数时候您会希望使用 useEffect。

一个useEffect相当于componentDidMount,所以在组件挂载的时候会运行一次,只有其中一个依赖的时候才会重新运行在依赖项数组中定义更改。

如果你只想在 query 依赖项有值时调用 getRecipes(),你可以像这样在条件中调用它:

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

此外,由于您的 useEffect 正在调用一个函数 (getRecipes),该函数被声明为 之外 使用效果,但 在[内部] 组件,您应该将函数声明移动到 useEffect 内部并添加适当的依赖项,或者将您的函数包装在 useCallback 中并将函数添加为 useEffect.

请参阅 React docs 了解为什么这很重要。