![PyPI Now Supports iOS and Android Wheels for Mobile Python Development](https://cdn.sanity.io/images/cgdhsj6q/production/96416c872705517a6a65ad9646ce3e7caef623a0-1024x1024.webp?w=400&fit=max&auto=format)
Security News
PyPI Now Supports iOS and Android Wheels for Mobile Python Development
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
use-stepper
Advanced tools
React hook to manage a numeric stepper/spinbutton
A numeric stepper or "spinbutton" (decrement button, input, increment button) is
deceptively non-trivial to implement. You have to manage the minimum, the
maximum, the input itself displaying the current value (conceptually numeric,
but ultimately a string in HTML), allowing a user to type freely and hopefully
arrive at a valid number (e.g. "-" is NaN
but you have to let them type it so
they can get to "-4", so simply parsing their input as a number is
insufficient), interpreting the input's value on blur, etc.
This React hook manages all this for you so you only have to worry about the styling. It returns the current value, functions for manual value manipulation, and a collection of prop getters to spread across your form elements to make it all work together. It also includes the ability to provide your own custom state reducer to enable ultimate control over what actions like "increment", "decrement", "coerce", etc. mean in your application.
Using npm:
npm install use-stepper # or, with yarn: yarn add use-stepper
This package also depends on
react
16.8.0 or newer. Please make sure you have that installed as well.
import { useStepper } from 'use-stepper';
function MyStepper() {
const { getFormProps, getInputProps, getIncrementProps, getDecrementProps } =
useStepper();
return (
<form {...getFormProps()}>
<button {...getDecrementProps()}>-</button>
<input {...getInputProps()} />
<button {...getIncrementProps()}>+</button>
</form>
);
}
The hook accepts an options object as its only parameter. The entries for the basic options are as follows:
number
| optional, default:0
The initial value and the value to use as a fallback upon invalid manual input.
number
| optional, default:1
The amount by which to increment or decrement the current value.
number
| optional, default:-Number.MAX_VALUE
The minimum value allowed.
number
| optional, default:Number.MAX_VALUE
The maximum value allowed.
boolean
| optional, default:false
Controls whether the current value (if unchanged) will update to the new default
if defaultValue
changes.
function(state: object, action: object): object
| optional
Changes to the state of the hook are applied using React's built-in
useReducer
hook. This function replaces the default reducer
implementation, which allows you to author your own logic to execute when an
action is dispatched. This gives you ultimate control in the event you wish to
constrain the value or otherwise modify the default behavior. It gives you the
current state and the action to execute, and you return the new state.
state
: the current state of the hookaction
: the action to executeState is just an object with a value
key (note: value
is a string, so it
should be converted to a number before performing mathematical operations on
it).
Actions have a type
field and an optional payload
field. The possible action
types are discoverable through useStepper.actionTypes
(e.g.
useStepper.actionTypes.increment
). The default reducer is also available at
useStepper.defaultReducer
in case you want to defer to the default
implementation in some cases (e.g. for the default/unhandled action, perhaps).
Constrain the stepper to only use whole numbers:
function IntegerStepper({ min, max, defaultValue }) {
function validValueClosestTo(desiredNumericValue) {
return String(Math.min(max, Math.max(desiredNumericValue, min)));
}
function integerReducer(state, action) {
const integerValue = parseInt(state.value, 10);
switch (action.type) {
case useStepper.actionTypes.increment: {
return { value: validValueClosestTo(integerValue + 1) };
}
case useStepper.actionTypes.decrement: {
return { value: validValueClosestTo(integerValue - 1) };
}
case useStepper.actionTypes.coerce: {
if (Number.isNaN(integerValue)) {
return { value: String(defaultValue) };
}
const newValue = validValueClosestTo(integerValue);
if (newValue !== state.value) {
return { value: newValue };
}
return state;
}
default:
return useStepper.defaultReducer(state, action);
}
}
const { getInputProps, getIncrementProps, getDecrementProps } = useStepper({
min,
max,
defaultValue,
stateReducer: integerReducer,
});
return (
<>
<button {...getDecrementProps()}>-</button>
<input {...getInputProps()} />
<button {...getIncrementProps()}>+</button>
</>
);
}
The hook returns an object with the following shape:
key | type | category |
---|---|---|
getFormProps | function | prop getter |
getInputProps | function | prop getter |
getIncrementProps | function | prop getter |
getDecrementProps | function | prop getter |
value | string | state |
increment | function | setter |
decrement | function | setter |
setValue | function | setter |
These functions are used to apply props to the elements that you render. This
gives you maximum flexibility to render what, when, and wherever you like. You
call these on the element in question (for example:
<input {...getInputProps()}
)). It's advisable to pass all your props to that
function rather than applying them on the element yourself to avoid your props
being overridden (or overriding the props returned). For example:
getInputProps({ onChange: myChangeHandler })
.
key | type | description |
---|---|---|
getFormProps | function({}) | returns the props you should apply to the form element for submit handling |
getInputProps | function({}) | returns the props you should apply to the input element (includes value ) |
getIncrementProps | function({}) | returns the props you should apply to the increment button element |
getDecrementProps | function({}) | returns the props you should apply to the decrement button element |
These are the values that represent the internal state of the hook.
key | type | description |
---|---|---|
value | string | the current value of the stepper |
These functions are exposed to provide manual manipulation of the internal value.
key | type | description |
---|---|---|
increment | function() | increments the value |
decrement | function() | decrements the value |
setValue | function(str) | sets the value (note: the argument passed will be coerced to a valid value within the specified range or fall back to the default value if not a valid number) |
@zag-js/number-input
is a more full-featured alternative
driven by state machines and maintained by the team behind the popular Chakra
UI project.react-stepper-primitive
by Andrew Joslin was the
prime source of inspiration for this hook.If you know of any others, please send a pull request to add them here.
FAQs
React hook to manage a numeric stepper/spinbutton
The npm package use-stepper receives a total of 681 weekly downloads. As such, use-stepper popularity was classified as not popular.
We found that use-stepper demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.