1

I save product ids in a localstorage to be used in recently viewed component. My Recently viewed component is below

import { useQuery } from "@apollo/client";
import { getRecentlyViewedProductArr } from "@gb-utils/product/product"
import { RECENTLY_VIEWED } from "@gb-utils/queries/product";
import { useEffect, useState } from "react";


    export default function RecentlyViewed() {
    
        const [recentIds, setRecentIds] = useState([])
    
        const { loading, error, data } = useQuery(RECENTLY_VIEWED, {
            variables: { ids: recentIds }
        })
    
        useEffect(() => {
            setRecentIds(getRecentlyViewedProductArr())
        }, []);
    
        if (loading) {
            return 'Loading';
        }
    
        if (error) {
            return error.message
        }
    
        return (
            <div>{JSON.stringify(data)}</div>
        )
    }

My question is about how I use get the product from wp-graphql using userQuery with the local storage.

Currently I am defining a state to store product ids and on mount of the RecentlyViewed component I update the recentIds by getting the data from localstorage. Is there a better way of doing the code above because I feel like it fetching data from wp without or empty recentIds is a problem.

helper.js

export const addRecentlyViewedProduct = (productId) => {

    let recent = getRecentlyViewedProduct()

    if (isEmpty(recent)) {
        // If recently viewed is empty then we just save the product id
        saveRecentlyViewedProduct(productId)

        return getRecentlyViewedProduct()
    }

    // if not empty then we check if product id exist and remove
    if (recent.includes(productId)) {
        recent = recent.replace(productId, '')
    }
    // Since we remove the product then we Add the product id again
    recent = "".concat(productId, '|', recent)
    recent = recent.replace('||', '|');
    recent = recent.startsWith('|') ? recent.substring(1) : recent
    recent = recent.endsWith('|') ? recent.substring(0, recent.length - 1) : recent;

    const limit = 5;
    let recentProductIds = recent.split('|')
    if (recentProductIds.length > limit) {
        recentProductIds = recentProductIds.slice(0, limit)
    }

    saveRecentlyViewedProduct(recentProductIds.join('|'))
    return getRecentlyViewedProduct()
}

export const saveRecentlyViewedProduct = (value) => {
    return localStorage.setItem('woo-next-recent-product', value);
}

export const getRecentlyViewedProduct = () => {

    const recentProductsStr = localStorage.getItem('woo-next-recent-product')
    return recentProductsStr

}

export const getRecentlyViewedProductArr = () => {
    const recentProductsStr = getRecentlyViewedProduct()
    if (isEmpty(recentProductsStr)) {
        return ''
    }

    let recentProductIds = recentProductsStr.split('|')
    return Array.from(recentProductIds.slice(1), Number); // get the 2nd to the last element
}
jameshwart lopez
  • 2,993
  • 6
  • 35
  • 65

1 Answers1

1

You can use the skip option from the useQuery API: https://www.apollographql.com/docs/react/data/queries/#skip

const [recentIds, setRecentIds] = useState([])
    
const { loading, error, data } = useQuery(RECENTLY_VIEWED, {
  variables: { ids: recentIds },
  skip: recentIds.length === 0
})
    
useEffect(() => {
  setRecentIds(getRecentlyViewedProductArr())
}, []);
vighnesh153
  • 4,354
  • 2
  • 13
  • 27
  • This seems to be what im looking for. I don't need to pass a dependency to the useEffect hook? – jameshwart lopez Sep 20 '22 at 08:19
  • If you don't want to listen to changes on the localstorage, then you can skip the dependencies. If you do want to listen to changes, then you will have to figure out a way to emit some event-based mechanism (because localStorage doesn't have one built-in) and then update `recentIds` when you receive that event. – vighnesh153 Sep 20 '22 at 11:22