Stepperize v8Explore the changes
Stepperize

The stepper instance

Understand the object that drives state, navigation, and rendering.

useStepper() returns a single flat object. Everything you read (current step, index, progress) and everything you do (navigate, save values, complete steps) lives directly on it — no nested state or navigation namespaces.

The fastest way to understand it is to drive one. Click the controls below and watch every value react in real time.

Drive a real instance

Every value below is read from useStepper(). Use the controls and watch them change.

const stepper = onboarding.useStepper();

stepper.id
"account"
The active step's typed id.
stepper.index
0
Its position in the steps array.
stepper.progress
0
Position from 0 to 1. Not the share of completed steps.
stepper.isFirst
true
At the start of the flow.
stepper.isLast
false
At the end of the flow.
stepper.canPrev
false
Bind it to your Back button's disabled state.
stepper.canNext
true
Bind it to your Next button's disabled state.
stepper.completed
[]
Only what you marked complete. Moving never fills it.

Last call

Click a control. Navigation returns a typed result you can check.

Try this

  • Point at Previous: it reads canPrev.
  • Go forward: completed stays empty.
  • Mark a step complete, then move: it stays marked.

What just happened

  • next() / prev() move the active step. Notice index, progress, and the current.id change together — they are all derived from one source.
  • canPrev / canNext flip automatically at the edges. You never compute "am I on the last step?" yourself — bind buttons straight to them.
  • setComplete() changes completed but leaves the position untouched. Completion is independent from where you are — see Status vs completion.
  • goTo(id) (click any circle) jumps directly to a step by its typed id.

The mental model

Think of the instance as derived state over one pointer. You move the pointer (the current index); everything else — current, progress, isLast, each step's status — is recomputed for you.

const stepper = onboarding.useStepper();

stepper.current; // the active step object (with your custom fields)
stepper.index; // where the pointer is
stepper.next(); // move the pointer forward
stepper.match({ ... }); // render exactly the active step

You only manage intent ("go next", "jump to review"). Stepperize manages the consequences.

The six you need on day one

Most flows ship with just these:

MemberWhat it gives you
currentThe active step object, including your custom fields.
match({...})Exhaustive, type-checked rendering by step id.
next() / prev()Move through the flow.
canNext / canPrevReady-made disabled states for your buttons.

Everything else — values, completion, events, step-map helpers — is there when you need it, and invisible until then. The full instance reference lists every member.

Next: the navigation lifecycle.

Edit on GitHub

Last updated on

On this page