0
\$\begingroup\$

I built a ButtonStepper component and it's sharing quite a bit of the same logic, so I was wondering if it could be refactored better. It's sharing quite a bit of code with incrementDisabled and decrementDisabled because I have to account for the button color changing from black to grey and disabling the TouchableOpacity when the mix or max is reached.

Also, should I be using useMemo or useCallback at all?

// TypeScript Type: Props
interface IProps {
  onChange: (value: number) => void;
  darkMode?: boolean;
  minValue?: number;
  maxValue?: number;
  stepValue?: number;
}

// Component: Button (Stepper)
const ButtonStepper = ({
  onChange,
  darkMode = false,
  minValue = Number.NEGATIVE_INFINITY,
  maxValue = Number.POSITIVE_INFINITY,
  stepValue = 1,
}: IProps): JSX.Element => {
  // React Hooks: State
  const [value, setValue] = useState<number>(0);

  // React Hooks: Lifecycle Methods
  useEffect(() => {
    onChange(value);
  }, [onChange, value]);

  // Increment Disabled
  const incrementDisabled = (): boolean => {
    // Disabled
    if (maxValue < value + stepValue) {
      return true;
    }
    // Active
    else {
      return false;
    }
  };

  // Decrement Disabled
  const decrementDisabled = (): boolean => {
    // Disabled
    if (minValue > value - stepValue) {
      return true;
    }
    // Active
    else {
      return false;
    }
  };

  // On Increment
  const onIncrement = (): void => {
    // Check Max Value
    if (!incrementDisabled()) {
      setValue(value + stepValue);
    }
  };

  // On Decrement
  const onDecrement = (): void => {
    // Check Min Value
    if (!decrementDisabled()) {
      setValue(value - stepValue);
    }
  };

  // Render Decrement Icon Color
  const renderDecrementIconColor = (): '#000000' | '#7D7D7D' => {
    // Dark
    if (darkMode) {
      // Disabled
      if (decrementDisabled()) {
        return '#7D7D7D';
      }
      // Active
      else {
        return '#000000';
      }
    }
    // Light
    else {
      // Disabled
      if (decrementDisabled()) {
        return '#7D7D7D';
      }
      // Active
      else {
        return '#000000';
      }
    }
  };

  // Render Increment Icon Color
  const renderIncrementIconColor = (): '#000000' | '#7D7D7D' => {
    // Dark
    if (darkMode) {
      // Disabled
      if (incrementDisabled()) {
        return '#7D7D7D';
      }
      // Active
      else {
        return '#000000';
      }
    }
    // Light
    else {
      // Disabled
      if (incrementDisabled()) {
        return '#7D7D7D';
      }
      // Active
      else {
        return '#000000';
      }
    }
  };

  return (
    <View style={darkMode ? styles.containerDark : styles.containerLight}>
      <TouchableOpacity
        style={darkMode ? styles.iconContainerDark : styles.iconContainerLight}
        onPress={onDecrement}
        disabled={decrementDisabled()}
        accessibilityLabel="Decrement"
        accessibilityRole="button"
      >
        <Icon name="ios-remove" color={renderDecrementIconColor()} size={27} />
      </TouchableOpacity>

      <View style={darkMode ? styles.dividerDark : styles.dividerLight} />

      <TouchableOpacity
        style={darkMode ? styles.iconContainerDark : styles.iconContainerLight}
        onPress={onIncrement}
        disabled={incrementDisabled()}
        accessibilityLabel="Increment"
        accessibilityRole="button"
      >
        <Icon name="ios-add-outline" color={renderIncrementIconColor()} size={27} />
      </TouchableOpacity>
    </View>
  );
};
```
\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.