gpt4 book ai didi

reactjs - 当 Context 中的状态发生变化时,组件不会立即重新渲染

转载 作者:行者123 更新时间:2023-12-05 03:20:47 24 4
gpt4 key购买 nike

我在 NextJS 电子商务项目中实现 React Context 时遇到了一些问题。将产品添加到购物车时,一切都很好,但是当我打开购物车模式以在确认订单之前增加或减少每个产品的数量时,组件没有重新呈现。它仅在我关闭模态后才重新呈现。这是我在代码沙箱上的项目的链接:https://codesandbox.io/s/hopeful-hill-z31o49

这是问题的快速演示视频:https://youtu.be/tRD7Hs-9rOw

这是上下文文件

export const CartContext = createContext<ContextProps>(null);

export const ContextProvider = function ({ children }) {
const [openModal, setOpenModal] = useState(false);
const [cart, setCart] = useState<any[]>([]);

const ctx = {
openModal,
setOpenModal,
cart,
setCart,
};

return <CartContext.Provider value={ctx}>{children}</CartContext.Provider>;
};

使用Context时出现问题的组件

// ./components/Modal.tsx

const Modal = () => {
const { setOpenModal, cart, setCart } = useContext(CartContext);
console.log("🚀 -> cart", cart);

const totalPrice = cart.reduce(
(sum, currProduct) => sum + currProduct.price * currProduct.quantity,
0,
);

function increaseQuantity(product: any) {
let updatedCart = cart;
const idx = updatedCart.findIndex((p) => p.name === product.name);
updatedCart[idx].quantity += 1;
setCart(updatedCart);
console.log("🚀 -> updatedCart", updatedCart);
}

function decreaseQuantity(product: any) {
let updatedCart = cart;
if (product.quantity > 1) {
const idx = updatedCart.findIndex((p) => p.name === product.name);
updatedCart[idx].quantity -= 1;
setCart(updatedCart);
console.log("🚀 -> updatedCart", updatedCart);
} else {
updatedCart = updatedCart.filter((p) => p.name !== product.name);
}
setCart(updatedCart);
}

return (
<div>
...
{cart.map((product) => (
<div>
<button onClick={() => increaseQuantity(product)}></button>
<div>{product.quantity}</div>
<button onClick={() => decreaseQuantity(product)}></button>
</div>
))}
...
</div>
)


最佳答案

useConext 没有触发渲染的原因是 React 没有对状态对象进行深度相等比较。当您调用 setCart(updatedCart); 时,React 不会检查购物车中的所有商品以查找差异。它只检查购物车的实例是否已更改。所以在这种情况下,它会将它视为没有机会,因为您只更新购物车中的商品而不更新购物车的实例。要更正此问题,您可以替换行

setCart(updatedCart);

setCart([...updatedCart]);

这会创建购物车的副本而不是重复使用同一个购物车,因此它会触发 React 来呈现更新。

但是,有时您不想这样做,尤其是当创建数组副本的成本太高时。触发更新而不是创建状态副本的一个简单技巧是添加一个状态以在更新时触发 React to render。在 /components/Modal.tsx您可以添加一个状态并在您对 UI 进行更新时更新它,如下所示

const Modal = () => {
const { setOpenModal, cart, setCart } = useContext(CartContext);
const { lastUpdate, setLastUpdate } = useState(0);
...
function increaseQuantity(product: any) {
...
setLastUpdate(Date.now());
...
}

function decreaseQuantity(product: any) {
...
setLastUpdate(Date.now());
...
}

关于reactjs - 当 Context 中的状态发生变化时,组件不会立即重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73083886/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com