FormRenderer
O componente principal que renderiza um FormSchema como um formulário multi-step ao vivo.
Import
import { FormRenderer } from "@schema-forms-data/renderer";
// ou
import { FormRenderer } from "@schema-forms-data/react";
Props
Obrigatórias
| Prop | Tipo | Descrição |
|---|---|---|
schema | FormSchema | A definição do formulário. Veja Core Types. |
Eventos
| Prop | Tipo | Descrição |
|---|---|---|
onSubmitStep | (stepIndex: number, data: Record<string, unknown>) => Promise<void> | Chamado quando o usuário avança cada step. Use para salvar rascunhos. |
onComplete | (data: Record<string, unknown>) => Promise<void> | Chamado no submit final com todos os valores acumulados de todos os steps. |
onValuesChange | (values: Record<string, unknown>) => void | Chamado a cada mudança de campo no step atual — útil para autosave. |
Visual
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
formTitle | string | undefined | Título exibido no topo do formulário. |
template | string | null | "moderno" | Chave do template. Veja Templates Customizados. |
className | string | undefined | Classe CSS extra aplicada ao wrapper raiz. |
StepIndicator | React.ComponentType<StepIndicatorProps> | built-in | Componente de indicador de step customizado. Veja abaixo. |
Dados
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
initialValues | Record<string, unknown> | {} | Pré-preenche valores dos campos quando o formulário carrega. |
initialStep | number | 0 | Inicia o formulário em um step específico (base 0). |
externalData | Record<string, unknown> | {} | Dados disponíveis para interpolação de template vars ({{evento.nome}}) e condicionais source: 'evento'. |
fieldErrors | Record<string, string> | {} | Erros de servidor por campo (ex: de uma resposta 422) definidos após o envio. |
Integrações
| Prop | Tipo | Descrição |
|---|---|---|
uploadFile | (file: File, fieldName: string, onProgress?: (pct: number) => void) => Promise<string> | Chamado quando o usuário seleciona um arquivo. Retorne o uploadId. |
deleteUploadedFile | (uploadId: string) => Promise<void> | Chamado automaticamente antes de substituir um arquivo, para deletar o anterior. Erros são silenciados. |
cepLookup | (cep: string, signal?: AbortSignal) => Promise<CepLookupResult> | Busca de CEP. Usa a API pública ViaCEP por padrão. |
resolveTermsUploadUrl | (uploadId: string) => Promise<string> | Resolve a URL de preview de um PDF de termos a partir de um uploadId. |
fieldResolvers | FieldResolvers | Props dinâmicas por campo — carregadas em tempo de render. Veja Injeção. |
validatorMapper | ValidatorMapper | Funções validadoras assíncronas customizadas. Veja Validação. |
componentMapper | ComponentMapper | Substitui o componente built-in de qualquer tipo de campo. Veja Component Mapper. |
paymentMethodOptions | { porDia?: PaymentOption[]; todosOsDias?: PaymentOption[] } | Opções customizadas para o campo payment_method. |
Exemplo de uso
import { FormRenderer } from "@schema-forms-data/renderer";
<FormRenderer
schema={schema}
formTitle="Cadastro"
template="moderno"
externalData={{ "evento.nome": "Acampamento 2026", "evento.valor": 5000 }}
initialValues={{ nome: "João" }}
uploadFile={async (file, fieldName, onProgress) => {
const form = new FormData();
form.append("file", file);
form.append("campo", fieldName);
const res = await fetch("/api/upload", { method: "POST", body: form });
const { id } = await res.json();
return id;
}}
deleteUploadedFile={async (uploadId) => {
await fetch(`/api/upload/${uploadId}`, { method: "DELETE" });
}}
cepLookup={async (cep) => {
const res = await fetch(`/api/cep/${cep}`);
return res.json(); // { logradouro, bairro, cidade, estado }
}}
resolveTermsUploadUrl={async (uploadId) => {
const res = await fetch(`/api/upload/${uploadId}/preview-url`);
const { url } = await res.json();
return url;
}}
validatorMapper={{
emailUnico: async (value) => {
const existe = await api.verificarEmail(String(value));
return existe ? "E-mail já cadastrado" : undefined;
},
}}
onSubmitStep={async (step, values) => api.salvarRascunho(step, values)}
onComplete={async (values) => api.finalizar(values)}
onValuesChange={(values) =>
sessionStorage.setItem("rascunho", JSON.stringify(values))
}
/>;
StepIndicator customizado
Substitua o indicador de step built-in com seu próprio componente:
import type { StepIndicatorProps } from "@schema-forms-data/renderer";
function MeuStepIndicator({
steps,
currentStep,
onStepClick,
}: StepIndicatorProps) {
return (
<div className="meus-steps">
{steps.map((step, i) => (
<button
key={step.id}
className={
i === currentStep ? "ativo" : i < currentStep ? "concluido" : ""
}
onClick={() => i < currentStep && onStepClick?.(i)}
>
{step.label}
</button>
))}
</div>
);
}
<FormRenderer
schema={schema}
StepIndicator={MeuStepIndicator}
onComplete={handleComplete}
/>;
interface StepIndicatorProps {
steps: Array<{ id: string; label?: string; icone?: string }>;
currentStep: number;
onStepClick?: (index: number) => void;
}