React数组渲染图片、解决key警告及代码优化方法
Hey there! Let's work through your questions step by step to get your React component working as expected and clean up those warnings.
Fixing the "Unique Key Prop" Warning
That warning pops up because React needs a unique key prop to track each item in a list efficiently—this helps it update the DOM correctly without unnecessary re-renders.
In your code, just add a key to the outermost <div> of each list item. Use a unique value from your inventory data (like serial or tag, since those are unique identifiers):
<div key={item.serial}> {/* rest of your item content */} </div>
Rendering Images Correctly
The issue with your image is the extra quotes around { item.image } in the src attribute. In JSX, when you use curly braces to insert a JavaScript variable, you don't need to wrap it in quotes—those quotes turn the variable into a literal string, so React is trying to load an image from the URL "{ item.image }" instead of the actual URL stored in item.image.
Fix it by removing the quotes, and add an alt attribute (this is required for accessibility and will prevent another warning):
<img src={item.image} alt={`Inventory item: ${item.name}`} />
You can also add an onError handler to show a fallback image if the original fails to load:
<img src={item.image} alt={`Inventory item: ${item.name}`} onError={(e) => e.target.src = 'https://via.placeholder.com/150?text=Image+Unavailable'} />
Optimizing Your Component
Let's refactor your class component to a modern function component with Hooks (React's recommended approach now), add loading/error states, and clean up the code:
import React, { useState, useEffect } from 'react'; import axios from 'axios'; const Inventory = () => { // State for inventory data, loading status, and errors const [inventory, setInventory] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); // Fetch data when component mounts useEffect(() => { const fetchInventory = async () => { try { const response = await axios.get('https://app.subarnanto.com/api/inventory'); setInventory(response.data); } catch (err) { setError('Oops! Failed to load inventory data.'); console.error('Fetch error:', err); } finally { setIsLoading(false); } }; fetchInventory(); }, []); // Empty dependency array means this runs once on mount // Show loading state while data is being fetched if (isLoading) return <div>Loading inventory items...</div>; // Show error message if fetch fails if (error) return <div className="error-message">{error}</div>; // Render a single inventory item (extract this for cleaner code) const renderInventoryItem = (item) => ( <div key={item.serial} className="inventory-item"> <h4>Nama: {item.name}</h4> <h4>Nomor Seri: {item.serial}</h4> <h4>ID Tag: {item.tag}</h4> <img src={item.image} alt={`${item.name} (Serial: ${item.serial})`} onError={(e) => e.target.src = 'https://via.placeholder.com/150?text=No+Image'} className="inventory-image" /> </div> ); // Render all inventory items return ( <div className="inventory-container"> {inventory.map(renderInventoryItem)} </div> ); }; export default Inventory;
Key improvements here:
- Function Component + Hooks: Replaces the class component with
useState(for state management) anduseEffect(for side effects like data fetching) — this makes the code shorter and easier to follow. - Loading/Error States: Gives users feedback while data loads, or if something goes wrong (instead of just showing an empty page).
- Extracted Render Function:
renderInventoryItemmakes the main return block cleaner and keeps related logic together. - Accessibility & Robustness: Added proper
alttext for images and a fallback for broken image links. - Cleaner Async Code: Used
async/awaitinstead of.then()for more readable promise handling.
内容的提问来源于stack exchange,提问作者Eko Andri

