RendererContext
Contexto interno que carrega todas as integrações injetáveis pelo FormRenderer. Você configura tudo via props do FormRenderer e o contexto é montado automaticamente.
useRendererContext
Acessa o contexto a partir de qualquer componente dentro do <FormRenderer>. Use dentro de componentes customizados criados via componentMapper:
import { useRendererContext } from "@schema-forms-data/renderer";
const {
uploadFile,
deleteUploadedFile,
cepLookup,
resolveTermsUploadUrl,
externalData,
fieldResolvers,
validatorMapper,
componentMapper,
} = useRendererContext();
RendererContextValue
interface RendererContextValue {
uploadFile?: (
file: File,
fieldName: string,
onProgress?: (pct: number) => void,
) => Promise<string>;
deleteUploadedFile?: (uploadId: string) => Promise<void>;
cepLookup?: (cep: string, signal?: AbortSignal) => Promise<CepLookupResult>;
resolveTermsUploadUrl?: (uploadId: string) => Promise<string>;
externalData?: Record<string, unknown>;
fieldResolvers?: FieldResolvers;
validatorMapper?: ValidatorMapper;
componentMapper?: ComponentMapper;
paymentMethodOptions?: {
porDia?: PaymentOption[];
todosOsDias?: PaymentOption[];
};
}
CepLookupResult
interface CepLookupResult {
logradouro?: string;
bairro?: string;
cidade?: string;
estado?: string;
erro?: boolean;
}
ValidatorMapper
Mapa de funções de validação customizadas. Referenciadas no schema via validate[] e warn[].
type FieldValidatorFn = (
value: unknown,
allValues: Record<string, unknown>, // todos os valores do step atual
config: FieldValidatorConfig, // { type, message, ...params }
externalData: Record<string, unknown>,
) => string | undefined | Promise<string | undefined>;
type ValidatorMapper = Record<string, FieldValidatorFn>;
Exemplo:
<FormRenderer
schema={schema}
validatorMapper={{
emailUnico: async (value) => {
const exists = await api.checkEmail(String(value));
return exists ? "E-mail já cadastrado" : undefined;
},
senhasIguais: (value, allValues, config) => {
const other = allValues[config["field"] as string];
return value === other ? undefined : "As senhas não conferem";
},
minIdade: (value, _all, config) => {
const idade = calcularIdade(String(value));
const min = (config["min"] as number) ?? 18;
return idade >= min ? undefined : `Mínimo ${min} anos`;
},
}}
onComplete={handler}
/>
Veja Validação para o guia completo.
ComponentMapper
Mapa de componentes React que substituem os componentes padrão por tipo de campo.
interface FieldComponentProps {
name: string;
control: Control<Record<string, unknown>>;
field: FormField; // já resolvido (após resolveProps + opcoesFromVar)
}
type ComponentMapper = Record<string, React.ComponentType<FieldComponentProps>>;
Exemplo:
import { FieldType } from "@schema-forms-data/core";
import { useController } from "react-hook-form";
import type { FieldComponentProps } from "@schema-forms-data/renderer";
const MeuTextField = ({ name, control, field }: FieldComponentProps) => {
const { field: rhf, fieldState } = useController({ name, control });
return (
<MeuInput
{...rhf}
label={field.label}
placeholder={field.placeholder}
disabled={field.isDisabled}
error={fieldState.error?.message}
/>
);
};
<FormRenderer
schema={schema}
componentMapper={{
[FieldType.TEXTO]: MeuTextField,
}}
onComplete={handler}
/>;
Veja Component Mapper para o guia completo.
FieldResolvers
Props dinâmicas por campo, resolvidas em tempo de render.
type FieldResolver = (
field: FormField,
formValues: Record<string, unknown>,
externalData: Record<string, unknown>,
) => Partial<FormField>;
type FieldResolvers = Record<string, FieldResolver>;
Exemplo — carregar opções do campo a partir de dados externos:
<FormRenderer
schema={schema}
fieldResolvers={{
opcoes_camiseta: (_field, _values, external) => ({
opcoes:
(external["evento.tamanhosCamiseta"] as string[])?.map((t) => ({
valor: t,
label: t,
})) ?? [],
}),
}}
externalData={{ "evento.tamanhosCamiseta": ["P", "M", "G", "GG"] }}
onComplete={handler}
/>
No schema, o campo FormField deve ter resolvePropsKey: "opcoes_camiseta".
Veja Injection para o guia completo.
Fields that use this must have resolvePropsKey set in the schema matching the key in fieldResolvers.
CepLookupResult
interface CepLookupResult {
logradouro?: string;
bairro?: string;
cidade?: string;
estado?: string;
erro?: boolean; // true if CEP not found
}
Default cepLookup
If cepLookup is not provided, DFCepField falls back to the public ViaCEP API.
// Use your own API:
<FormRenderer
schema={schema}
cepLookup={async (cep) => {
const res = await fetch(`/api/cep/${cep}`);
return res.json();
}}
onComplete={...}
/>