Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Lidando com números negativos

Como não é possível comprar 0 ou -1 livro, precisamos desabilitar o botão de subtração quando a quantidade é 1. Eu fiz assim:

export const AbInputQuantidade = ({onChange}: AbInputQuantidadeProps) => {

    const [valor, setValor] = useState(1);
     // useState que controla a desabilitação do botão
    const [isDisabled, setIsDisabled] = useState(false);


    useEffect(() => {
        if (onChange) {
            onChange(Number(valor))
        }

        // toda vez que 'valor' alterar, verifica se o valor é 1 e, se for, desabilita o botão
        if (valor === 1) {
            setIsDisabled(true)
        } else {
            setIsDisabled(false)
        }

    }, [valor])

  return (
    <FlexContainerEstilizado>
      <LabelEstilizada>Quantidade</LabelEstilizada>
      <ContainerEstilizada>
      //disabled={isDisabled} desabilita o botão quando o valor é 1 e mantém habilitado quando é maior
        <BotaoEstilizado onClick={() => setValor(anterior => anterior - 1)} disabled={isDisabled}>-</BotaoEstilizado>
        <span>{valor}</span>
        <BotaoEstilizado onClick={() => setValor(anterior => anterior + 1)}>+</BotaoEstilizado>
      </ContainerEstilizada>
    </FlexContainerEstilizado>
  );
};

Também é importante mostrar visualmente que o botão está inativo. Fiz assim:

const BotaoEstilizado = styled.button<{ disabled?: boolean }>`
    //altera background do botão para mostrar que está habilitado/desabilitado
    background: ${(props) => (props.disabled ? '#779bb8' : '#002F52')};
    box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.25);
    border: none;
    border-radius: 50%;
    color: #fff;
    width: 28px;
    height: 28px;
    font-size: 24px;
    //altera cursor para demonstrar que botão não é clicável quando está desabilitado
    cursor: ${(props) => (props.disabled ? '' : 'pointer')};;
`
1 resposta
solução!

Oii, Dara. Tudo bem?

Que legal que você procurou outras formas de fazer :D

O seu código funciona, mas ele poderia ser melhorado para seguir as boas práticas de desenvolvimento. Atualmente, ele usa o useEffect desnecessariamente e gerencia estados de desabilitação que poderiam ser simplificados. Uma alternativa seria:

export const AbInputQuantidade = ({ onChange, minValue = 1, maxValue = Infinity }) => {
  const [valor, setValor] = useState(minValue);

  const incrementar = () => {
    setValor((anterior) => {
      const novoValor = Math.min(anterior + 1, maxValue);
      if (onChange) onChange(novoValor);
      return novoValor;
    });
  };

  const decrementar = () => {
    setValor((anterior) => {
      const novoValor = Math.max(anterior - 1, minValue);
      if (onChange) onChange(novoValor);
      return novoValor;
    });
  };

  return (
    <FlexContainerEstilizado>
      <LabelEstilizada>Quantidade</LabelEstilizada>
      <ContainerEstilizada>
        <BotaoEstilizado onClick={decrementar} disabled={valor === minValue}>
          -
        </BotaoEstilizado>
        <span>{valor}</span>
        <BotaoEstilizado onClick={incrementar} disabled={valor === maxValue}>
          +
        </BotaoEstilizado>
      </ContainerEstilizada>
    </FlexContainerEstilizado>
  );
};

Eliminamos a necessidade do useEffect e se focamos apenas no gerenciamento do estado valor, mantendo o código mais limpo e fácil de entender. Assim, você consegue um código mais eficiente e alinhado com as boas práticas!

Um abraço.