React Native中如何单独修改Bookmark图标的状态?
Hey there! Let’s get that bookmark toggle sorted for your dynamically loaded product cards—no more all-icons-switching-at-once chaos. The main problem here is that you’re probably using a single global state to track bookmark status, which is why every card reacts when you click one. Here’s how to fix it:
Instead of a single boolean like isBookmarked, use a collection (like a Set or object) that maps product IDs to their bookmarked state. This way, we only track which specific products are bookmarked, not a global "all or nothing" state.
For example, if you’re using React:
// Initialize state with an empty Set to store bookmarked product IDs const [bookmarkedIds, setBookmarkedIds] = useState(new Set());
If you’re using vanilla JavaScript, just declare a Set in your scope:
const bookmarkedIds = new Set();
Modify your click handler to accept the product’s unique ID, then add or remove that ID from your state collection:
React Version
const handleBookmarkToggle = (productId) => { setBookmarkedIds(prevState => { const updatedIds = new Set(prevState); // Toggle the ID in the Set updatedIds.has(productId) ? updatedIds.delete(productId) : updatedIds.add(productId); return updatedIds; }); };
Vanilla JS Version
const handleBookmarkToggle = (event) => { const productId = event.target.dataset.productId; // Grab ID from data attribute const button = event.target.closest('.bookmark-btn'); // Get the button element if (bookmarkedIds.has(productId)) { bookmarkedIds.delete(productId); // Swap to empty bookmark icon button.innerHTML = '<svg class="bookmark-empty">...</svg>'; } else { bookmarkedIds.add(productId); // Swap to filled bookmark icon button.innerHTML = '<svg class="bookmark-filled">...</svg>'; } };
When rendering each product card, check if its ID is in your bookmarkedIds collection to show the correct icon:
React Version
{products.map(product => ( <div key={product.id} className="product-card"> {/* Your product content goes here */} <button onClick={() => handleBookmarkToggle(product.id)} className="bookmark-btn" > {/* Show filled icon if ID is in the Set, else empty */} {bookmarkedIds.has(product.id) ? <Icon name="bookmark-filled" /> : <Icon name="bookmark-empty" /> } </button> </div> ))}
Vanilla JS (For Dynamically Loaded Cards)
When creating each product card dynamically, add the product ID as a data attribute and attach the click listener:
function createProductCard(product) { const card = document.createElement('div'); card.className = 'product-card'; const bookmarkBtn = document.createElement('button'); bookmarkBtn.className = 'bookmark-btn'; bookmarkBtn.dataset.productId = product.id; // Set initial icon state bookmarkBtn.innerHTML = bookmarkedIds.has(product.id) ? '<svg class="bookmark-filled">...</svg>' : '<svg class="bookmark-empty">...</svg>'; // Attach click handler bookmarkBtn.addEventListener('click', handleBookmarkToggle); card.appendChild(bookmarkBtn); // Add other product elements to the card... return card; }
The root issue was that you used a single state variable (like let isBookmarked = false) that every card checked. When you toggled that variable, every card re-evaluated it and updated their icon—hence all icons changed at once. By tying the state to each product’s unique ID, we ensure only the clicked card’s status gets flipped.
内容的提问来源于stack exchange,提问作者Riddhi

