为什么我的useEffect react函数在每次页面加载时都运行,尽管给了它第二个带有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;
答案 0 :(得分:2)
useEffect
与componentDidMount
等效,因此它将在组件安装时运行一次,然后仅在依赖项数组中定义的一个依赖项发生更改时才重新运行。
如果仅当getRecipes()
依赖项具有值时才想调用query
,则可以像这样的条件调用它:
useEffect(() => {
if(query) {
getRecipes()
}
}, [query])
此外,当您的useEffect
调用的函数(getRecipes
)声明为外部使用效果而在内部内部时,应该将函数声明移到useEffect
内并添加适当的依赖关系,或者将函数包装在useCallback
中并添加函数作为useEffect
的依赖关系。
请参阅React docs,以了解为什么这很重要。
答案 1 :(得分:0)
UseEffect钩子工作等效于componentDidMount,componentDidUpdate和componentWillUnmount组合了React类组件的生命周期。但是在DOM.componentDidMount和useEffect的作用时间不同,在挂载后运行。但是useEffect在将油漆提交到屏幕之后而不是之前运行。这意味着如果您需要读取DOM,然后同步设置状态以创建新的UI,则会出现闪烁。useLayoutEffect的设计时间与componentDidMount相同。所以useLayoutEffect(fn,[])比useEffect(fn,[])更接近componentDidMount()-至少从时间角度来看。 这是否意味着我们应该改用useLayoutEffect? 可能不会。 如果确实要通过同步设置状态来避免该闪烁,请使用useLayoutEffect。但是由于这些情况很少见,因此您通常会希望使用useEffect。