Intro
When my application starts, a list of images appear. If additional details about an image is required, a user can click on an image that has previously loaded, and a modal would appear with it's relevant details.
Even though everything works as it should, I'm encountering an error message that can be found in Chrome browser's console.
Error
Warning: Each child in a list should have a unique "key" prop.
Attempted
I've tried placing key={Math.floor(Date.now() * 20)}
within the Image
found in the modal, but that doesn't work.
Where am I going wrong? How can I fix this issue?
function getHomePage() {
const [token, setToken] = useState("");
const [visibility, setVisibility] = useState(false);
const [NFTBalances, setNFTBalances] = useState();
const [collection, setCollection] = useState();
const [nft, setNft] = useState();
const { Moralis } = useMoralis();
//load my images when application starts
useEffect(() => {
collectionChanged('myCollection');
}, []);
const handleSelectToken = async (num, col) => {
if (num && col) {
const dbNFTs = Moralis.Object.extend(col);
const query = new Moralis.Query(dbNFTs);
console.log(num);
query.equalTo("tokenId", num);
let selectedNFT = await query.first();
selectedNFT = selectedNFT.attributes;
console.log(selectedNFT);
setNft(selectedNFT);
setVisibility(true);
//open modal
$("#openModal").modal("show");
}
};
const addToNFTs = async (col) => {
const dbNFTs = Moralis.Object.extend(col);
const query = new Moralis.Query(dbNFTs);
query.ascending("rank");
query.limit(4);
const topNFTs = query.skip(NFTBalances.length);
const results = await topNFTs.find();
setNFTBalances(NFTBalances.concat(results));
}
return (
<>
//modal box
<div className="modal fade" id="openModal" tabIndex="-1" role="dialog" aria-hidden="true">
<div className="modal-dialog modal-lg" role="document">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div className="modal-body">
<div>
<Image key={Math.floor(Date.now() * 20)}
preview={false} src={nft.image} loading="lazy"
style={{ display: "block", width: "50%"}}/>
<p>{nft.details}</p>
</div>
</div>
</div>
</div>
</div>
<div className="col-xxl-3 col-xl-3 col-lg-3 col-md-3">
<div className="filter-sidebar">
<div className="filter-sidebar-content">
<div className="form-group">
//SEARCH BOX
<Search placeholder="Please search here"
onChange={(e) => setToken(e.target.value) }
onSearch={() => handleSelectToken(token, collection)} />
</div>
</div>
</div>
</div>
//Images populate when application loads
//Clicking an image will populate image details in a modal
<div className="row">
{NFTBalances && NFTBalances.map((nft, index) => {
return (
<div className="col-xxl-3 col-xl-3 col-lg-6 col-md-6">
<div className="card items">
<Card key={index} onClick={() =>
handleSelectToken(nft.attributes.tokenId,collection)}
cover={ <Image src={nft.attributes.image} /> }>
</Card>
</div>
</div>
);})}
</div>
</>
);}
export default getHomePage;