Why my images are blinking and chaning when i click on category filter?

to watch the problem you can test it here http://u100525.test-handyhost.ru/products
the problem appears if to click many times on category items, images of products start to bug :c

so if i click on categories my code is filtering products array and update statement – visibleProducts then im doing visibleProducts.map((product)=>{});

as i gues the problem is releted with images only, because every time when react renders my the component does request to the server for getting image by id and waits while the image will load, but if i click on an other category react(ProductItem) starts other request for new images then it is starting to bug :c

im new in react and just stated to practice what i have to do guys?

is my code correct ?

here is my ProductItem component ->

import React, { useState, useEffect, memo, useCallback } from "react";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { setModalShow, onQuickViewed, addedToCart } from "../../actions";

import Checked from "../checked";

import "./product-item.css";
import Spinner from "../spinner";

const ProductItem = ({
  product,
  wpApi,
  addedToCart,
  onQuickViewed,
  setModalShow,
}) => {
  const [prodImg, setProdImg] = useState("");
  const [animated, setAnimated] = useState(false);
  const [checked, setChecked] = useState(false);
  const [itemLoading, setItemLoading] = useState(true);

  const checkedFn = useCallback(() => {
    setChecked(true);
    setTimeout(() => {
      setChecked(false);
    }, 800);
  },[product]);

  const onModalOpen = useCallback((e, id) => {
    onQuickViewed(e, id);
    setModalShow(true);
  }, product);

  const addHandle = useCallback((e, id) => {
    e.preventDefault();
    addedToCart(id);
    checkedFn();
  },[product]);

  useEffect(()=>{
    setItemLoading(false);
  }, [prodImg]);

  useEffect(() => {
    wpApi.getImageUrl(product.imageId).then((res) => {
      setProdImg(res);
    });
  });

  return (
    <div className="product foo">
      <div
        className='product__inner'}
      >
        {!itemLoading?         <div
          className="pro__thumb"
          style={{
            backgroundImage:prodImg
              ? `url(${prodImg})`
              : "assets/images/product/6.png",
          }}
        >
          <Link
            to={`/product-details/${product.id}`}
            style={{ display: `block`, width: `100%`, paddingBottom: `100%` }}
          >

          </Link>
        </div>: <Spinner/>}


        <div className="product__hover__info">
          <ul className="product__action">
            <li>
              <a
                onClick={(e) => {
                  onModalOpen(e, product.id);
                }}
                title="Quick View"
                className="quick-view modal-view detail-link"
                href="#"
              >
                <span ><i class="zmdi zmdi-eye"></i></span>
              </a>
            </li>
            <li>
              <a
                title="Add TO Cart"
                href="#"
                onClick={(e) => {
                  addHandle(e, product.id);
                }}
              >
                {checked ? (
                  <Checked />
                ) : (
                  <span className="ti-shopping-cart"></span>
                )}
              </a>
            </li>
          </ul>
        </div>
      </div>
      <div className="product__details">
        <h2>
          <Link to={`/product-details/${product.id}`}>{product.title}</Link>
        </h2>
        <ul className="product__price">
          <li className="old__price">${product.price}</li>
        </ul>
      </div>
    </div>
  );
};

const mapStateToProps = ({ options, cart, total, showModal }) => {
  return {};
};

const mapDispatchToProps = {
  onQuickViewed,
  setModalShow,
  addedToCart,
};

export default connect(mapStateToProps, mapDispatchToProps)(memo(ProductItem));

here is my parent component Products ->

import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import ProductItem from "../product-item";
import { withWpApiService } from "../hoc";
import { onQuickViewed, addedToCart, categoriesLoaded } from "../../actions";
import CategoryFilter from "../category-filter";
import Spinner from "../spinner";

import "./products.css";

const Products = ({
  maxProducts,
  WpApiService,
  categoriesLoaded,
  addedToCart,
  onQuickViewed,
  products,
  categories,
  loading,
}) => {
  const [activeIndex, setActiveIndex] = useState(0);
  const [activeCategory, setActiveCategory] = useState(0);
  const [visibleProducts, setVisibleProducts] = useState([]);

  const wpApi = new WpApiService();

  useEffect(() => {
    updateVisibleProducts(activeCategory, products);
  }, [products]);

  useEffect(() => {
    wpApi.getCategories().then((res) => {
      categoriesLoaded(res);
    });
  }, []);

  const getCatId = (cat) => {
    setActiveCategory(cat);
    updateVisibleProducts(cat, products);
    setActiveIndex(cat);
  };

  const updateVisibleProducts = (category, products) => {
    let updatedProducts = [];
    switch (category) {
      case 0:
        updatedProducts = products;

        setVisibleProducts(updatedProducts);

        break;
      default:
        updatedProducts = products.filter(
          (product) => product.categories.indexOf(category) >= 0
        );

        setVisibleProducts(updatedProducts);
    }
  };

  let currentLocation = window.location.href.split("/");

  if (!loading) {
    return (
      <section className="htc__product__area shop__page mb--60 mt--130 bg__white">
        <div className={currentLocation[3] == "" ? `container` : ""}>
          <div className="htc__product__container">
            <CategoryFilter
              activeIndex={activeIndex}
              categories={categories}
              getCatId={getCatId}
            />

            <div
              className="product__list another-product-style"
              style={{ height: "auto" }}
            >
              {visibleProducts
                .slice(0, maxProducts ? maxProducts : products.length)
                .map((prod, id) => {
                  return (
                    <ProductItem
                      wpApi={wpApi}
                      key={id}
                      onQuickViewed={onQuickViewed}
                      addedToCart={addedToCart}
                      product={prod}
                    />
                  );
                })}
            </div>
          </div>
        </div>
      </section>
    );
  } else {
    return <Spinner />;
  }
};

const mapStateToProps = ({ products, loading, activeCategory, categories }) => {
  return {
    products,
    activeCategory,
    categories,
    loading,
  };
};

const mapDispatchToProps = {
  addedToCart,
  categoriesLoaded,
  onQuickViewed,
};

export default withWpApiService()(
  connect(mapStateToProps, mapDispatchToProps)(Products)
);

and if you need, here is my CategoryFilter component ->

import React from 'react'

const CategoryFilter = ({categories, getCatId, activeIndex}) => {
    return (
        <div className="row mb--60">
        <div className="col-md-12">
          <div className="filter__menu__container">
            <div className="product__menu">
              {categories.map((cat) => {
                return (
                  <button key={cat.id}
                   className={activeIndex === cat.id? 'is-checked' : null}
                    onClick={() => getCatId(cat.id)}
                    data-filter=".cat--4"
                  >
                    {cat.name}
                  </button>
                );
              })}
            </div>
          </div>
        </div>
      </div>
    )
}

export default CategoryFilter

93 thoughts on “Why my images are blinking and chaning when i click on category filter?”

Leave a Comment