Event Handling
Callbacks fired by the FormWizard component.
Event Handling
| Event | Signature |
|---|---|
onComplete | (data?: WizardData) => void — fires when finish is pressed on a valid last step. |
onTabChange | (e: WizardStepChangeEvent) => void — fires when the active step changes. |
onDataChange | (data: WizardData) => void — fires whenever wizard data changes. |
onComplete
Fires after finish is triggered and the final step validates. If the last step is invalid, navigation is blocked and this never runs — so you do not need to re-check validity inside it.
import type { WizardData } from "react-form-wizard-component";
const handleComplete = (data?: WizardData) => {
console.log("Wizard completed with data:", data);
};
<FormWizard onComplete={handleComplete}>{/* ... */}</FormWizard>;With react-hook-form, remember handleSubmit returns an event handler, so
invoke it rather than passing it straight through:
<FormWizard onComplete={() => void form.handleSubmit(submit)()} />onTabChange
Fires whenever navigation changes the active step.
import type { WizardStepChangeEvent } from "react-form-wizard-component";
const handleTabChange = ({
prevIndex,
nextIndex,
stepId,
}: WizardStepChangeEvent) => {
console.log("Tab changed:", { prevIndex, nextIndex, stepId });
};
<FormWizard onTabChange={handleTabChange}>{/* ... */}</FormWizard>;| Field | Type | Description |
|---|---|---|
prevIndex | number | Index the wizard moved away from. |
nextIndex | number | Index the wizard moved to. |
stepId | string | undefined | id of the now-active step, when it declares one. |
onTabChange no longer fires on mount. Earlier releases reported a
spurious 0 → 0 transition on the first render. If you used that to
initialise something, do it directly instead.
onDataChange
Fires whenever wizard data changes — from updateData, setData, or a
controlled data prop being written back.
const [data, setData] = React.useState<WizardData>({ plan: "basic" });
<FormWizard data={data} onDataChange={setData} schema={schema} />;Passing data makes the wizard controlled: it renders what you give it and
reports intended changes through onDataChange, exactly like a controlled
input. Omit data to let the wizard own its state.
Headless equivalent
useWizard exposes the same callbacks as onStepChange and onDataChange:
const wizard = useWizard({
stepIds: ["a", "b"],
onStepChange: (e) => console.log(e),
onDataChange: (d) => console.log(d),
});See Props for full signatures, and References for the imperative methods.