React Modal添加项后列表不自动更新问题求助
问题:添加商品后列表无法自动更新
我通过React Context管理商品列表,用Modal组件添加新项,但添加完成关闭Modal后,列表不会自动刷新显示新商品。
CartProvider 代码
import React, { useState } from "react"; const CartContext = React.createContext({ items: [], name_category: "", information_category: "", image_category: null, addItem: (item) => {}, removeItem: (id) => {}, }); const CartProvider = (props) => { const [cartItems, setCartItems] = useState([]); const addItemHandler = (item) => { setCartItems((prevItems) => { return [...prevItems, item]; }); }; const removeItemHandler = (id) => { setCartItems((prevItems) => { return prevItems.filter((item) => item.id !== id); }); }; const cartContext = { name_category: "", information_category: "", image_category: null, items: cartItems, addItem: addItemHandler, removeItem: removeItemHandler, }; return ( <CartContext.Provider value={cartContext}> {props.children} </CartContext.Provider> ); }; export { CartProvider, CartContext };
Categories(CartModal)代码
import React, { useContext, useState } from "react"; import { GrCloudUpload, GrAddCircle } from "react-icons/gr"; import { IoIosAddCircleOutline } from "react-icons/io"; import Modal from "../../UI/Modal"; import { CartContext } from "@/store/CartProvider"; const Categories = (props) => { const [enteredName, setEnteredName] = useState(""); const [enteredImageUrl, setEnteredImageUrl] = useState(""); const [enteredDescription, setEnteredDescription] = useState(""); const [items, setItems] = useState([]); // 冗余状态 const [showModal, setShowModal] = useState(false); const cartContext = useContext(CartContext); const showModalHandler = () => { setShowModal(true); }; const closeModalHandler = () => { setShowModal(false); }; const nameInputChangeHandler = (event) => { setEnteredName(event.target.value); }; const imageUrlInputChangeHandler = (event) => { setEnteredImageUrl(event.target.value); }; const descriptionInputChangeHandler = (event) => { setEnteredDescription(event.target.value); }; const restForm = () => { setEnteredName(""); setEnteredImageUrl(""); setEnteredDescription(""); }; const AddHandleClick = () => { const newItem = { id: Math.random().toString(), name: enteredName, imageUrl: enteredImageUrl, description: enteredDescription, }; cartContext.addItem(newItem); setItems(cartContext.items); // 无效的同步操作 restForm(); closeModalHandler(); }; return ( <div className="grid grid-cols-3 gap-4 place-items-stretch h-56"> {/* 列表渲染依赖本地items */} <div> {items.length > 0 && items.map((item) => ( <div key={item.id}> <h2>{item.name}</h2> </div> ))} </div> <button onClick={showModalHandler} className="flex border-2 border-[#F8B162] rounded-lg h-[6rem] w-[10rem] justify-center items-center" > <IoIosAddCircleOutline style={{ color: "#F8B162" }} className="w-[5rem] h-[5rem] self-center" /> </button> {showModal && ( <Modal onClose={closeModalHandler}> <form> <div className="flex flex-col items-center justify-center space-y-4"> <input type="text" placeholder="Item name" value={enteredName} onChange={nameInputChangeHandler} className="w-full p-2 border border-gray-300 rounded-md" /> <input type="text" placeholder="Image URL" value={enteredImageUrl} onChange={imageUrlInputChangeHandler} className="w-full p-2 border border-gray-300 rounded-md" /> <textarea placeholder="Item description" value={enteredDescription} onChange={descriptionInputChangeHandler} className="w-full p-2 border border-gray-300 rounded-md" /> <button onClick={AddHandleClick} className="px-4 py-2 font-medium text-white bg-blue-500 rounded-md" > Add to Cart </button> </div> </form> </Modal> )} </div> ); }; export default Categories;
问题原因
- 本地状态冗余且不同步:你在
Categories里额外声明了items状态,这个状态和Context中的cartContext.items完全独立。调用cartContext.addItem后,Context里的cartItems会异步更新,但你立刻调用setItems(cartContext.items)拿到的还是旧值,导致本地状态没跟上Context的变化。 - 渲染依赖错误:列表渲染用的是本地
items而不是Context里的cartContext.items,所以即使Context更新了,组件也不会重新渲染列表。
修复方案
步骤1:删除冗余的本地状态
删掉Categories里的const [items, setItems] = useState([]);,不需要维护本地副本。
步骤2:直接用Context数据渲染列表
把列表渲染部分改成依赖cartContext.items:
<div> {cartContext.items.length > 0 && cartContext.items.map((item) => ( <div key={item.id}> <h2>{item.name}</h2> </div> ))} </div>
步骤3:移除无效的同步代码
在AddHandleClick里删掉setItems(cartContext.items);,现在直接用Context的数据,不需要手动同步。
修改后的AddHandleClick:
const AddHandleClick = () => { const newItem = { id: Math.random().toString(), name: enteredName, imageUrl: enteredImageUrl, description: enteredDescription, }; cartContext.addItem(newItem); restForm(); closeModalHandler(); };
这样修改后,当Context里的商品列表更新时,Categories组件会自动感知到变化并重新渲染列表,添加新商品后就能立刻显示了。
内容的提问来源于stack exchange,提问作者Zakaria Zhlat
相关产品推荐
相关产品推荐

