React项目中TypeError: Cannot add property Quantity, object is not extensible错误的排查与修复咨询
Fix for TypeError: Cannot add property Quantity, object is not extensible
Let's break down what's causing your error and how to fix it step by step.
Key Issues in Your Code
- Nested Ref Structure: Your custom hook returns an array containing a ref, and you wrap that result in another
useRefinApp.jsx. This means you're not accessing the actual items array when trying to modify it. - Storing the Wrong Data: In your custom hook's
useEffect, you're stringifying the ref object itself (JSON.stringify(itemsInCart)) instead of the array insideitemsInCart.current. This stores a ref structure in localStorage, not your actual cart items. - Directly Modifying Non-Extensible Objects: Even if you fix the ref issue, if the objects from localStorage are non-extensible (e.g., frozen before storage), modifying them directly will throw an error.
Fixed Code
Step 1: Correct the Custom Hook (App.jsx)
Rewrite your custom hook to properly manage the ref and localStorage, following React's custom hook conventions:
import { useRef, useEffect } from 'react'; // Custom hooks should start with "use" const useItemsCartWithLocalStorage = (storageKey) => { // Initialize ref with localStorage data or empty array const itemsInCartRef = useRef(JSON.parse(localStorage.getItem(storageKey)) || []); useEffect(() => { // Save the actual array (ref.current) to localStorage localStorage.setItem(storageKey, JSON.stringify(itemsInCartRef.current)); }, [itemsInCartRef.current, storageKey]); return itemsInCartRef; }; function App() { // Get the ref directly from the hook (no extra useRef!) const itemsInCartRef = useItemsCartWithLocalStorage('itemsQuantityString'); return <Files itemsInCartRef={itemsInCartRef} />; }
Step 2: Update Files.jsx to Work with Correct Data
Instead of modifying objects in place, create new extensible copies with the Quantity property added using map:
const Files = ({ itemsInCartRef }) => { // Create a new array with copied objects, adding Quantity const updatedItems = itemsInCartRef.current.map(item => { // Spread existing properties and add the new Quantity field return { ...item, Quantity: 1 }; }); // Update the ref with the new array (if you need to persist this change) itemsInCartRef.current = updatedItems; // Rest of your component logic... };
Additional Notes
- Why
map? Spreading the original object into a new one creates an extensible copy, avoiding the "object is not extensible" error entirely. - Consider
useStatefor Reactive State: If your component needs to re-render when cart items change,useRefwon't trigger re-renders. Switching touseStateis better for reactive management:
Use it inconst useItemsCartWithLocalStorage = (storageKey) => { const [itemsInCart, setItemsInCart] = useState(() => JSON.parse(localStorage.getItem(storageKey)) || [] ); useEffect(() => { localStorage.setItem(storageKey, JSON.stringify(itemsInCart)); }, [itemsInCart, storageKey]); return [itemsInCart, setItemsInCart]; };App.jsx:
And update inconst [itemsInCart, setItemsInCart] = useItemsCartWithLocalStorage('itemsQuantityString'); return <Files itemsInCart={itemsInCart} setItemsInCart={setItemsInCart} />;Files.jsx:const updatedItems = itemsInCart.map(item => ({ ...item, Quantity: 1 })); setItemsInCart(updatedItems);
内容的提问来源于stack exchange,提问作者ExtraSun
相关产品推荐
相关产品推荐

