TINTIN
TINTIN

Reputation: 183

React Hooks: Can't access updated useState variable outside useEffect?

I am new to react and creating react app , in this app , food items can be drag to order list using react dnd , the problem i am facing is i am not able to get the updated OrderList variable in any function outside the useEffect,

in the addFoodToOrderList , useEffect ,I am printing the same OrderList variable but in addFoodToOrderList the output is empty , I know useState is async function but while adding 3rd item to order list it should show at least first 2 item but its giving empty array(0) as output , case is different for useEffect

code :

export default function FoodCardContainer() {
    const [liked,setLiked] = useState("")
    
    function handleLike(e) {
        setLiked(prevNotes => {
            return [...prevNotes,e];
          });
      }
    const [orderList, setOrderList] = useState([]);
      
    const [{ isOver }, drop] = useDrop(() => ({
        accept: "div",
        drop: (item) => {
         addFoodToOrderList(item.id)},
        collect: (monitor) => ({
          isOver: !!monitor.isOver(),
        }),
      }));
    
    const addFoodToOrderList = (id) => {
       const orderItem = fooditems.filter((f) => id === f._id)
       setOrderList((preorderLists) => {return [...preorderLists,orderItem[0]]});
       console.log("this one outside useEffect",orderList)
      };
   
   useEffect(() => {
     console.log("this one inside useEffect",orderList)
    },[orderList])

my console:

enter image description here

Upvotes: 3

Views: 1165

Answers (1)

Giorgi Moniava
Giorgi Moniava

Reputation: 28654

It seems that function passed to drop was memoized and never updated. The docs mention this as parameters to the useDrop:

deps A dependency array used for memoization. This behaves like the built-in useMemoReact hook. The default value is an empty array for function spec, and an array containing the spec for an object spec.

Since you provided function spec, it defaulted to empty array as deps.

So you should specify deps.

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

Upvotes: 4

Related Questions