【问题标题】:Why does my useEffect react function run when the page loads although I am giving it a second value array为什么我的useEffect反应函数在页面加载时运行,尽管我给了它第二个值数组
【发布时间】:2020-06-19 21:49:45
【问题描述】:

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

【问题讨论】:

  • 所有 useEffects 在组件挂载时运行一次,然后它们仅在其依赖项之一(在数组中)发生更改时重新运行。
  • 如果你只想在查询有一定值的时候调用getRecipes,那么在使用效果里面使用一个if函数。
  • useEffect( () =&gt; { if (query) { getRecipes(); }}, [query]);
  • @JMadelaine 从技术上讲,useEffect() 不是在 render() 生命周期中第一次执行吗? componentWillMount(),然后是render(),然后是componentDidMount()
  • @Rick Sanchez 我添加了我的 cmets 作为答案以及更多信息。

标签: javascript reactjs react-hooks use-effect use-state


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    useEffect 等同于componentDidMount,因此它会在组件挂载时运行一次,然后仅在依赖项数组中定义的其中一个依赖项发生更改时重新运行。

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-15
      • 1970-01-01
      • 2019-06-20
      • 2015-08-19
      相关资源
      最近更新 更多