useHiddenFieldResolvers

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

View as Markdown

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

Parameter Type Required Description
methods UseFormReturn<Record<string, unknown>> Yes react-hook-form instance from useForm()
fields Fields Yes Form 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

Resolver Async Output
timestamp No ISO 8601 string
hostname No window.location.hostname
pageUrl No window.location.href
referrer No document.referrer
userAgent No navigator.userAgent
urlParam No URL query parameter value — options { param, fallback? }
ip Yes Visitor 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.