PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Friday, July 1, 2022

[FIXED] How to filter products by productType on Shopify?

 July 01, 2022     javascript, next.js, shopify     No comments   

Issue

The desired behaviour is for users to be able to filter products by their productType using buttons in a menu.

At the moment I'm querying the Shopify storefront API and fetching back products in lib/Shopify.js

export async function getProductsInCollection() {
  const query = `
  {
    collectionByHandle(handle: "frontpage") {
      title
      products(first: 25) {
        edges {
          node {
            id
            title
            productType
            handle
          }
        }
      }
    }
  }`

  const response = await ShopifyData(query)
  const allProducts = response.data.collectionByHandle.products.edges ? response.data.collectionByHandle.products.edges : []
  return allProducts
}

export function filter(type) {
  let filtredProducts = getProductsInCollection().filter(product => product.node.productType === type);
  return filtredProducts;
}

lib/Shopify.js also contains a function to fetch all the productTypes in the store.

export async function getProductTypes() {
  const query = 
  `{
    shop {
      products(first:250, query:"-product_type:''") {
        edges {
            node {
              productType
          }
        }
      }
    }
  }`

  const response = await ShopifyData(query)
  const rawProductTypes = response.data.shop.products ? response.data.shop.products.edges : []
  const productTypes = Array.from(new Set(rawProductTypes));
  return productTypes
}

Then shop.js loops through all of the productTypes and displays them in a menu. It also loops through all of the products.

import { getProductsInCollection, getProductTypes, filter } from "../lib/shopify"
import React, { useState, useEffect } from "react";
import Link from 'next/link'

export default function Shop({ products, pages, projects, productTypes }) {
  const [filtredProducts, setFiltredProducts] = useState(null);

  useEffect(() => {
    setFiltredProducts(getProductsInCollection());
  }, []);

  var categories = new Map();
  productTypes.forEach( function( item ) {
    categories.set(JSON.stringify(item), item);
  });

  function handleCategories(e) {
    let type = e.target.value;
    type !== "all"
      ? setFiltredProducts(filter(type))
      : setFiltredProducts(getProductsInCollection());
  }

  const deduped = Array.from(new Set(productTypes));

  return (
    <div>
      <div>
         {categories &&
        [...categories.values()].map((category, index) => (
          <>
            <button className="mr-8 mb-6 underline" key={index} value={category.node.productType} onClick={handleCategories}>
             {category.node.productType}
            </button>
          </>
        ))}
      {filtredProducts &&
          filtredProducts.map(p => (
            <ul>
              <li>{p.node.title}</li>
            </ul>
          ))}
      </div>
    </div>
  )
}

export async function getStaticProps() {
    const products = await getProductsInCollection()
    const productTypes = await getProductTypes()
  
    return {
      props: { 
        products,
        productTypes,
      },
    }
  }

When the user tries to click on the filter they get the following error.

TypeError: getProductsInCollection(...).filter is not a function

What's the correct way to get the filter to work so the menu filters the products below?


Solution

getProductsInCollection returns promise, use async/await before the filter.

In shop.js also you have to use async/await before setting to state.

export async function getProductsInCollection() {
  const query = `
  {
    collectionByHandle(handle: "frontpage") {
      title
      products(first: 25) {
        edges {
          node {
            id
            title
            productType
            handle
          }
        }
      }
    }
  }`;

  const response = await ShopifyData(query);
  const allProducts = response.data.collectionByHandle.products.edges
    ? response.data.collectionByHandle.products.edges
    : [];
  return allProducts;
}

export async function filter(type) {
  let filtredProducts = await getProductsInCollection();
  return filtredProducts.filter((product) => product.node.productType === type);
}

// shop.js
async function handleCategories(e) {
  let type = e.target.value;
  let products = [];
  if (type !== "all") {
    products = await filter(type);
  } else {
    products = getProductsInCollection();
  }
  setFiltredProducts(products);
}


Answered By - Rahul Sharma
Answer Checked By - Marie Seifert (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing