State 不计算新值:(
我需要帮助
我的状态依赖于另一个状态,并且想要根据 setTotalPrice
下面的代码中的第一个状态更新第二个状态 未获取 ingredientsPrice + PizzaPrice< 的值/code> 当我更新
ingredientsPrice
时,
import React, { useState } from "react";
import classes from "../../styles/Pages/Product.module.scss";
import Image from "next/image";
import axios from "axios";
function Product({ pizza }) {
// The State of Pizza Size
const [size, setSize] = useState(0);
const [ingredientsPrice, setIngredientsPrice] = useState(0);
const [pizzaPrice, setPizzaPrice] = useState(pizza.price[size]);
const [totalPrice, setTotalPrice] = useState(pizza.price[size]);
const handleIngredients = async (e, ingPrice) => {
// add ingredients Price on every change and call total handler fn();
if (e.target.checked) {
setIngredientsPrice((prevIngPrice) => prevIngPrice + ingPrice);
handleTotalPrice();
} else {
setIngredientsPrice((prevIngPrice) => prevIngPrice - ingPrice);
handleTotalPrice();
}
};
const handleTotalPrice = () => {
// Calc the pizza price + ing price and update total
setTotalPrice(pizzaPrice + ingredientsPrice);
};
return (
<div className={classes.Container}>
<div className={classes.Left}>
<div className={classes.ImgContainer}>
<Image
alt={pizza.title}
src={pizza.image}
layout="fill"
objectFit="contain"
/>
</div>
</div>
<div className={classes.Right}>
<h1 className={classes.Title}>{pizza.title}</h1>
<span className={classes.Price}>${totalPrice}</span>
<p className={classes.Description}>{pizza.description}</p>
<h3 className={classes.Choose}>Choose Your Size</h3>
<div className={classes.Sizes}>
<div
className={classes.SizeItem}
onClick={() => setSize(0)}
>
<Image
src={"/Images/size.png"}
alt="Small Size"
layout="fill"
/>
<span className={classes.Size}>Small</span>
</div>
<div
className={classes.SizeItem}
onClick={() => setSize(1)}
>
<Image
src={"/Images/size.png"}
alt="Small Size"
layout="fill"
/>
<span className={classes.Size}>Medium</span>
</div>
<div
className={classes.SizeItem}
onClick={() => setSize(2)}
>
<Image
src={"/Images/size.png"}
alt="Small Size"
layout="fill"
/>
<span className={classes.Size}>Large</span>
</div>
</div>
<h3 className={classes.Choose}>
Choose Additional Ingredients
</h3>
<div className={classes.Ingredients}>
{pizza.extraOptions.map((cur, index) => {
const trimedName = cur.extra.trim();
const ingPrice = cur.price;
return (
<div
className={classes.IngredientOption}
key={"Extra" + index}
>
<input
type={"checkbox"}
name={trimedName}
id={trimedName}
className={classes.Checkbox}
onChange={(e) =>
handleIngredients(e, ingPrice)
}
/>
<label htmlFor={trimedName}>{cur.extra}</label>
</div>
);
})}
</div>
<div className={classes.Quentity}>
<input type={"number"} defaultValue={1} max={5} min={1} />
<button>Add to Cart</button>
</div>
</div>
</div>
);
}
export default Product;
export async function getServerSideProps({ params }) {
const pizza = await axios.get(
"http://localhost:3000/api/products/" + params.id
);
return {
props: { pizza: pizza.data },
};
}
我希望 totalPrice
会在 ingredientsPrice
更新时自动更新
I need help
I have a state depending on another state and want to update the second state based on the first state in the code below the setTotalPrice
Doesn't get the value of ingredientsPrice + pizzaPrice
when I update the ingredientsPrice
import React, { useState } from "react";
import classes from "../../styles/Pages/Product.module.scss";
import Image from "next/image";
import axios from "axios";
function Product({ pizza }) {
// The State of Pizza Size
const [size, setSize] = useState(0);
const [ingredientsPrice, setIngredientsPrice] = useState(0);
const [pizzaPrice, setPizzaPrice] = useState(pizza.price[size]);
const [totalPrice, setTotalPrice] = useState(pizza.price[size]);
const handleIngredients = async (e, ingPrice) => {
// add ingredients Price on every change and call total handler fn();
if (e.target.checked) {
setIngredientsPrice((prevIngPrice) => prevIngPrice + ingPrice);
handleTotalPrice();
} else {
setIngredientsPrice((prevIngPrice) => prevIngPrice - ingPrice);
handleTotalPrice();
}
};
const handleTotalPrice = () => {
// Calc the pizza price + ing price and update total
setTotalPrice(pizzaPrice + ingredientsPrice);
};
return (
<div className={classes.Container}>
<div className={classes.Left}>
<div className={classes.ImgContainer}>
<Image
alt={pizza.title}
src={pizza.image}
layout="fill"
objectFit="contain"
/>
</div>
</div>
<div className={classes.Right}>
<h1 className={classes.Title}>{pizza.title}</h1>
<span className={classes.Price}>${totalPrice}</span>
<p className={classes.Description}>{pizza.description}</p>
<h3 className={classes.Choose}>Choose Your Size</h3>
<div className={classes.Sizes}>
<div
className={classes.SizeItem}
onClick={() => setSize(0)}
>
<Image
src={"/Images/size.png"}
alt="Small Size"
layout="fill"
/>
<span className={classes.Size}>Small</span>
</div>
<div
className={classes.SizeItem}
onClick={() => setSize(1)}
>
<Image
src={"/Images/size.png"}
alt="Small Size"
layout="fill"
/>
<span className={classes.Size}>Medium</span>
</div>
<div
className={classes.SizeItem}
onClick={() => setSize(2)}
>
<Image
src={"/Images/size.png"}
alt="Small Size"
layout="fill"
/>
<span className={classes.Size}>Large</span>
</div>
</div>
<h3 className={classes.Choose}>
Choose Additional Ingredients
</h3>
<div className={classes.Ingredients}>
{pizza.extraOptions.map((cur, index) => {
const trimedName = cur.extra.trim();
const ingPrice = cur.price;
return (
<div
className={classes.IngredientOption}
key={"Extra" + index}
>
<input
type={"checkbox"}
name={trimedName}
id={trimedName}
className={classes.Checkbox}
onChange={(e) =>
handleIngredients(e, ingPrice)
}
/>
<label htmlFor={trimedName}>{cur.extra}</label>
</div>
);
})}
</div>
<div className={classes.Quentity}>
<input type={"number"} defaultValue={1} max={5} min={1} />
<button>Add to Cart</button>
</div>
</div>
</div>
);
}
export default Product;
export async function getServerSideProps({ params }) {
const pizza = await axios.get(
"http://localhost:3000/api/products/" + params.id
);
return {
props: { pizza: pizza.data },
};
}
I expect the totalPrice
will update automatically when ingredientsPrice
updates
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题在于:
setIngredientsPrice
实际上以异步方式更改了ingredientsPrice
,因此handleTotalPrice
中的代码肯定有可能在<时执行code>ingredientsPrice 尚未更新,因此导致totalPrice
值错误。为了克服 React 中的这个常见问题,您需要将
handleTotalPrice
函数调用移动到useEffect
挂钩,如下所示:我们传入
useEffect
的函数每当依赖项数组(我们也传递到 useEffect 的数组)中列出的任何变量发生更改时,code> 钩子就会运行。The problem is with this:
setIngredientsPrice
actually changes theingredientsPrice
in an async manner, so it is surely possible that the code insidehandleTotalPrice
execute wheningredientsPrice
is not yet updated thus resulting with the wrongtotalPrice
value.To overcome this common problem in React, you need to move your
handleTotalPrice
function call to auseEffect
hook, like this:The function that we pass in
useEffect
hook will run whenever any of the variables listed inside dependency array (the array which we also pass into theuseEffect
) change.React 中的状态更新是异步的,这意味着它们不会立即应用,而是排队。
我建议您将依赖状态放入一个对象中,然后更新该对象。
ingredientsPrice
和totalPrice
是相关的。如果更新其中一个,则还需要更新另一个(至少根据我的理解),因此将它们放在一个对象状态中并仅更新该状态。请注意,更新状态时必须提供新对象,因为仅执行不深度比较。
看看这篇博客文章了解更多详情。
State updates in React are asynchronous, that means they are not applied immediately but queued.
I would suggest that you put dependent state in one single object which you then update.
ingredientsPrice
andtotalPrice
are dependent. If you update one, you need to update the other as well (at least from my understanding), so put them together in an object state and update just that one state.Be aware that you must provide a new object when you update state as only a no deep comparism is performed.
Have a look at this blog post for more details.