0

为什么我的 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

4

2 回答 2

2

AuseEffect相当于componentDidMount,因此它会在组件挂载时运行一次,然后仅在依赖数组中定义的依赖项之一发生更改时才重新运行。

如果您只想getRecipes()query依赖项有值时调用,您可以在条件中调用它,如下所示:

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

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

有关为什么这很重要的信息,请参阅React 文档

于 2020-03-07T11:36:25.140 回答
0

UseEffect hook 等效于 componentDidMount、componentDidUpdate 和 componentWillUnmount 组合 React 类组件生命周期。但是在 DOM.componentDidMount 和 useEffect 在挂载后运行的时间不同。但是 useEffect 在绘制完成后运行,而不是之前运行。这意味着如果你需要从 DOM 中读取,你会得到一个闪烁,然后同步设置状态以使新的 UI.useLayoutEffect 被设计为与 componentDidMount 具有相同的时序。所以 useLayoutEffect(fn, []) 比 useEffect(fn, []) 更接近 componentDidMount() —— 至少从时间的角度来看。这是否意味着我们应该改用 useLayoutEffect ?可能不是。如果您确实想通过同步设置状态来避免闪烁,请使用 useLayoutEffect。但由于这些情况很少见,

于 2020-03-07T10:16:04.710 回答