reactjsnext.jswp-graphql

getting localStorage data so that I can pass it to apollo query variables but skip query if the variable is empty


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
}

Solution

  • 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())
    }, []);