State 不计算新值 :(
State Doesn't calculate the new value : (
我需要帮助
我有一个状态依赖于另一个状态,我想根据 setTotalPrice
下面代码中的第一个状态更新第二个状态 我更新时没有得到 ingredientsPrice + pizzaPrice
的值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
更新时自动更新
React 中的状态更新是异步的,这意味着它们不会立即应用而是排队。
我建议您将依赖状态放在一个对象中,然后再对其进行更新。 ingredientsPrice
和 totalPrice
是相关的。如果你更新一个,你也需要更新另一个(至少根据我的理解),所以将它们放在一个对象状态中并只更新那个状态。
请注意,更新状态时必须提供新对象,因为只执行非深度比较。
查看此blog post了解更多详情。
问题在于:
setIngredientsPrice((prevIngPrice) => prevIngPrice - ingPrice);
handleTotalPrice();
setIngredientsPrice
实际上以异步方式更改了 ingredientsPrice
,因此肯定有可能 handleTotalPrice
中的代码在 ingredientsPrice
尚未更新时执行,从而导致totalPrice
值错误。
要克服 React 中的这个常见问题,您需要将 handleTotalPrice
函数调用移动到 useEffect
挂钩,如下所示:
//update totalPrice when ingredientsPrice or pizzaPrice change
useEffect(() => {
setTotalPrice(ingredientsPrice + pizzaPrice);
//or handleTotalPrice();
},[ingredientsPrice, pizzaPrice]);
我们传入 useEffect
钩子的函数将 运行 每当依赖数组(我们也传入 useEffect
的数组)中列出的任何变量发生变化时。
我需要帮助
我有一个状态依赖于另一个状态,我想根据 setTotalPrice
下面代码中的第一个状态更新第二个状态 我更新时没有得到 ingredientsPrice + pizzaPrice
的值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
更新时自动更新
React 中的状态更新是异步的,这意味着它们不会立即应用而是排队。
我建议您将依赖状态放在一个对象中,然后再对其进行更新。 ingredientsPrice
和 totalPrice
是相关的。如果你更新一个,你也需要更新另一个(至少根据我的理解),所以将它们放在一个对象状态中并只更新那个状态。
请注意,更新状态时必须提供新对象,因为只执行非深度比较。
查看此blog post了解更多详情。
问题在于:
setIngredientsPrice((prevIngPrice) => prevIngPrice - ingPrice);
handleTotalPrice();
setIngredientsPrice
实际上以异步方式更改了 ingredientsPrice
,因此肯定有可能 handleTotalPrice
中的代码在 ingredientsPrice
尚未更新时执行,从而导致totalPrice
值错误。
要克服 React 中的这个常见问题,您需要将 handleTotalPrice
函数调用移动到 useEffect
挂钩,如下所示:
//update totalPrice when ingredientsPrice or pizzaPrice change
useEffect(() => {
setTotalPrice(ingredientsPrice + pizzaPrice);
//or handleTotalPrice();
},[ingredientsPrice, pizzaPrice]);
我们传入 useEffect
钩子的函数将 运行 每当依赖数组(我们也传入 useEffect
的数组)中列出的任何变量发生变化时。