Randy_Johnson's avatar

ReactJS Callback Function not updating list!

I am using a call back function to update the array inside Dashboard, I confirmed that this is working by using a alert and I also confirmed that the array inside dashboard is updating by using a console.log(cart). But with all this confirmation, the visual cart is not showing the update inside ShopingCart. Now I have to dash out, and this is a major concern since I've been messing around with it for some hours now. Please can someone enlighten me. Should I use useEffect inside ShoppingCart to check? Please Help, must dash!

┌──────────────────────────────────────────────┐
│                                              │
│ DASHBOARD              ◄─────────────────────┼──┐
│                                              │  │
│  ┌────────────────────────────────────────┐  │  │
│  │                                        │  │  │
│  │ SHOW PRODUCTS                          │  │  │
│  │                                        │  │  │
│  │  ┌──────────────────────────────────┐  │  │  │
│  │  │                                  │  │  │  │
│  │  │ SHOW PRODUCT                     │  │  │  │
│  │  └──────────────────────────────────┘  │  │  │
│  │                                        │  │  │
│  └────────────────────────────────────────┘  │  │
│                                              │  │
│  ┌────────────────────────────────────────┐  │  │
│  │                                        │  │  │
│  │ SHOPPING CART                          │  │  │
│  │                                        │  │  │
│  │                                        │  │  │
│  │                                        │  │  │
│  │                                        │  │  │
│  │                                        │  │  │
│  └────────────────────────────────────────┘  │  │
│                                              │  │
└──────────────────────────────────────────────┘  │
                                                  │
┌──────────────────────────────────────────────┐  │
│                                              │  │
│ const  [cart, setCart] = useState();         ├──┘
│                                              │
└──────────────────────────────────────────────┘
0 likes
10 replies
Sinnbeck's avatar

Just to better understand. Can you show the shopping cart component?

1 like
Randy_Johnson's avatar
import React, { useState, useEffect } from "react";


export function PrimaryShoppingCart({ cart }) {

    const [list, setList] = useState(cart);
    const [total, setTotal] = useState();

    const handleRemove = function (id) {
        let newList = list.filter((obj) => obj.id !== id);
        setList(newList);
    };


    useEffect(() => {
        const sumWithInitial = list.reduce((accumulator, object) => {
            return accumulator + object.price;
        }, 0);
        setTotal(sumWithInitial);
    }, [list]);


    return <>
        <aside className="w-full h-screen" aria-label="Sidebar">
            {console.log('Primary Shopping Component')}
            <div className="px-3 py-4 overflow-y-auto bg-inherit flex-1">
                <ul className="space-y-2">
                    <li>
                        <div className="flex">
                            <div className="basis-1/2">
                                <a href="#" className="flex items-center p-2 text-base font-normal text-gray-900 rounded-lg dark:text-white">
                                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" viewBox="0 0 16 16">
                                        <path d="M0 1.5A.5.5 0 0 1 .5 1H2a.5.5 0 0 1 .485.379L2.89 3H14.5a.5.5 0 0 1 .491.592l-1.5 8A.5.5 0 0 1 13 12H4a.5.5 0 0 1-.491-.408L2.01 3.607 1.61 2H.5a.5.5 0 0 1-.5-.5zM5 12a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm7 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm-7 1a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm7 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2z" />
                                    </svg>
                                    <span className="ml-3">Shopping  Cart</span>
                                </a>
                            </div>
                        </div>
                    </li>

                    <hr />

                    {list.length === 0 ? (
                        <p className="text-white text-center">The cart is empty!</p>
                    ) : (
                        <></>
                    )}

                    {list.map((item) => (
                        <li key={item.id}>
                            <div className="text-white text-sm">
                                <div className="flex">
                                    <div className="basis-7/12 p-3 rounded-l font-bold bg-slate-500 hover:bg-slate-400">{item.name}</div>
                                    <div className="basis-1/12 bg-slate-700 text-center p-3 font-bold">{item.amount}</div>
                                    <div className="basis-3/12 bg-slate-600 text-center p-3 font-bold float-right">${item.price}</div>
                                    <div className="basis-1/12 bg-red-600 hover:bg-red-700 rounded-r text-center  p-3 font-bold float-right cursor-pointer" onClick={() => handleRemove(item.id)}>
                                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-x-lg mx-auto align-middle" viewBox="0 0 16 16">
                                            <path d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z" />
                                        </svg>
                                    </div>
                                </div>
                            </div>
                        </li>
                    ))}
                    <hr />
                    <li>
                        <div className="flex">
                            <div className="basis-2/3 bg-emerald-500 hover:bg-emerald-400 rounded-l p-3 font-bold text-white cursor-pointer">Checkout</div>
                            <div className="basis-1/3 bg-slate-100 rounded-r text-center p-3 font-bold text-gray-700">
                                ${total}
                            </div>
                        </div>
                    </li>
                </ul>
            </div>
        </aside>
    </>;
}
Randy_Johnson's avatar

@Sinnbeck Yes its correct, but I am not sure if its the correct way to be doing it. But as the code is now, should the visible update in the shopping cart be happening. Because right now nothing is happening even though cart is being updated when using console log..

Sinnbeck's avatar

@Randy_Johnson In the current case no, as you are setting it to a local state. So in this case you would need to useEffect to detect any change

useEffect(() => {
    setList(offer);
}, [offer]);

But be aware that it would never propergate up the tree again. So any change in shoppingcart will never reach the dashboard

1 like
MohamedTammam's avatar

@Randy_Johnson I don't see where you're updating the list that's in the dashboard component. You're only updating the list that's created in the PrimaryShoppingCart and when it renders it takes the value again from its props. Therefor nothing will change.

You need to pass the callback that updates the list in the dashboard itself. Or use context as @sinnbeck mentioned.

1 like
Randy_Johnson's avatar

Okay I got it working. I used useEffect in shopping cart to check if the parameter var coming in is changed. Now I will study context.

But how is this done in reality. If you could give me a paragraph that would be great!

Shopping cart

    useEffect(() => {
        setList(cart)
    }, [cart]);
Sinnbeck's avatar

@Randy_Johnson Its very simple really. Use effect takes 2 parameters.

  1. A callback that will be called if it is "triggered". This can run any code needed. And it can return some sort of cleanup (like removing a timeout or stopping an ajax call)
  2. An array of variables to listen to. An empty array means run once (when the component is loaded). In your case it listens on offer for changes
1 like
Randy_Johnson's avatar

@Sinnbeck Hey, thanks for your help. This is my first app with ReactJS. Its just the best way for me to really grasp things. I changed the answer because you was right with the context approach for what I need. Makes things much easier.

If anyone finds themselves here. This is a great resource.

https://www.youtube.com/watch?v=lhMKvyLRWo0&t=182s&ab_channel=BenAwad

Please or to participate in this conversation.