AsyncStorage is not working, the value always disappears when the application reload

Viewed 282

I want to save an array of object to device using AsyncStorage, I have used AsyncStorage for save my jwt token and it working well. But when i tried to save an array of object it wasn't working here is my code :

  const storeCart = async (value) => {
    try {
      const jsonValue = JSON.stringify(value);
      await AsyncStorage.setItem(`cart-${user.id}`, jsonValue);
    } catch (e) {
      console.log(e);
    } finally {
      const jsonValue = await AsyncStorage.getItem(`cart-${user.id}`);
      if (jsonValue != null) {
        console.log(
          'this is from async storage after save',
          JSON.parse(jsonValue),
          user.id,
        );
      }
    }
  };

  const getCart = async () => {
    try {
      const jsonValue = await AsyncStorage.getItem(`cart-${user.id}`);
      if (jsonValue != null) {
        setCarts(JSON.parse(jsonValue));
        console.log('carts after refresh the app', jsonValue, user.id);
      }
    } catch (e) {
      console.log(e);
    }
  };

The Console Log

I have tried to console log the result after setItem, and it was saved successly, but when i reload the app and tried to console.log, it return and empty array, the key is already correct, and i have console log the user id too for make sure.

Here's the full code, if needed :

import React, { useState, createContext, useEffect, useContext } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
import AuthenticationContext from '../authentication/AuthenticationContext';

const CartsContext = createContext();

export const CartsContextProvider = ({ children }) => {
  const { user } = useContext(AuthenticationContext);
  const [carts, setCarts] = useState([]);

  const storeCart = async (value) => {
    try {
      const jsonValue = JSON.stringify(value);
      await AsyncStorage.setItem(`cart-${user.id}`, jsonValue);
    } catch (e) {
      console.log(e);
    } finally {
      const jsonValue = await AsyncStorage.getItem(`cart-${user.id}`);
      if (jsonValue != null) {
        console.log(
          'this is from async storage after save',
          JSON.parse(jsonValue),
          user.id,
        );
      }
    }
  };

  const getCart = async () => {
    try {
      const jsonValue = await AsyncStorage.getItem(`cart-${user.id}`);
      if (jsonValue != null) {
        setCarts(JSON.parse(jsonValue));
        console.log('carts after refresh the app', jsonValue, user.id);
      }
    } catch (e) {
      console.log(e);
    }
  };

  useEffect(() => {
    storeCart(carts);
  }, [carts, user]);

  useEffect(() => {
    getCart();
  }, [user]);

  const searchByMerchant = (merchantId) => {
    for (let i = 0; i < carts.length; i++) {
      if (carts[i].merchantId === merchantId) {
        return carts[i];
      }
    }
  };

  const searchByItem = (itemId, arrayOfItems) => {
    for (let i = 0; i < arrayOfItems.length; i++) {
      if (itemId === arrayOfItems[i].productId) {
        return arrayOfItems[i];
      }
    }
  };

  const deletePerMerchant = (merchantId) => {
    return carts.filter((x) => {
      return x.merchantId != merchantId;
    });
  };

  const deletePerItem = (itemId, arrayOfItems) => {
    return arrayOfItems.filter((x) => {
      return x.productId != itemId;
    });
  };

  const addItem = (merchantId, productId, qty) => {
    let merchantCheck = searchByMerchant(merchantId);
    let temp = null;

    if (merchantCheck) {
      let itemCheck = searchByItem(productId, merchantCheck.items);
      if (itemCheck) {
        let itemAfterRemoveSelectedItem = deletePerItem(
          productId,
          merchantCheck.items,
        );
        temp = deletePerMerchant(merchantId);
        if (qty === 0) {
          if (itemAfterRemoveSelectedItem.length === 0) {
            setCarts([...temp]);
          } else {
            setCarts([
              ...temp,
              ...[
                {
                  merchantId,
                  items: [...itemAfterRemoveSelectedItem],
                },
              ],
            ]);
          }
        } else {
          setCarts([
            ...temp,
            ...[
              {
                merchantId,
                items: [
                  ...itemAfterRemoveSelectedItem,
                  ...[{ productId, qty: qty }],
                ],
              },
            ],
          ]);
        }
      } else {
        temp = deletePerMerchant(merchantId);
        setCarts([
          ...temp,
          ...[
            {
              merchantId,
              items: [...merchantCheck.items, ...[{ productId, qty }]],
            },
          ],
        ]);
      }
    } else {
      if (qty > 0) {
        setCarts([...carts, ...[{ merchantId, items: [{ productId, qty }] }]]);
      }
    }
  };

  return (
    <CartsContext.Provider value={{ carts, addItem }}>
      {children}
    </CartsContext.Provider>
  );
};

