Search code examples
reactjsuse-effectreact-state

REACT a button that updates state which updates the button value


i have this state to check if the user added a specific item to shopping cart or no:

  const [isAdded, setIsAdded] = useState(false);

in the beginning, it assumes user didn't add the item to his shopping cart so the value of the button will be ADD TO CART

            <button
              type="button"
              className="addToCart"
              onClick={() => handleCart(item._id)}
            >
              {isAdded ? "REMOVE FROM CART" : "ADD TO CART"}
            </button>

when the user clicks ```ADD TO CART`` it trigger this function:

  const handleCart = async (itemId) => {
    const response = await fetch(
      `http://localhost:8000/add-or-remove-item-from-cart/${itemId}`,
      {
        method: "POST",
        headers: {
          "Content-type": "application/json",
        },
        body: JSON.stringify({
          userId: user._id,
        }),
      }
    );
    const data = await response.json();
    setIsAdded(!isAdded);
  };

the function make request to http://localhost:8000/add-or-remove-item-to-cart/${itemId} and checks if the user already added this item to his shopping cart it will remove it, otherwise it will add it, and this works like a charm

the button value should update immediately when the user clicks to add or remove the item from his/her shopping cart and also should be updated when page gets refresh, so when he clicks it will change isAdded state to the opposite setIsAdded(!isAdded); , but this doesn't work as useEffect is must needed to check if user added item to his shopping cart or no and update state accordingly, it will look like something like this:


const { user } = useContext(AuthContext); // user coming from context API

useEffect(()=>{
  setIsAdded(user.cartItems.includes(itemId)) // true if user added the item, false otherwise
},[itemId])

but the problem is i don't have access to itemId in useEffect as i also can't use it inside the handleCart function, so how can i do that to persist state ?


Solution

  • You should use a separate component ItemCard and pass itemId as props to this ItemCard.

        const ItemCard = ({itemId})=>{
            const { user } = useContext(AuthContext); // user coming from context API
    
            useEffect(()=>{
                setIsAdded(user.cartItems.includes(itemId)) // true if user added 
                //the item, false otherwise
            },[itemId]);
            return <button
              type="button"
              className="addToCart"
              onClick={() => handleCart(item._id)}
            >
              {isAdded ? "REMOVE FROM CART" : "ADD TO CART"}
            </button>
        }
    

    Then when you are showing the list of items, do this

    items.map((item)=> <ItemCard key={item.itemId} itemId={item.itemId} ...item/>)