ReactJS:React setState/useState 不会立即更新
ReactJS: React setState/useState does not update immediately
我正在构建一个美食食谱应用程序,我有一个即时自动过滤搜索结果,当用户键入任何字母时查询并获取数据。例如,对于字母“c”,它将显示成分中包含字母“c”的结果列表。一切似乎都工作正常,除了自动过滤器向后延迟一个字母,所以当用户键入“ch”或“c + 一个随机字母时它只显示包含字母“c”的结果".
我读了这个 link:https://linguinecode.com/post/why-react-setstate-usestate-does-not-update-immediatelyand 这有助于我定义为什么 React useState 不会立即更新,我认为解决方案是使用 React useEffect。我是学习 React 的新手,所以我很难将我的代码重构为在我的案例中使用 useEffect。如果有人启发我,我将不胜感激。谢谢大家!
这是我的演示:gif
这是我的代码:
// Recipes.js
export default function Recipes() {
const [query, setQuery] = useState("")
const [recipes, setRecipes] = useState([])
const [alert, setAlert] = useState("")
const APP_ID = "5b1b4741"
const APP_KEY = "0325f7a61ac15027151b8060740d90f0"
const url = `https://api.edamam.com/search?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`
const getData = async () => {
if (query !== "") {
const result = await Axios.get(url)
if (!result.data.more) {
return setAlert("No food with such name")
}
console.log(result)
setRecipes(result.data.hits)
setQuery("")
setAlert("")
} else {
setAlert("Please fill the form")
}
}
const onChange = async e => {
setQuery(e.target.value)
if (query !== "") {
const result = await Axios.get(url)
console.log(result)
setRecipes(result.data.hits)
}
}
const onSubmit = e => {
e.preventDefault()
getData()
};
return (
<div className="recipes">
<div className="search-box">
<h1>Your Recipe App</h1>
<form onSubmit={onSubmit} className="search-form">
{alert !== "" && <Alert alert={alert} />}
<input
type="text"
name="query"
onChange={onChange}
value={query}
placeholder="Search Food"
/>
<input type="submit" value="Search" />
</form>
{query.length !== 0 &&
<div className="search-result">
{recipes.slice(0, 5).map((val) => {
return (
<a className="search-item" href={val.recipe.url} target="_blank" rel="noopener noreferrer">
<p>{val.recipe.label}</p>
</a>
)
})}
</div>
}
</div>
<div className="recipes-card">
{recipes !== [] &&
recipes.map(recipe => <Recipe key={uuidv4()} recipe={recipe} />)}
</div>
</div>
// Recipe.js
const Recipe = ({ recipe }) => {
const [show, setShow] = useState(false);
const { label, image, url, ingredients } = recipe.recipe;
return (
<div className="recipe">
<h2>{label}</h2>
<img src={image} alt={label} />
<a href={url} target="_blank" rel="noopener noreferrer">
Go To Link
</a>
<button onClick={() => setShow(!show)}>Ingredients</button>
{show && <RecipeDetails ingredients={ingredients} />}
</div>
)
}
export default Recipe
const onChange = async e => {
setQuery(e.target.value)
if (query !== "") {
const result = await Axios.get(url)
console.log(result)
setRecipes(result.data.hits)
}
}
您正在发送消息以设置 query
的新值,但随后 立即 使用旧值(函数已关闭)使您的Ajax请求。
任一:
- 只需使用
e.target.value
而不是 query
(不要忘记也移动计算 url
值的逻辑)。
- 设置一个
useEffect
依赖于 query
的挂钩,其中包含我引用的第 3-7 行的代码。
你不是被迫使用useEffect
:
export default function Recipes() {
const [query, setQuery] = useState("")
const [recipes, setRecipes] = useState([])
const [alert, setAlert] = useState("")
const APP_ID = "5b1b4741"
const APP_KEY = "0325f7a61ac15027151b8060740d90f0"
const baseUrl = `https://api.edamam.com/search`
const getData = async () => {
if (query !== "") {
const result = await Axios.get(baseUrl + `?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`)
if (!result.data.more) {
return setAlert("No food with such name")
}
console.log(result)
setRecipes(result.data.hits)
setQuery("")
setAlert("")
} else {
setAlert("Please fill the form")
}
}
const onChange = async e => {
setQuery(e.target.value)
if (query !== "") {
const result = await Axios.get(baseUrl + `?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`)
console.log(result)
setRecipes(result.data.hits)
}
}
const onSubmit = e => {
e.preventDefault()
getData()
};
return (
<div className="recipes">
<div className="search-box">
<h1>Your Recipe App</h1>
<form onSubmit={onSubmit} className="search-form">
{alert !== "" && <Alert alert={alert} />}
<input
type="text"
name="query"
onChange={onChange}
value={query}
placeholder="Search Food"
/>
<input type="submit" value="Search" />
</form>
{query.length !== 0 &&
<div className="search-result">
{recipes.slice(0, 5).map((val) => {
return (
<a className="search-item" href={val.recipe.url} target="_blank" rel="noopener noreferrer">
<p>{val.recipe.label}</p>
</a>
)
})}
</div>
}
</div>
<div className="recipes-card">
{recipes !== [] &&
recipes.map(recipe => <Recipe key={uuidv4()} recipe={recipe} />)}
</div>
</div>
我正在构建一个美食食谱应用程序,我有一个即时自动过滤搜索结果,当用户键入任何字母时查询并获取数据。例如,对于字母“c”,它将显示成分中包含字母“c”的结果列表。一切似乎都工作正常,除了自动过滤器向后延迟一个字母,所以当用户键入“ch”或“c + 一个随机字母时它只显示包含字母“c”的结果".
我读了这个 link:https://linguinecode.com/post/why-react-setstate-usestate-does-not-update-immediatelyand 这有助于我定义为什么 React useState 不会立即更新,我认为解决方案是使用 React useEffect。我是学习 React 的新手,所以我很难将我的代码重构为在我的案例中使用 useEffect。如果有人启发我,我将不胜感激。谢谢大家!
这是我的演示:gif
这是我的代码:
// Recipes.js
export default function Recipes() {
const [query, setQuery] = useState("")
const [recipes, setRecipes] = useState([])
const [alert, setAlert] = useState("")
const APP_ID = "5b1b4741"
const APP_KEY = "0325f7a61ac15027151b8060740d90f0"
const url = `https://api.edamam.com/search?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`
const getData = async () => {
if (query !== "") {
const result = await Axios.get(url)
if (!result.data.more) {
return setAlert("No food with such name")
}
console.log(result)
setRecipes(result.data.hits)
setQuery("")
setAlert("")
} else {
setAlert("Please fill the form")
}
}
const onChange = async e => {
setQuery(e.target.value)
if (query !== "") {
const result = await Axios.get(url)
console.log(result)
setRecipes(result.data.hits)
}
}
const onSubmit = e => {
e.preventDefault()
getData()
};
return (
<div className="recipes">
<div className="search-box">
<h1>Your Recipe App</h1>
<form onSubmit={onSubmit} className="search-form">
{alert !== "" && <Alert alert={alert} />}
<input
type="text"
name="query"
onChange={onChange}
value={query}
placeholder="Search Food"
/>
<input type="submit" value="Search" />
</form>
{query.length !== 0 &&
<div className="search-result">
{recipes.slice(0, 5).map((val) => {
return (
<a className="search-item" href={val.recipe.url} target="_blank" rel="noopener noreferrer">
<p>{val.recipe.label}</p>
</a>
)
})}
</div>
}
</div>
<div className="recipes-card">
{recipes !== [] &&
recipes.map(recipe => <Recipe key={uuidv4()} recipe={recipe} />)}
</div>
</div>
// Recipe.js
const Recipe = ({ recipe }) => {
const [show, setShow] = useState(false);
const { label, image, url, ingredients } = recipe.recipe;
return (
<div className="recipe">
<h2>{label}</h2>
<img src={image} alt={label} />
<a href={url} target="_blank" rel="noopener noreferrer">
Go To Link
</a>
<button onClick={() => setShow(!show)}>Ingredients</button>
{show && <RecipeDetails ingredients={ingredients} />}
</div>
)
}
export default Recipe
const onChange = async e => { setQuery(e.target.value) if (query !== "") { const result = await Axios.get(url) console.log(result) setRecipes(result.data.hits) } }
您正在发送消息以设置 query
的新值,但随后 立即 使用旧值(函数已关闭)使您的Ajax请求。
任一:
- 只需使用
e.target.value
而不是query
(不要忘记也移动计算url
值的逻辑)。 - 设置一个
useEffect
依赖于query
的挂钩,其中包含我引用的第 3-7 行的代码。
你不是被迫使用useEffect
:
export default function Recipes() {
const [query, setQuery] = useState("")
const [recipes, setRecipes] = useState([])
const [alert, setAlert] = useState("")
const APP_ID = "5b1b4741"
const APP_KEY = "0325f7a61ac15027151b8060740d90f0"
const baseUrl = `https://api.edamam.com/search`
const getData = async () => {
if (query !== "") {
const result = await Axios.get(baseUrl + `?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`)
if (!result.data.more) {
return setAlert("No food with such name")
}
console.log(result)
setRecipes(result.data.hits)
setQuery("")
setAlert("")
} else {
setAlert("Please fill the form")
}
}
const onChange = async e => {
setQuery(e.target.value)
if (query !== "") {
const result = await Axios.get(baseUrl + `?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`)
console.log(result)
setRecipes(result.data.hits)
}
}
const onSubmit = e => {
e.preventDefault()
getData()
};
return (
<div className="recipes">
<div className="search-box">
<h1>Your Recipe App</h1>
<form onSubmit={onSubmit} className="search-form">
{alert !== "" && <Alert alert={alert} />}
<input
type="text"
name="query"
onChange={onChange}
value={query}
placeholder="Search Food"
/>
<input type="submit" value="Search" />
</form>
{query.length !== 0 &&
<div className="search-result">
{recipes.slice(0, 5).map((val) => {
return (
<a className="search-item" href={val.recipe.url} target="_blank" rel="noopener noreferrer">
<p>{val.recipe.label}</p>
</a>
)
})}
</div>
}
</div>
<div className="recipes-card">
{recipes !== [] &&
recipes.map(recipe => <Recipe key={uuidv4()} recipe={recipe} />)}
</div>
</div>