useHiddenFieldResolvers

Resolves hidden field values at form mount — timestamps, URLs, IP addresses, and UTM parameters.

useHiddenFieldResolvers

Resolves all hidden field values when the form mounts. Filters fields with type: 'hidden', runs their resolvers in parallel, and sets the values via react-hook-form’s setValue.

You probably don’t need this directly. It runs automatically inside useFormState (and therefore inside <Form />). Use it only when building a custom form renderer that needs to support hidden fields.


Signature

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

useHiddenFieldResolvers(methods, fields);

Parameters

ParameterTypeRequiredDescription
methodsUseFormReturn<Record<string, unknown>>Yesreact-hook-form instance from useForm()
fieldsFieldsYesForm field configurations from config.fields

Return Value

This hook returns void. It operates as a side-effect only — setting hidden field values via methods.setValue().


How It Works

  1. On mount (and again if fields or methods change), filters all fields where type === 'hidden' — if there are none, it does nothing
  2. Runs all resolvers concurrently via Promise.all and resolveValue()
  3. Sets each value with setValue(name, value, { shouldDirty: false })
  4. Cleanup function prevents stale writes if the component unmounts before resolvers complete

Most resolvers produce their value instantly (timestamp, hostname, pageUrl, referrer, userAgent, urlParam). The ip resolver uses fetch and is genuinely async. All run concurrently regardless.


Example

import { useHiddenFieldResolvers } from '@saastro/forms';
import type { FormConfig } from '@saastro/forms';
import { useForm } from 'react-hook-form';

function CustomFormRenderer({ config }: { config: FormConfig }) {
  const methods = useForm<Record<string, unknown>>({ defaultValues: {} });

  // Resolves hidden field values on mount
  useHiddenFieldResolvers(methods, config.fields);

  const onSubmit = (values: Record<string, unknown>) => {
    console.log(values); // includes the resolved hidden values
  };

  return (
    <form onSubmit={methods.handleSubmit(onSubmit)}>
      {/* Render visible fields... */}
      {/* Hidden fields render nothing, but their values are in form state */}
    </form>
  );
}

Built-in Resolvers

ResolverAsyncOutput
timestampNoISO 8601 string
hostnameNowindow.location.hostname
pageUrlNowindow.location.href
referrerNodocument.referrer
userAgentNonavigator.userAgent
urlParamNoURL query parameter value — options { param, fallback? }
ipYesVisitor IP via fetch — options { endpoint?, fallback? } (default https://api.ipify.org?format=json)

Hidden fields accept only these serializable built-ins (SerializableFieldResolver) — the function-based custom resolver is excluded so configs stay JSON-storable. All resolvers are SSR-safe: when browser globals (window, document, navigator) are unavailable, urlParam returns its fallback (or an empty string) and the other browser-based resolvers return an empty string. The ip resolver returns its fallback (or an empty string) if the fetch fails.