export default CartsContext;

Thanks !

1 Answers

I believe this is happening because the cart value is being overwritten when you reload the app because the useEffect is called each time you reload the app. The setCarts is being called after adding something in cart, and therefore the first useEffect (which has in deps [cart, user]) is being called too and it sets correctly the data in local storage. But afterwards, if you reload the app, the same useEffect is being called again and the cart = [] is being set into the local storage. I would solve this by giving up to the first useEffect and setting directly the data into local storage without having any state related to it.

import React, { useState, createContext, useEffect, useContext } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
import AuthenticationContext from '../authentication/AuthenticationContext';

const CartsContext = createContext();

export const CartsContextProvider = ({ children }) => {
  const { user } = useContext(AuthenticationContext);

  const storeCart = async (value) => {
    try {
      const jsonValue = JSON.stringify(value);
      await AsyncStorage.setItem(`cart-${user.id}`, jsonValue);
    } catch (e) {
      console.log(e);
    } finally {
      const jsonValue = await AsyncStorage.getItem(`cart-${user.id}`);
      if (jsonValue != null) {
        console.log(
          'this is from async storage after save',
          JSON.parse(jsonValue),
          user.id,
        );
      }
    }
  };

  const getCart = async () => {
    try {
      const jsonValue = await AsyncStorage.getItem(`cart-${user.id}`);
      if (jsonValue != null) {
        storeCart(JSON.parse(jsonValue));
        console.log('carts after refresh the app', jsonValue, user.id);
      }
    } catch (e) {
      console.log(e);
    }
  };



  useEffect(() => {
    getCart();
  }, [user]);

  const searchByMerchant = (merchantId) => {
    for (let i = 0; i < carts.length; i++) {
      if (carts[i].merchantId === merchantId) {
        return carts[i];
      }
    }
  };

  const searchByItem = (itemId, arrayOfItems) => {
    for (let i = 0; i < arrayOfItems.length; i++) {
      if (itemId === arrayOfItems[i].productId) {
        return arrayOfItems[i];
      }
    }
  };

  const deletePerMerchant = (merchantId) => {
    return carts.filter((x) => {
      return x.merchantId != merchantId;
    });
  };

  const deletePerItem = (itemId, arrayOfItems) => {
    return arrayOfItems.filter((x) => {
      return x.productId != itemId;
    });
  };

  const addItem = (merchantId, productId, qty) => {
    let merchantCheck = searchByMerchant(merchantId);
    let temp = null;

    if (merchantCheck) {
      let itemCheck = searchByItem(productId, merchantCheck.items);
      if (itemCheck) {
        let itemAfterRemoveSelectedItem = deletePerItem(
          productId,
          merchantCheck.items,
        );
        temp = deletePerMerchant(merchantId);
        if (qty === 0) {
          if (itemAfterRemoveSelectedItem.length === 0) {
            storeCart([...temp]);
          } else {
            storeCart([
              ...temp,
              ...[
                {
                  merchantId,
                  items: [...itemAfterRemoveSelectedItem],
                },
              ],
            ]);
          }
        } else {
          storeCart([
            ...temp,
            ...[
              {
                merchantId,
                items: [
                  ...itemAfterRemoveSelectedItem,
                  ...[{ productId, qty: qty }],
                ],
              },
            ],
          ]);
        }
      } else {
        temp = deletePerMerchant(merchantId);
        storeCart([
          ...temp,
          ...[
            {
              merchantId,
              items: [...merchantCheck.items, ...[{ productId, qty }]],
            },
          ],
        ]);
      }
    } else {
      if (qty > 0) {
        storeCart([...carts, ...[{ merchantId, items: [{ productId, qty }] }]]);
      }
    }
  };

  return (
    <CartsContext.Provider value={{ carts, addItem }}>
      {children}
    </CartsContext.Provider>
  );
};

export default CartsContext;

Related