function is giving me an empty array even though the array is not empty

I am using Reactjs in a project. I have a component where I am fetching the unsplash api and getting all the data in state. I have consoled the data and I have got the data here. That’s fine check this code and then lets move forward.

import React,{useState} from 'react'
import { Controllers } from './Controllers'
import { Viewer } from './Viewer'
import axios from 'axios'
import {DndProvider} from 'react-dnd'
import { HTML5Backend } from 'react-dnd-html5-backend'

export const Home = () => {

    const [art, setArt]=useState([])   
   
    const fetchArt=async()=>{
        const res = await axios.get('https://api.unsplash.com/photos/?client_id=6PTwdXbHvJktVaOjlXJevpv0LJhpuhA5gE36W6DsJkA');
        const data = await res.data;
        // console.log(data);
        setArt(data);
    }

    // console.log(art);   // got the data here
   
    return (
        <DndProvider backend={HTML5Backend}>
            <div className='wrapper'>
                <div className='main-box'>
                    <Controllers fetchArt={fetchArt} art={art}/>                   
                    <Viewer art={art}/>             
                </div>
            </div>
        </DndProvider>        
    )
}

The next thing is I am passing this data or state which is an array of objects to another component as props and I did get the data in this component too. That is fine too, lets move forward.

now in the same component…I have a function where I am consoling the same data but I am unable to get the data here.

now the annoying part when I comment that console and then uncomment it again and then triggering the same function surprisingly I am getting the data in console. Please check the code and image here

this is my github link:

https://github.com/HamzaAnwar1998/tshirt-customizer-app-

import React,{useState} from 'react'
import { Icon } from 'react-icons-kit'
import {undo} from 'react-icons-kit/icomoon/undo'
import {redo} from 'react-icons-kit/icomoon/redo'
import front from '../images/front.png'
import back from '../images/back.png'
import {zoomIn} from 'react-icons-kit/feather/zoomIn'
import {useDrop} from 'react-dnd'

export const Viewer = ({art}) => {
    
    // console.log(art); //got the data here

    const [image, setImage]=useState(front);   
    
    const [droppedImages, setDroppedImages]=useState([]);    

    const [{isOver}, drop]=useDrop(()=>({
        accept:'div',
        drop:(item)=>addImageToShirt(item.id),
        collect:(monitor)=>({
            isOver: !!monitor.isOver()
        })
    }))

    const addImageToShirt=(id)=>{
        console.log(id);  // got the id
        // console.log(art);  // not getting the data but when I comment and then uncomment the same console.log
        // and then when I check the browser console I am surprisingly getting the data 
        const pictureList=art.filter(newArt=>id===newArt.id);
        console.log(pictureList); // I am stuck in an really annoying issue &
        // that is console.log(pictureList) is giving me an empty array array(0) but when I comment
        // this console.log statement and then uncomment it again then in browser I will
        // get my data in console.log as array(1)       
        setDroppedImages((droppedImages)=>[...droppedImages,pictureList[0]]);
    }    

    return (
        
        <div className='viewer-box'>            
            <div className='undo-redo-box'>
                <div className='box'>
                    <div className='icon'>
                        <Icon icon={undo} size={22}/>
                    </div>
                    <div className='text'>undo</div>
                </div>
                <div className='box disabled'>
                    <div className='icon'>
                        <Icon icon={redo} size={22}/>
                    </div>
                    <div className='text'>redo</div>
                </div>
            </div>
            
            <div className='img' ref={drop}>
                <img src={image}/>
                {/* <>{droppedImages.map(img=>(
                    <div key={img.id}>
                        <img src={img.urls.full} style={{width:150+'px'}}/>
                    </div>
                ))}</> */}
            </div>
            <div className='functionalities-box'>
                <div className='box' onClick={()=>setImage(front)}>
                    <div className='icon-img'>
                        <img src={front}/>
                    </div>
                    <div className='text active'>Front</div>
                    {image===front&&(<div className='underline'></div>)}
                </div>
                <div className='box' onClick={()=>setImage(back)}>
                    <div className='icon-img'>
                        <img src={back}/>
                    </div>
                    <div className='text'>Back</div>
                    {image===back&&(<div className='underline'></div>)}
                </div>
                <div className='box'>
                    <div className='icon'>
                        
                    </div>
                    <div className='text active'>Sleeve Design</div>
                </div>
                <div className='box'>
                    <div className='icon'>
                        <Icon icon={zoomIn} size={22}/>
                    </div>
                    <div className='text active'>Zoom</div>
                </div>
            </div>
        </div>
    )
}

Answer

You have to provide the array of dependencies when you use useDrop hook, when you do not provide it, the variable art will not be updated, I recommend you take a look at information about how closure works on javascript:

    const [{isOver}, drop]=useDrop(()=>({
        accept:'div',
        drop:(item)=>addImageToShirt(item.id),
        collect:(monitor)=>({
            isOver: !!monitor.isOver()
        })
    }), [art])