Serenity
Serenity

Reputation: 4054

increment and decrement not working properly

I am trying to create quantity field where user can increase and decrease the quantity. I am binding this field with redux form. There is an issue where if i keep on increasing it increases the number but when after increasing the number if i try to decrease the number it first increases and in second decrease it starts to decrease the number. When decreasing if the number is reached to the point of 1 then if i try to increase the number it will show 0 and then starts working in an expected way.

Here is the demo as well

https://codesandbox.io/s/little-lake-q3rw9

here is the source code

const QuantityField = ({ input, label, meta, inputCss, labelCss, ...rest }) => {
  const [quantity, setQuantity] = React.useState(1);

  const handleIncrease = () => {
    setQuantity(quantity + 1);
    console.log("###################");
    rest.change(input.name, quantity);
    console.log("###################");
    console.log("input value", input.value);
  };

  const handleDecrease = () => {
    if (quantity > 0) {
      setQuantity(quantity - 1);
      rest.change(input.name, quantity);
    }
  };

  return (
    <>
      <InputWrapper>
        {label && (
          <Label isActive={meta !== undefined && meta.active} css={labelCss}>
            {label}
          </Label>
        )}
        <TextInputWapper>
          <Augment onClick={() => handleIncrease()}>
            <FontAwesomeIcon icon={faPlus} style={{ color: "#fff" }} />
          </Augment>
          <TextInput
            css={inputCss}
            disabled
            isActive={meta !== undefined && meta.active}
            hasError={meta !== undefined && meta.touched && !!meta.error}
            {...input}
            {...rest}
          />
          <Augment onClick={() => handleDecrease()}>
            <FontAwesomeIcon icon={faMinus} style={{ color: "#fff" }} />
          </Augment>
        </TextInputWapper>
        {meta !== undefined && meta.touched && !!meta.error && (
          <Error className="field-error">{meta.error}</Error>
        )}
      </InputWrapper>
    </>
  );
};

export default QuantityField;

const Augment = styled.span`
  background: #1ab394;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.375rem 0.75rem;
  cursor: pointer;
`;

Upvotes: 0

Views: 668

Answers (2)

Ankit Kumar Rajpoot
Ankit Kumar Rajpoot

Reputation: 5600

My Code is:- Actions

import { MINUS_NUMBER, PLUS_NUMBER, RESET_NUMBER } from "./types";
export const minusAction = number => dispatch => {
  dispatch({
    type: MINUS_NUMBER,
    payload: number
  });
};
export const plusAction = number => dispatch => {
  dispatch({
    type: PLUS_NUMBER,
    payload: number
  });
};
export const resetAction = number => dispatch => {
  dispatch({
    type: RESET_NUMBER,
    payload: number
  });
};

Reducer

const addNumber = (state = initialState, action) => {
  switch (action.type) {
    case MINUS_NUMBER:
      return {
        ...state,
        number: action.payload - 1
      };
    case PLUS_NUMBER:
      return {
        ...state,
        number: action.payload + 1
      };
    case RESET_NUMBER:
      return {
        ...state,
        number: 0
      };
    default:
      return state;
  }
};
export default addNumber;

Root Reducer

import { combineReducers } from "redux";
import clickerReducer from "./clickerReducer";
export default combineReducers({
  clickerReducer
});

component

import React from "react";
import { connect } from "react-redux";
import { minusAction, plusAction, resetAction } from "../actions/clickerAction";
function App(props) {
  return (
    <div align="center" className="App">
      <h1>{props.number}</h1>
      <button
        onClick={() => {
          props.minusAction(props.number);
        }}
      >
        -
      </button>
      <button
        onClick={() => {
          props.resetAction(props.number);
        }}
      >
        Reset
      </button>
      <button
        onClick={() => {
          props.plusAction(props.number);
        }}
      >
        +
      </button>
    </div>
  );
}
const mapStateToProps = state => ({
  number: state.clickerReducer.number
});
export default connect(mapStateToProps, {
  minusAction,
  plusAction,
  resetAction
})(App);

Upvotes: 0

aravind_reddy
aravind_reddy

Reputation: 5476

The problem here is you are changing values just after setQuantity which is asynchronous so your next statement will not have the updated value instead you need to use useEffect to notify you the quantity value changes and then update/change your values

  const QuantityField = ({ input, label, meta, inputCss, labelCss, ...rest }) => {
  const [quantity, setQuantity] = React.useState(0);

  const handleIncrease = () => {
    setQuantity(quantity + 1);
    console.log("###################");
    // rest.change(input.name, quantity);
    console.log("###################");
    console.log("input value", input.value);
  };

  const handleDecrease = () => {
    if (quantity > 0) {
      setQuantity(quantity - 1);
      console.log("sss", quantity);
    }
  };

  React.useEffect(() => {          
      rest.change(input.name, parseInt(quantity,10));
  }, [quantity]);

here is the sandbox link https://codesandbox.io/s/compassionate-mestorf-r0qyt

Upvotes: 1

Related Questions