Hooks & FormSpy
Acesse o estado do formulário e a API programática a partir de qualquer componente dentro do <FormRenderer>.
Todos os hooks e o <FormSpy> precisam estar montados dentro da árvore do <FormRenderer> (ex: dentro de um componente de campo customizado ou um filho renderizado por um componente do componentMapper).
useFormApi
Retorna a API programática do formulário.
import { useFormApi } from "@schema-forms-data/renderer";
const api = useFormApi();
Tipo de retorno
interface FormApi {
change: (name: string, value: unknown) => void;
submit: () => void;
reset: (values?: Record<string, unknown>) => void;
getState: () => FormStateSnapshot;
}
Exemplo
import { useFormApi } from "@schema-forms-data/renderer";
function BotaoPreenchimento() {
const api = useFormApi();
return (
<button
type="button"
onClick={() => {
api.change("nome", "João Silva");
api.change("email", "joao@email.com");
}}
>
Preencher com meus dados
</button>
);
}
useFormState
Retorna o estado reativo do formulário — re-renderiza a cada mudança de campo.
import { useFormState } from "@schema-forms-data/renderer";
const { values, errors, warnings, dirty, valid, submitting } = useFormState();
Tipo de retorno
interface FormStateValue {
values: Record<string, unknown>;
errors: Record<string, string | undefined>;
warnings: Record<string, string>; // de validators warn[]
dirty: boolean;
valid: boolean;
submitting: boolean;
}
Exemplo
import { useFormState } from "@schema-forms-data/renderer";
function BarraStatus() {
const { dirty, valid, submitting, errors } = useFormState();
return (
<div className="barra-status">
{dirty && (
<span className="badge badge-aviso">Alterações não salvas</span>
)}
{!valid && (
<span className="badge badge-erro">
Corrija {Object.keys(errors).length} erro(s)
</span>
)}
{submitting && <span>Salvando…</span>}
</div>
);
}
useField
Retorna o estado de um campo individual — reativo.
import { useField } from "@schema-forms-data/renderer";
const { value, error, warning, dirty, touched, valid } = useField("email");
Tipo de retorno
interface FieldState {
value: unknown;
error?: string;
warning?: string; // de validators warn[]
dirty: boolean;
touched: boolean;
valid: boolean;
}
Exemplo
import { useField } from "@schema-forms-data/renderer";
function DicaEmail() {
const email = useField("email");
if (!email.touched) return null;
if (email.error) return <p className="erro">{email.error}</p>;
if (email.warning) return <p className="aviso">⚠ {email.warning}</p>;
return <p className="sucesso">✓ E-mail válido</p>;
}
useFieldApi
Retorna props input e dados meta para construir componentes de campo customizados.
import { useFieldApi } from "@schema-forms-data/renderer";
const { input, meta } = useFieldApi("email");
Tipo de retorno
interface FieldApiReturn {
input: {
name: string;
value: unknown;
onChange: (...args: unknown[]) => void;
onBlur: () => void;
ref: React.Ref<unknown>;
};
meta: {
error?: string;
warning?: string;
touched: boolean;
dirty: boolean;
valid: boolean;
};
}
Exemplo
import { useFieldApi } from "@schema-forms-data/renderer";
function MeuEmailInput() {
const { input, meta } = useFieldApi("email");
return (
<div>
<input
type="email"
{...(input as React.InputHTMLAttributes<HTMLInputElement>)}
className={meta.error ? "input-erro" : ""}
/>
{meta.error && <span className="erro">{meta.error}</span>}
{meta.warning && <span className="aviso">{meta.warning}</span>}
</div>
);
}
<FormSpy>
Observa o estado do formulário como um componente React. Útil quando não é possível usar hooks (ex: precisa renderizar fora do formulário, ou fazer bridge com um contexto não-hook).
import { FormSpy } from "@schema-forms-data/renderer";
Padrão 1 — render prop
<FormSpy
render={(state) => <pre>{JSON.stringify(state.values, null, 2)}</pre>}
/>
Padrão 2 — children como função
<FormSpy>{(state) => <span>{state.valid ? "✓" : "×"}</span>}</FormSpy>
Padrão 3 — callback onChange
<FormSpy
onChange={(state) => {
if (state.dirty)
sessionStorage.setItem("rascunho", JSON.stringify(state.values));
}}
/>
Padrão 4 — combinado
<FormSpy
onChange={(state) => api.autoSave(state.values)}
render={(state) => (
<div className="rodape-form">
{state.submitting ? "Enviando…" : state.dirty ? "Não salvo" : "Salvo"}
</div>
)}
/>