useSubmitActionTriggers

Fires submit actions automatically on field change, field blur, step transitions, and idle timeout.

useSubmitActionTriggers

Manages automatic execution of submit actions based on non-submit triggers like field changes, blur events, step transitions, and idle timeouts. This is what powers real-time features like auto-saving on field change or sending analytics on step exit.

You probably don’t need this directly. The <Form> component wires it up internally whenever your config has submitActions. Use it when building custom trigger logic on top of your own form.


Signature

import { useSubmitActionTriggers } from '@saastro/forms';

const { triggerFieldChange, triggerFieldBlur, triggerManual, hasActionsForTrigger } =
  useSubmitActionTriggers({
    config,
    getValues,
    currentStep,
    onActionExecuted,
    onActionError,
    enabled,
  });

Parameters

ParameterTypeRequiredDescription
configFormConfigYesForm configuration with submit actions
getValues() => Record<string, unknown>YesFunction returning the current form values — pass methods.getValues itself (avoids re-renders)
currentStepstringYesActive step ID
onActionExecuted(result) => voidNoCalled after an action completes
onActionError(error, actionName) => voidNoCalled when an action fails
enabledbooleanNoEnable/disable all triggers (default: true)

getValues is a function reference, not a values object. Pass methods.getValues directly — do not call it (methods.getValues()). The hook reads values lazily at fire time, so triggers always see the latest data without subscribing to every keystroke.


Return Value

PropertyTypeDescription
triggerFieldChange(fieldName, value) => voidTrigger onFieldChange actions (debounced)
triggerFieldBlur(fieldName) => voidTrigger onFieldBlur actions (immediate)
triggerManual(actionIds?) => Promise<SubmitActionsResult>Manually trigger specific actions
hasActionsForTrigger(triggerType, triggerValue?) => booleanCheck if any actions exist for a trigger type

Trigger Types

TriggerWhen It FiresBehavior
onFieldChangeUser changes a field valueDebounced (debounceMs of the first matching action, default 300ms, per field)
onFieldBlurUser leaves a fieldImmediate
onStepEnterUser navigates to a stepAutomatic (via step change detection)
onStepExitUser leaves a stepAutomatic (via step change detection)
onDelayUser is idle for delayMs ms (default 30000)Automatic (listens to mousedown, keydown, touchstart, scroll; re-arms after each activity)
manualProgrammatic triggerVia triggerManual() call

onSubmit actions are not handled by this hook — they run inside the submit pipeline when the form is submitted. hasActionsForTrigger('onSubmit') still reports them.


Example: Manual Trigger

import { useFormState, useSubmitActionTriggers } from '@saastro/forms';
import type { FormConfig } from '@saastro/forms';

function SaveDraftButton({ config }: { config: FormConfig }) {
  const { methods, currentStepId } = useFormState({ config, fields: config.fields });

  const { triggerManual, hasActionsForTrigger } = useSubmitActionTriggers({
    config,
    getValues: methods.getValues, // pass the function, don't call it
    currentStep: currentStepId,
  });

  const saveDraft = async () => {
    // Check if there are manual actions available
    if (hasActionsForTrigger('manual')) {
      const result = await triggerManual(['save-draft']);
      console.log('Draft saved:', result.allSuccessful);
    }
  };

  return <button onClick={saveDraft}>Save draft</button>;
}

Notes

  • triggerManual ignores enabled — it executes even when enabled is false. The automatic effects and triggerFieldChange/triggerFieldBlur do respect it.
  • triggerFieldChange ignores its value argument; values are read via getValues() when the debounced action actually fires.
  • The hook’s option and return interfaces are not exported types — only the function itself is public.
  • All debounce and idle timers are cleared on unmount.