Home > Net >  useReducer - Counter does not work on production
useReducer - Counter does not work on production

Time:11-13

I made an online store, but the counter for adding products to the cart does not work on production (everything works on localhost).

ProductHero.tsx (component code where the counter is):

import { useAppDispatch } from 'hooks/useRedux';
import { FC, useReducer, useState } from 'react';
import {
  StyledBoxCounter,
  StyledButton,
  StyledContent,
  StyledPrice,
  StyledProductHero,
  Wrapper,
} from './ProductHero.styles';
import { addProduct } from 'store';
import { ActionType, CountType, ProductHeroType } from 'types';
import { ActionTypes } from 'constants/index';
import SuccessInformation from 'components/molecules/SuccessInformation/SuccessInforamtion';

const reducer = (state: CountType, action: ActionType) => {
  switch (action.type) {
    case ActionTypes.Add:
      return { count: state.count   };
    case ActionTypes.Subtract:
      if (state.count === 1) return state;
      else return { count: state.count-- };
    case ActionTypes.Reset:
      return { count: 1 };
    default:
      return state;
  }
};

const ProductHero: FC<ProductHeroType> = (product) => {
  const { cartImage, image, name, shortName, isNew, description, productPrice, price } = product;
  const dispatch = useAppDispatch();
  const [state, dispatchCounter] = useReducer(reducer, { count: 1 });
  const [isOpen, setIsOpen] = useState(false);

  const closeSuccesInformation = () => setIsOpen(false);

  const toggleSuccesInformation = () => {
    setIsOpen(true);
    setTimeout(() => {
      closeSuccesInformation();
    }, 3000);
  };

  const handleAddProduct = () => {
    dispatch(
      addProduct({ image: cartImage, shortName, productPrice, quantity: state.count, price }),
    );
    dispatchCounter({ type: ActionTypes.Reset });
    toggleSuccesInformation();
  };

  return (
    <>
      <SuccessInformation
        name={name}
        isOpen={isOpen}
        closeSuccesInformation={closeSuccesInformation}
      />
      <StyledProductHero>
        <picture>
          <source media='(min-width: 768px)' srcSet={image.desktop} />
          <source media='(min-width: 500px)' srcSet={image.tablet} />
          <img src={image.mobile} alt={`${name} image`} />
        </picture>
        <div>
          {isNew && <h5>new product</h5>}
          <h2>{name}</h2>
          <StyledContent>{description}</StyledContent>
          <StyledPrice>$ {productPrice}</StyledPrice>
          <Wrapper>
            <StyledBoxCounter>
              <button onClick={() => dispatchCounter({ type: ActionTypes.Subtract })}>-</button>
              <div>{state.count}</div>
              <button onClick={() => dispatchCounter({ type: ActionTypes.Add })}> </button>
            </StyledBoxCounter>
            <StyledButton onClick={handleAddProduct}>add to cart</StyledButton>
          </Wrapper>
        </div>
      </StyledProductHero>
    </>
  );
};

export default ProductHero;

live version: https://audiophile-ms.netlify.app/ github: https://github.com/Skolaczk/Audiophile/blob/main/src/components/organisms/ProductHero/ProductHero.tsx?fbclid=IwAR0rWOruteD9m6K0MbIc1szO7NAJGO5bOhjBu9ZPolKXwFZJhXWS1kZBxEM

I tried to debug the code for this component and it turned out to be a problem with the reducer but I'm not sure.

CodePudding user response:

It's because the way you set a new value on your reducer is incorrect in terms of what you're trying to do.

In JavaScript, the order really matters if you assign a variable with an increment operator. For example:

let a = 1;

b = a  ; // b = 1
c =   a; // c = 2

So in your case, when you click ( ) or (-) buttons, you always get the old value because the increment operator comes after the variable. So instead of put if after, just need to put it before the state.count

return { count:   state.count };

For an explanation about this, you could look at this article, which explains in C/C but the concept is pretty much the same.

  • Related