in checkOut js im unable to access the data inside the items arrey but i can access the length how is it possible i added 3 items i can see the items.lenth but when try to use items.map its not working showing error:
TypeError: Cannot read properties of undefined (reading 'image')
store.ts
import { configureStore } from "#reduxjs/toolkit";
import basketReducer from "./basketSlice";
//this is redux like a global store to store users items data
//when users put the items in the shopping cart
export const store = configureStore({
reducer: {
basket: basketReducer,
},
});
busketSlice.ts
import { createSlice } from "#reduxjs/toolkit";
interface BasketItem {
id: string;
title: string;
image: string;
description: string;
price: number;
category: string;
}
const initialState = {
items: [] as BasketItem[],
};
export const basketSlice = createSlice({
name: "basket",
initialState,
reducers: {
addToBasket: (state, action) => {
state.items = state.items.concat(action.payload);
},
removeFromBasket: (state, action) => {
const index = state.items.findIndex((basketItem: any) => basketItem.id === action.payload.id)
let newBasket = [...state.items];
if (index >= 0){
//if item exists in the basket remove it ...
newBasket.splice(index, 1);
} else {
console.warn(`cant remove (id: ${action.payload.id}) because its not in busket`)
}
state.items = newBasket;
},
},
});
export const { addToBasket, removeFromBasket } = basketSlice.actions;
// Selectors - This is how we pull information from the Global store slice
export const selectItems = (state: any) => state.basket.items;
export const selectTotal = (state: any) => state.busket.items.reduce((total:any, item:any) => total + item.price, 0);
const basketReducer = basketSlice.reducer;
export default basketReducer;
Cards.tsx
import Image from 'next/image';
import React, { useEffect, useState } from 'react';
import { StarIcon } from '#heroicons/react/solid';
// import Currency from 'react-currency-formatter';
import { useDispatch } from 'react-redux';
import { addToBasket } from "../basketSlice"
export default function Cards({id,title,image,description,price,category}: any) {
const dispatch = useDispatch()
const addItemsToBusket = () => {
const product = {
id,title,image,description,price,category
}
dispatch(addToBasket(product))//sending the product as an action to the redux store
}
const [rating, set] = useState(5);
const [hasPrime, setH] = useState(Math.random() < 1)
useEffect(() => {
set(Math.floor(Math.random() * 5) + 1 );
}, [])
useEffect(() => {
setH(Math.random() < 0.5 );
}, [])
return (
<div className="relative z-30 flex flex-col p-10 m-5 bg-white ">
<p className='absolute text-xs italic right-2 top-2'>{category}</p>
<Image className='mx-auto' src={image} height={200} width={200} alt=""/>
<h4 className='my-3'>{title}</h4>
<div className='flex'>
{Array(rating).fill(rating).map((_, i) => (
<StarIcon key={i} className='h-6 text-yellow-500'/>
))}
</div>
<p className='my-2 text-xs line-clamp-2 '>{description}</p>
<div>
{/* <Currency quantity={props.price} currency="INR"/> */}
<p className='mb-5'>₹{price}</p>
</div>
{hasPrime && (
<div className='flex items-center -mt-5 space-x-2'>
<img
className='w-12'
src="https://links.papareact.com/fdw" alt="" />
<p className='text-xs text-gray-500'>Free Next-Day Delivary</p>
</div>
)}
<button onClick={addItemsToBusket} className='mt-auto button'>Add to Busket</button>
</div>
)
}
ProductsFeed.tsx
import React from 'react'
import Cards from './Cards'
export default function({ products }: any) {
return (
<div className="grid grid-flow-row-dense mx-auto md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 md:-mt-40 lg:-mt-52">
{products.slice(0,4).map((product: any) => (
<Cards
key={product.id}
id={product.id}
title={product.title}
price={product.price * 60}
description={product.description}
category={product.category}
image={product.image}
/>
))}
<img className="md:col-span-full" src="https://links.papareact.com/dyz" alt="" />
<div className='md:col-span-2'>
{products.slice(4,5).map((product: any) => (
<Cards
key={product.id}
id={product.id}
title={product.title}
price={product.price * 60}
description={product.description}
category={product.category}
image={product.image}
/>
))}
</div>
{products.slice(5, products.length).map((product: any) => (
<Cards
key={product.id}
id={product.id}
title={product.title}
price={product.price * 60}
description={product.description}
category={product.category}
image={product.image}
/>
))}
</div>
)
}
checkout.tsx
import React from 'react'
import Nav from '../components/Nav'
import { signIn, signOut, useSession } from "next-auth/react"
import { useSelector } from 'react-redux';
import { selectItems } from '../basketSlice';
import CheckOutProduct from '../components/CheckOutProduct';
export default function CheckOut() {
const { data: session } = useSession()
const items = useSelector(selectItems);
console.warn(items)
return (
<div className='h-screen bg-gray-100'>
<Nav />
<main>
{!session? (
<div>
<div className='flex items-center justify-start p-10 m-10 space-x-4 overflow-hidden bg-white md:space-x-10'>
<img src="/checkout.svg" className='h-[7rem] w-[7rem] sm:w-[15rem] sm:h-[15rem]' alt=""/>
<div className=''>
<h1 className='font-bold md:text-[2rem] mb-1'>Your Amazon Cart is empty</h1>
<p className='text-[#007185] hover:text-red-600 cursor-pointer hover:underline hover'>Shop today's deals</p>
<button
className='px-10 py-2 mt-4 button'
onClick={() => signIn()}>Sign in to your account</button>
</div>
</div>
<div className=' h-[5rem] bg-white mx-10' />
</div>
): (
<div>
<div className='flex items-center justify-start p-10 m-10 space-x-4 overflow-hidden bg-white md:space-x-10'>
<img src="/checkout.svg" className='h-[7rem] w-[7rem] sm:w-[15rem] sm:h-[15rem]' alt=""/>
<div className=''>
<h1 className='font-bold md:text-[2rem] mb-1'>
{items.length === 0? "Your Amazon Cart is empty": "Shoping Basket"}
</h1>
<p className='text-[#007185] hover:text-red-600 cursor-pointer hover:underline hover'>Shop today's deals</p>
</div>
</div>
<div className='mx-10 bg-white '>
{items.length !== 0 && `You have ${items.length} items in your busket.`}
{items.map(({item, i}: any) => {
<CheckOutProduct
key={i}
image={item.image}
price={item.price}/>
})}
</div>
</div>
)}
</main>
</div>
)
}
checkOutProduct.tsx
import Image from 'next/image'
import React from 'react'
export default function CheckOutProduct({ id,title,image,description,price,category }: any) {
return (
<div className='grid grid-cols-5'>
<Image src={image} height={200} width={200} alt=""/>
<p>{price}</p>
</div>
)
}
Try to add like below because concat will not change object reference since updated values will not show in component.
addToBasket: (state, action) => {
state.items = [...state.items, ...action.payload];
}
Related
I am facing a hydration error when trying to add motion from framer-motion in any element from the file.
Without motion, everything works fine:
import { useRef, useState, useEffect } from 'react';
import { usePathname, useRouter } from 'next/navigation';
import Image from 'next/image';
import Link from 'next/link';
import { Icon, Dropdown, UserIcon } from '#ui';
import { menuItems } from '#utils/menu';
import useOutsideClick from '#hooks/useOutsideClick';
import { useAppDispatch, useAppSelector } from '#hooks/reduxHooks';
import { triggerCloseMenu } from 'redux/Slices/menuSlice';
import { motion } from 'framer-motion';
const Header = () => {
const [url, setUrl] = useState<string>('/images/logoLight.png');
const dispatch = useAppDispatch();
const close = () => {
dispatch(triggerCloseMenu());
};
const menuOpen = useAppSelector((state) => state.menu.menuOpen);
const wrapperRef = useRef(null);
const pathname = usePathname();
const router = useRouter();
useOutsideClick(wrapperRef, close);
useEffect(() => {
setUrl(
pathname === '/'
? !menuOpen
? '/images/logoLight.png'
: '/images/logoDark.png'
: '/images/logoDark.png',
);
}, [menuOpen, pathname]);
return (
<header
className="fixed top-0 z-50 w-screen bg-transparent "
ref={wrapperRef}
>
<nav className=" mx-auto flex w-full max-w-[2000px] items-center justify-between py-9 px-7 ">
<div className="flex items-center justify-center space-x-6">
<Icon />
<Image
src={url}
alt="logo_image"
width={120}
height={0}
className="mb-1"
onClick={() => {
router.push('/');
close();
}}
/>
</div>
<div className="relative flex items-center space-x-10">
<div className="hidden space-x-14 lg:flex">
{menuItems.map((i: Menu) => (
<Link
href={i.path}
key={i.id}
className={`${
pathname !== i.path ? 'font-normal' : 'font-extrabold'
}
text-lg text-white transition duration-300 ease-linear`}
>
{i.label}
</Link>
))}
</div>
<UserIcon />
</div>
</nav>
<Dropdown />
</header>
);
};
export default Header;
But if I replace with <motion.header> </motion.header> I am getting this error : Error: Hydration failed because the initial UI does not match what was rendered on the server.
I am using latest version of Nextjs (without app directory), and framer-motion v8
I'm trying to fetch data dynamically according to user choice, here I'm using getServerSide props inside pages/newsPages/[category].tsx
error pointing towards this:
TypeError: Cannot read properties of null (reading 'useContext')
46 export async function getServerSideProps(context: any) {
> 47 | const router = useRouter();
| ^
import { useRouter } from 'next/router'
import React, { useState } from 'react'
import Feeds from '../../components/Feeds'
import Header from '../../components/Header'
export default function category({ newsCategory }:any) {
const [date, setDate] = useState(new Date())
return (
<div className='bg-gray-100'>
<Header />
<main className='mx-5 my-5'>
<div className='bg-white'>
<div className='flex justify-between p-4'>
<h1 className='text-sm font-bold md:text-2xl'>Wellcome to clone BBC.com</h1>
<h1 className='text-sm font-bold md:text-2xl'>{date.toDateString()}</h1>
</div>
{newsCategory.articles.slice(0, 1).map((article:any )=> (
<a key={article.url} href={article.url}
className="relative">
<img className='w-full' src={article.urlToImage ? article.urlToImage: "./ALT.jpg"} alt="" />
<h1
className='text-white absolute bottom-[40%] left-[5%]
lg:text-2xl text-xl'>{article.title}</h1>
<p className='text-white absolute bottom-[30%] left-[5%] line-clamp-1'>{article.description}</p>
</a>
))}
<div className='grid grid-flow-row-dense md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4'>{/*grid start*/}
{newsCategory.articles.slice(1, newsCategory.articles.length).map((article: any) => (
<Feeds
url={article.url}
className=""
key={article.url}
urlToImage={article.urlToImage}
title={article.title}
description={article.description}
/>
))}
</div>
</div>
</main>
</div>
)
}
export async function getServerSideProps(context: any) {
const router = useRouter();
const { category } = router.query
const newsCategory = await fetch(`https://newsapi.org/v2/top-headlines?country=us&category=${category}&apiKey=${process.env.API_KEY}`)
.then(res => res.json())
return {
props: {
newsCategory,
}
}
}
pages/index.tsx
import Head from 'next/head'
import Header from '../components/Header';
import NewsFeed from '../components/NewsFeed';
export default function Home({ news }: any) {
return (
<div className='bg-gray-100 '>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<Header />
<main className='mx-5 my-5'>
<NewsFeed news={news} key={news.article}/>
</main>
</div>
)
}
export async function getServerSideProps(context: any) {
const news = await fetch("https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=")
.then(res=>res.json());
return {
props: {
news,
}
}
}
header.tsx
pushing to the newspages
<p className='hidden hover:text-blue-500 sm:inline-flex'
onClick={()=> router.push("/")}>Home</p>
<p className='hidden hover:text-blue-500 sm:inline-flex'
onClick={()=> router.push("/newsPages/general")}>News</p>
<p className='hidden hover:text-blue-500 sm:inline-flex'
onClick={()=> router.push("/newsPages/sports")}>Sport</p>
<p className='hidden hover:text-blue-500 sm:inline-flex'
onClick={()=> router.push("/newsPages/entertainment")}>Reel</p>
<p className='hidden hover:text-blue-500 sm:hidden lg:inline-flex'
onClick={()=> router.push("/newsPages/health")}>Worklife</p>
<p className='hidden hover:text-blue-500 sm:hidden lg:inline-flex'
onClick={()=> router.push("/newsPages/science")}>Science</p>
<p className='hidden hover:text-blue-500 sm:hidden lg:inline-flex'
onClick={()=> router.push("/newsPages/future")}>Future</p>
what I did wrong here, can I use getServerSideProps in multiple files inside the pages folder? why here this error occurs,
EXPLANATION OF THE PHOTOS AND CODE BELOW
In the following component (CODE BELOW) I am trying to achieve something like in the screenshot 1 (Where the availableList, the data, is passed from the parent component but it shows an empty space before the data passed) but as soon as I select the data (screenshot 2), and I click again, the drop-down does not show the empty space as I had in the screenshot 1, because I am now in the currentItem -selectItem. By doing what I did in the below code the drop-down is moved up. I am wondering what would be the best strategy to achieve (point 1 in point 3 too) and avoid this movement of the div UP or let it be in place of the actual selection.
import { FC, useEffect, useState } from 'react';
import {
Select,
SelectContent,
SelectItem,
SelectItemText,
SelectPortal,
SelectScrollUpButton,
SelectTrigger,
SelectValue,
SelectViewport
} from '#radix-ui/react-select';
import { ChevronUpIcon, ChevronDownIcon } from '#heroicons/react/outline';
import cn from 'classnames';
import { twMerge } from 'tailwind-merge';
interface BatchSelectorClassNames {
loadingClassName?: string;
formButtonClassName?: string;
selectedItemClassName?: string;
selectContentClassName?: string;
selectItemListClassName?: string;
className?: string;
}
export interface SelectChoice {
value: string;
label: string;
}
interface Props {
defaultValue?: string;
onChange?: (value: string) => void;
classNames?: BatchSelectorClassNames;
data: SelectChoice[];
name?: string;
disabled?: boolean;
value?: string;
}
const Selector: FC<Props> = ({
defaultValue,
onChange,
classNames,
data,
name,
disabled,
value
}) => {
const [currentItem, setCurrentItem] = useState<SelectChoice | undefined>(
undefined
);
const [availableList, setAvailableList] = useState<SelectChoice[]>([]);
const [opened, onOpenChange] = useState<boolean>(false);
const selectTriggerProps = {
className: twMerge(
cn(
'group flex items-center h-12 select-none rounded-lg bg-white px-4 text-left shadow-plain',
classNames?.className,
classNames?.formButtonClassName,
{
'group hover:shadow-plain-lg cursor-pointer': !disabled,
'stroke-inpay-black-haze-700 stroke-1.5 group hover:none text-inpay-black-haze-700':
disabled
}
)
)
};
const selectedItemProps = {
className: twMerge(
cn(
'group flex h-12 cursor-pointer items-center px-4 rounded-t-lg outline-offset-[-1px] hover:bg-inpay-green-200 hover:text-inpay-green-700 border-none focus:outline-none',
classNames?.className,
classNames?.selectedItemClassName,
{
'px-4': disabled
}
)
)
};
const selectItemListProps = {
className: twMerge(
cn(
'group h-12 flex items-center cursor-pointer px-4 outline-offset-[-1px] first:rounded-t-lg last:rounded-b-lg hover:bg-inpay-green-200 hover:text-inpay-green-700 border-none focus:outline-none',
classNames?.className,
classNames?.selectItemListClassName
)
)
};
const selectContentProps = {
className: twMerge(
cn(
'relative z-50 select-none overflow-hidden rounded-lg bg-white shadow-plain-lg w-72',
classNames?.selectContentClassName
)
)
};
const onValueChange = (value: string) => {
if (data) {
const matchingValue = data.find((element) => element.value == value);
if (matchingValue) {
setCurrentItem({ ...matchingValue });
setAvailableList(data.filter((i) => i.value != matchingValue.value));
onChange && onChange(value);
}
}
};
useEffect(() => {
setAvailableList(data);
setCurrentItem(undefined);
}, [data]);
useEffect(() => {
if (defaultValue) {
const newValue = data.find((i) => i.value === defaultValue);
if (newValue) {
setCurrentItem(newValue);
} else {
setCurrentItem(newValue);
}
setAvailableList(data.filter((i) => i.value != defaultValue));
}
}, [defaultValue, data]);
return (
<Select
onValueChange={onValueChange}
onOpenChange={onOpenChange}
name={name}
disabled={disabled}
defaultValue={defaultValue || ''}
value={value}
>
<SelectTrigger {...selectTriggerProps}>
<SelectValue />
</SelectTrigger>
<SelectPortal>
<SelectContent {...selectContentProps}>
<SelectScrollUpButton className="flex justify-center">
<ChevronUpIcon className="h-10 w-6 stroke-1.5" />
</SelectScrollUpButton>
<SelectViewport>
{currentItem && (
<div>
<SelectItem
key={null}
disabled
value=""
{...selectItemListProps}
>
<SelectItemText>
<div className="flex">
<div className="flex-1"></div>
{opened ? (
<ChevronUpIcon className="w-1/12 stroke-inpay-black-500 stroke-1.5" />
) : (
<ChevronDownIcon
className={cn(
'w-1/12 stroke-inpay-black-haze-700 stroke-1.5',
{
'w-1/12 stroke-inpay-black-haze-700 stroke-1.5 group-hover:stroke-inpay-black-500':
!disabled
}
)}
/>
)}
</div>
</SelectItemText>
</SelectItem>
<SelectItem
key={currentItem.value}
value={currentItem.value}
{...selectedItemProps}
>
<SelectItemText>
<div className="flex">
<div className="flex-1">{currentItem.label}</div>
</div>
</SelectItemText>
</SelectItem>
</div>
)}
{!currentItem && (
<SelectItem key={null} disabled value="" {...selectItemListProps}>
<SelectItemText>
<div className="flex">
<div className="flex-1"></div>
<ChevronDownIcon className="w-1/12 stroke-inpay-black-500 stroke-1.5" />
</div>
</SelectItemText>
</SelectItem>
)}
{/* {opened && (
<SelectItem key={null} disabled value="" {...selectItemListProps}>
<SelectItemText>
<div className="flex">
<div className="flex-1"></div>
</div>
</SelectItemText>
</SelectItem>
)} */}
{availableList.map((item) => (
<SelectItem
key={item.value}
value={item.value}
{...selectItemListProps}
>
<SelectItemText>
<div className="flex">
<div className="flex-1">{item.label}</div>
</div>
</SelectItemText>
</SelectItem>
))}
</SelectViewport>
</SelectContent>
</SelectPortal>
</Select>
);
};
export default Selector;
Sticker.ts
import React from "react";
import Image from "next/image";
import {GetServerSideProps, InferGetServerSidePropsType } from 'next';
import Product from "models/Product";
import currencyFormatter from "lib/currencyFormatter";
import mongoose from "mongoose";
import handler from "pages/api/pincode";
// const Sticker = (props: any) => {
const Sticker = ({products}) => {
// const products = JSON.parse((props?.products));
console.log("list of product "+ products)
return (
<div>
<section className="text-gray-600 body-font">
<div className="container px-5 py-24 mx-auto">
<div className="flex flex-wrap -m-4 justify-centr">
{/* {products?.map((dt: any, idx: number) => */}
{/* <div className="lg:w-1/4 md:w-1/2 p-4 w-full" key={idx}> */}
<div className="lg:w-1/4 md:w-1/2 p-4 w-full" >
{/* <a href={`./product/${dt?.category}/${dt?.id}`} className="block relative h-68 rounded overflow-hidden"> */}
<a href="./product/{category}/slug[jhbjh]" className="block relative h-68 rounded overflow-hidden">
<Image
alt="ecommerce"
className="object-cover cursor-pointer object-center w-full h-full block"
src="https://m.media-amazon.com/images/I/61SFAM62ucL._SL1280_.jpg"
width="100"
height="100"
/>
</a>
<div className="mt-4">
<h3 className="text-gray-500 text-xs tracking-widest title-font mb-1">
Home Decor
</h3>
<h2 className="text-gray-900 title-font text-lg font-medium">
Paper Plane Design Quote and Motivational Posters 12X18
</h2>
<p className="mt-1">{currencyFormatter(179)}</p>
</div>
</div>
{/* )} */}
</div>
</div>
</section>
</div>
);
};
export async function getServerSideProps(context) {
if(!mongoose.connections[0].readyState){
await mongoose.connect(process.env.MONGO_URI)
}
let products = await Product.find()
return {
// props: { products },
props: { products : JSON.parse(JSON.stringify(products)) },
}
}
export default Sticker;
_app.tsx
import React, { useEffect, useState } from 'react'
import { NextUIProvider, useSSR } from '#nextui-org/react';
import '../styles/globals.css'
import Navbar from '../modules/body/Navbar';
import Footer from '../modules/body/Footer';
import theme from "../themes";
import { AppProps } from 'next/app';
// import SideNavbar from '../mainComponent/SideNavbar'
function MyApp({ Component, pageProps }: AppProps) {
const [cart, setCart] = useState<object>({})
const [subTotal, setSubTotal] = useState<number>(0)
const { isBrowser } = useSSR();
useEffect(() => {
try {
if (localStorage.getItem("cart")) {
setCart(JSON.parse(localStorage.getItem("cart") || ""))
saveCart(JSON.parse(localStorage.getItem("cart") || ""))
}
} catch (error) {
console.log(error);
localStorage.clear()
}
}, [])
const saveCart = (myCart: object) => {
localStorage.setItem("cart", JSON.stringify(myCart))
// let keys = Object.keys(myCart);
const subt = Object.values(myCart).reduce((acc, curr) => acc + curr?.price * curr?.qty,0);
setSubTotal(subt)
}
const addToCart = (itemCode, qty, price, name, size, variant) => {
let newCart = cart;
if (itemCode in cart) {
newCart[itemCode].qty = cart[itemCode].qty + qty
}
else {
newCart[itemCode] = { qty: 1, price, name, size, variant }
}
setCart(newCart)
saveCart(newCart)
}
const removeFromCart = (itemCode, qty, price, name, size, variant) => {
let newCart = JSON.parse(JSON.stringify(cart));
if (itemCode in cart) {
newCart[itemCode].qty = cart[itemCode].qty - qty
}
if (newCart[itemCode]["qty"] <= 0) {
delete newCart[itemCode]
}
setCart(newCart)
saveCart(newCart)
}
const clearCart = () => {
setCart({})
saveCart({})
}
return isBrowser && (
<NextUIProvider theme={theme}>
<Navbar key={subTotal} cart={cart} addToCart={addToCart} removeFromCart={removeFromCart}
clearCart={clearCart} subTotal={subTotal} />
{/* <SideNavbar /> */}
<Component cart={cart} addToCart={addToCart} removeFromCart={removeFromCart}
clearCart={clearCart} subTotal={subTotal} {...pageProps} />
<Footer />
</NextUIProvider>
)
}
export default MyApp
I tried every method posted on the browser but still it shows undefined. If you help me to find out the solution of this problem then i will be very happy and feel blessed with this coding environment. please solve this as soon as possible. My whole project is stucked because of this error.
This is my first time I am asking question here. If I make any mistake, sorry from now on. I've been trying to build infinite scroll bar with 3 columns. But when the next data is fetched, the images act really weird. I've tried almost everything like "fixed, flex-nowrap", etc.. with tailwind. But none of them worked. I also made research almost for 3 hours and couldn't find any helpful resources. I'd be glad if you could help me!
video: https://streamable.com/ouk16y
import React, { useState, useEffect } from "react";
import InfiniteScroll from "react-infinite-scroll-component";
//components
//icons
import { AiOutlineHeart, AiOutlinePlus } from "react-icons/ai";
//styling
const Gallery = () => {
const apiKey = "apiKey";
const [pictures, setPictures] = useState([]);
const [page, setPage] = useState(1);
//fetching the api data
useEffect(() => {
fetch(
`https://api.unsplash.com/search/photos?page=${page}&query=office&client_id=${apiKey}`
)
.then((resp) => {
return resp.json();
})
.then((data) => {
const pictureData = [...new Set(data.results)];
setPictures((prev) => [...prev, ...pictureData]);
});
}, [page]);
return (
<InfiniteScroll
dataLength={pictures.length}
next={() => setPage((prev) => prev + 1)}
hasMore={true}
scrollThreshold={0.3}
>
<div className="columns-1 lg:columns-3 col-auto lg:w-5/6 mx-auto gap-8 space-y-4">
{pictures.map((picture) => (
<div className="" key={picture.id}>
<div className="flex p-2 lg:hidden ">
<img
className="rounded-full w-10 h-10"
src={picture.user.profile_image.medium}
alt={`${picture.name} profile`}
/>
<span className="pt-2 pl-2">{picture.user.name}</span>
</div>
<img className="resize-none" src={picture.urls.regular} />
{/* //icons for small devices// */}
<div className="flex mt-2 pl-2 mb-8 lg:hidden">
<AiOutlineHeart className="w-8 h-8 text-gray-600" />
<AiOutlinePlus className="w-8 h-8 ml-2 text-gray-600 " />
<button className="w-40 border ml-auto mr-4">Download</button>
</div>
</div>
))}
</div>
</InfiniteScroll>
);
};
export default Gallery;
'''