Hooks
Learn about the hooks provided by the Figma Forms Renderer for managing form state and behavior
The Figma Forms Renderer provides several custom React hooks to manage form state, navigation, validation, and data. These hooks allow you to easily interact with the form's functionality and state within your React components.
These hooks must be used within a <FormProvider> component to ensure they have access to the necessary context.
useFormData
Returns the static properties from the JsonForm object passed to the <FormProvider>.
| Property | Type | Description |
|---|---|---|
| title | string | The title of the form. |
| description | string | The description of the form. |
| pages | JsonFormPage[] | An array of form pages. |
Examples
Use title and description to display the form header.
import { useFormData } from "@/components/formProvider";
export function FormHeader() {
const { title, description } = useFormData();
return (
<header>
<h1>{title}</h1>
<p>{description}</p>
</header>
);
}Use pages to create a sidebar listing all form pages.
import { useFormData } from "@/components/formProvider";
export function FormSidebar() {
const { pages } = useFormData();
return (
<aside>
<ul>
{pages.map((page) => (
<li key={page.id}>{page.title}</li>
))}
</ul>
</aside>
);
}useFormNavigation
Returns the active page's JsonFormPage object and functions to navigate between form pages.
| Property | Type | Description |
|---|---|---|
| currentPage | JsonFormPage | The currently active form page. |
| pageIdx | number | The index of the currently active page. |
| nextPage | () => void | Navigate to the next form page. |
| prevPage | () => void | Navigate to the previous form page. |
| goToPage | (idx: number) => void | Navigate to a specific form page by index. |
All navigation methods respect page validation and will not navigate to the next page if the current page has validation errors.
Examples
Use currentPage to display the active page's title and description. Use nextPage and prevPage for navigation buttons.
import { useFormNavigation } from "@/components/formProvider";
import { FormRenderer } from "@/components/formRenderer";
export function FormPage() {
const { currentPage, pageIdx, nextPage, prevPage } = useFormNavigation();
return (
<div>
<h2>
Page {pageIdx + 1}: {currentPage.title}
</h2>
<h3>{currentPage.description}</h3>
<FormRenderer />
<div>
{pageIdx !== 0 && <button onClick={prevPage}>Previous</button>}
<button onClick={nextPage}>Next</button>
</div>
</div>
);
}Use goToPage to create a sidebar for direct page navigation.
import { useFormNavigation, useFormData } from "@/components/formProvider";
export function FormSidebar() {
const { pages } = useFormData();
const { goToPage } = useFormNavigation();
return (
<aside>
<ul>
{pages.map((page, index) => (
<li key={page.id} onClick={() => goToPage(index)}>
{page.title}
</li>
))}
</ul>
</aside>
);
}useFormStatus
Returns the completion status of pages and the overall form.
| Property | Type | Description |
|---|---|---|
| getStepStatus | () => StepStatus | Returns the total and completed step counts |
| getPageInfo | (idx: number) => PageInfo | Returns information about a specific page by index. |
Examples
Use getStepStatus to display form progress.
import { useFormStatus } from "@/components/formProvider";
export function FormProgress() {
const { getStepStatus } = useFormStatus();
const { totalSteps, completedSteps } = getStepStatus();
return (
<div>
Progress: {completedSteps} / {totalSteps} steps completed
</div>
);
}Use getPageInfo to create a sidebar with page status indicators.
import { useFormNavigation, useFormStatus } from "@/components/formProvider";
export function SidebarItem(props: { title: string; idx: number }) {
const { title, idx } = props;
const { goToPage } = useFormNavigation();
const { getPageInfo } = useFormStatus();
const { complete, disabled, isCurrent } = getPageInfo(idx);
return (
<li
onClick={() => goToPage(idx)}
style={{
textDecoration: complete ? "line-through" : "none",
fontWeight: isCurrent ? "bold" : "normal",
color: disabled ? "gray" : "black",
cursor: disabled ? "not-allowed" : "pointer",
}}
>
{title}
</li>
);
}useFormState
Manages and provides access to the form's state.
| Property | Type | Description |
|---|---|---|
| formState | FormState | The current state of the form. |
| setFormState | (state: FormState) => void | Function to update the form state. |
| handleCheckboxChange | (groupId: string, itemId: string, elements: Checkbox[]) => void | Handle changes in checkbox groups. |
| handleRadioChange | (groupId: string, itemId: string, elements: RadioButton[]) => void | Handle changes in radio button groups. |
The formState object contains the current values of all form fields, where keys are field IDs and values are user inputs. See formProvider/types.ts for more details on the FormState type.
Form field components generally handle state updates using JsonForms' built-in handleChange method. However, nested fields require special handlers that also remove child field values when a parent field is unchecked or when a radio button selection changes.
Examples
Use formState to submit the form data.
import { useFormState } from "@/components/formProvider";
export function FormSubmit() {
const { formState } = useFormState();
const handleSubmit = () => {
// Simulate form submission
console.log("Form submitted with state:", formState);
};
return <button onClick={handleSubmit}>Submit Form</button>;
}Use setFormState to reset the form.
import { useFormState } from "@/components/formProvider";
export function FormReset() {
const { setFormState } = useFormState();
const handleReset = () => {
setFormState({});
};
return <button onClick={handleReset}>Reset Form</button>;
}useFormValidation
Returns validation status and functions to validate the form.
| Property | Type | Description |
|---|---|---|
| errors | ErrorObject[] | An array of AJV validation errors for the current page. |
| setErrors | (errors: ErrorObject[]) => void | Function to set validation errors. |
| validationMode | ValidationMode | The current validation mode of the form ("None" or "ValidateAndShow"). |
Example
Use errors to display validation errors for the current page.
import { useFormValidation } from "@/components/formProvider";
export function ErrorsPanel() {
const { errors, validationMode } = useFormValidation();
if (validationMode !== "ValidateAndShow" || errors.length === 0) {
return null;
}
return (
<div>
<h3>Validation Errors:</h3>
<ul>
{errors.map((error, index) => (
<li key={index}>{error.message}</li>
))}
</ul>
</div>
);
}