Personal Catalogue: React & Firebase — Chapter 7, Exercise 2 ===================================================================== TASK Temporarily replace the onSnapshot listener in App.jsx with the earlier one-time getDocs() fetch, reproduce the stale-tags bug (edit a book's tags, go back, reopen it), and confirm the old tags are shown. Restore the listener and confirm the fix — with no other code changed anywhere. SOLUTION Temporary change in App.jsx: useEffect(() => { getDocs(collection(db, "items")).then((snapshot) => { setItems(snapshot.docs.map((d) => ({ id: d.id, ...d.data() }))); }); }, []); // (onSnapshot version commented out) Reproduction: 1. Open a Book's detail view. Its tags show: ['Python']. 2. Use TagEditor to add "Web Development". The console/Firestore viewer confirms the write succeeded — the document's own tags field is now ['Python', 'Web Development']. 3. Click "Back to list." 4. Reopen the same book's detail view. Observed (with getDocs()): The detail view shows tags: ['Python'] — the old value. The write genuinely happened, but items in React state was only ever populated once, on mount, and reopening the detail view just re-reads the same stale array already sitting in memory. Restore the onSnapshot version (revert the useEffect body only — no other file touched): useEffect(() => { const unsubscribe = onSnapshot(collection(db, "items"), (snapshot) => { setItems(snapshot.docs.map((d) => ({ id: d.id, ...d.data() }))); }); return () => unsubscribe(); }, []); Repeating the identical steps now shows tags: ['Python', 'Web Development'] immediately upon reopening the detail view — no other component was touched, confirming the fix lives entirely in how items gets populated, not in TagEditor or ItemDetail themselves. WHY THIS WORKS AS AN ANSWER ---------------------------- It reproduces the bug with the specific naive code the chapter describes, records the real stale result, then restores only the one useEffect body the chapter names and confirms the fix without touching any other file — directly demonstrating that the fix is isolated to how data flows into the app, not to any individual component's own logic.