Child 更新上下文 React 后组件未更新
Child Components not being updated after updating context React
我正在尝试使用 React 上下文创建购物车机制。
这是我的上下文提供程序
export default function App() {
const [cart, setCart] = useState(cartInitialState);
return (
<CartContext.Provider value={{ cart, setCart }}>
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
<MenuItemDetailsView />
</CartContext.Provider>
);
}
购物车初始状态是一些虚拟的空购物车。 MenuItemDetailsView 是一个 child 视图,它使用 parent 组件上下文
function MenuItemDetailsView() {
const { cart, setCart } = useContext(CartContext);
const findItemInCart = () => {
//return quantity of cart item with specific id
};
const handleAdd = () => {
const itemIndex = cart.items.findIndex((item) => item.id === 0);
let newCart = cart;
console.debug(newCart);
if (itemIndex === -1) {
//do stuff
} else {
//do stuff
}
setCart(newCart);
};
return (
<div>
<h1>{findItemInCart()}</h1>
<button onClick={handleAdd}>add</button>
</div>
);
}
child 视图应该能够正确地更新上下文。问题是 parent 应用程序在更新上下文后没有重新呈现 MenuItemDetailsView 组件。 (App 组件重新渲染自身
这是我的代码的沙箱
https://codesandbox.io/s/react-context-demo-cart-eyjx2
我不太明白这里的问题。 App 组件不应该重新渲染它的 children 吗?如果不是,我怎么告诉他在更新上下文时重新渲染?
我理解设置本地 child 变量并在更新数量时同时更新变量和上下文本身的可能性,但我认为这将是解决实际问题的方法。
SN:退出 MenuItemView 并重新进入时(从多页应用程序,未显示在沙盒中)数量得到更新,这意味着 useContext 正常工作并且每次 MenuItemView 时都正确读取购物车项目正在重新渲染。但是我再次希望购物车得到更新而无需退出组件并手动返回
这里的问题是您正在改变购物车状态。
let newCart = cart;
newCart
仍然引用您保持状态的同一个对象,因此当您更新 newCart
时,您也在改变 cart
。一旦你做了 setCart(newCart)
,React 就会退出状态更新(和重新渲染),因为它和以前是同一个对象。 React docs.
中有更多关于 React 在更新状态时如何比较对象的信息
这里的解决方法是先复制状态作为一个新的对象:
const newCart = { ...cart };
或者更好的是,使用功能状态更新:
setCart(prevCart => {
const newCart = { ...prevCart };
// do stuff with newCart
return newCart;
});
我正在尝试使用 React 上下文创建购物车机制。
这是我的上下文提供程序
export default function App() {
const [cart, setCart] = useState(cartInitialState);
return (
<CartContext.Provider value={{ cart, setCart }}>
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
<MenuItemDetailsView />
</CartContext.Provider>
);
}
购物车初始状态是一些虚拟的空购物车。 MenuItemDetailsView 是一个 child 视图,它使用 parent 组件上下文
function MenuItemDetailsView() {
const { cart, setCart } = useContext(CartContext);
const findItemInCart = () => {
//return quantity of cart item with specific id
};
const handleAdd = () => {
const itemIndex = cart.items.findIndex((item) => item.id === 0);
let newCart = cart;
console.debug(newCart);
if (itemIndex === -1) {
//do stuff
} else {
//do stuff
}
setCart(newCart);
};
return (
<div>
<h1>{findItemInCart()}</h1>
<button onClick={handleAdd}>add</button>
</div>
);
}
child 视图应该能够正确地更新上下文。问题是 parent 应用程序在更新上下文后没有重新呈现 MenuItemDetailsView 组件。 (App 组件重新渲染自身
这是我的代码的沙箱
https://codesandbox.io/s/react-context-demo-cart-eyjx2
我不太明白这里的问题。 App 组件不应该重新渲染它的 children 吗?如果不是,我怎么告诉他在更新上下文时重新渲染?
我理解设置本地 child 变量并在更新数量时同时更新变量和上下文本身的可能性,但我认为这将是解决实际问题的方法。
SN:退出 MenuItemView 并重新进入时(从多页应用程序,未显示在沙盒中)数量得到更新,这意味着 useContext 正常工作并且每次 MenuItemView 时都正确读取购物车项目正在重新渲染。但是我再次希望购物车得到更新而无需退出组件并手动返回
这里的问题是您正在改变购物车状态。
let newCart = cart;
newCart
仍然引用您保持状态的同一个对象,因此当您更新 newCart
时,您也在改变 cart
。一旦你做了 setCart(newCart)
,React 就会退出状态更新(和重新渲染),因为它和以前是同一个对象。 React docs.
这里的解决方法是先复制状态作为一个新的对象:
const newCart = { ...cart };
或者更好的是,使用功能状态更新:
setCart(prevCart => {
const newCart = { ...prevCart };
// do stuff with newCart
return newCart;
});