Skip to main content

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={...}
/>