### Install @formity/react Source: https://context7.com/martiserra99/formity/llms.txt Install the React package for Formity using npm. ```bash npm install @formity/react ``` -------------------------------- ### Integrate ESLint React Plugin Source: https://github.com/martiserra99/formity/blob/main/apps/react/README.md Install eslint-plugin-react and update your ESLint configuration to include its recommended rules. This setup also configures the React version for ESLint. ```javascript // eslint.config.js import react from 'eslint-plugin-react' export default tseslint.config({ // Set the react version settings: { react: { version: '18.3' } }, plugins: { // Add the react plugin react, }, rules: { // other rules... // Enable its recommended rules ...react.configs.recommended.rules, ...react.configs['jsx-runtime'].rules, }, }) ``` -------------------------------- ### Formity with Inputs and Params in React Source: https://context7.com/martiserra99/formity/llms.txt Demonstrates how to use 'inputs' for flow logic and 'params' for render functions in a Formity flow. Ensure 'inputs' and 'params' are correctly typed in the Schema. ```tsx import { useFormity, Flow, s } from "@formity/react"; type Schema = { render: React.ReactNode; struct: [ s.Form<{ choice: string }>, s.Return<{ choice: string; userId: string }>, ]; inputs: { availableOptions: string[] }; // used in flow logic params: { userId: string }; // available in render }; const flow: Flow = [ { form: { fields: ({ availableOptions }) => ({ choice: [availableOptions[0], []], }), render: ({ fields, params, onNext }) => (

User: {params.userId}

), }, }, { return: ({ choice }, inputs, params) => ({ choice, userId: params.userId }), }, ]; function App() { return ( <> {useFormity({ flow, inputs: { availableOptions: ["option-a", "option-b"] }, params: { userId: "user-42" }, onReturn: (v) => console.log(v), })} ); } ``` -------------------------------- ### `onBack` — return to the previous step Source: https://context7.com/martiserra99/formity/llms.txt Navigates backward in the form, persisting the current field values so they are pre-filled on return. ```APIDOC ## `onBack` — return to the previous step ### Description Navigates backward, persisting the current field values so they are pre-filled on return. ### Usage ```tsx render: ({ fields, onBack }) => ( ) ``` ``` -------------------------------- ### `initialState` and `State` — save and resume Source: https://context7.com/martiserra99/formity/llms.txt The `State` type holds navigation history (`points`) and all field values (`memory`). It can be serialized and passed back as `initialState` to resume a form session. ```APIDOC ## `initialState` and `State` — save and resume The `State` type (from `@formity/system`) holds `points` (navigation history) and `memory` (all field values entered). It can be serialized and passed back as `initialState` to resume a session. ```tsx import { useState } from "react"; import { useFormity, Flow, s, State, OnReturn } from "@formity/react"; type Schema = { render: React.ReactNode; struct: [s.Form<{ step1: string }>, s.Form<{ step2: string }>, s.Return<{ step1: string; step2: string }>]; inputs: Record; params: Record; }; declare const flow: Flow; function ResumableForm() { // Load saved state from storage (null on first visit) const saved = localStorage.getItem("formState"); const initialState: State | undefined = saved ? JSON.parse(saved) : undefined; const onReturn: OnReturn = (values) => { localStorage.removeItem("formState"); console.log("Done:", values); }; return ( <> {useFormity({ flow, initialState, onReturn, // Use getState inside render to persist on each step })} ); } ``` ``` -------------------------------- ### Use useFormity Hook for Multi-Step Forms Source: https://context7.com/martiserra99/formity/llms.txt The primary hook for running a multi-step form. It accepts a flow, optional inputs/params, initial state, and callbacks for yielding and returning values. Ensure the schema, flow, and hook usage are correctly defined. ```tsx import { useFormity, Flow, s, OnReturn, OnYield } from "@formity/react"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; // 1. Define the Schema — describes the shape of inputs, params, and struct type MySchema = { render: React.ReactNode; struct: [ s.Form<{ name: string; age: number }>, s.Return<{ name: string; age: number }>, ]; inputs: Record; params: Record; }; // 2. Define the flow array const flow: Flow = [ { form: { fields: () => ({ name: ["", []], // [defaultValue, dependencyKeys] age: [18, []], }), render: ({ fields, onNext }) => (
{ e.preventDefault(); onNext({ name: "Alice", age: 30 }); }}>
), }, }, { return: ({ name, age }) => ({ name, age }), }, ]; // 3. Use the hook inside a component function MultiStepForm() { const onReturn: OnReturn = (values) => { // values: { name: string; age: number } console.log("Form completed:", values); }; const onYield: OnYield = (values) => { // called at every yield element during navigation console.log("Step data:", values); }; return <>{useFormity({ flow, onReturn, onYield })}; } ``` -------------------------------- ### Jump to a labelled step with `onJump` Source: https://context7.com/martiserra99/formity/llms.txt Use `onJump` to navigate directly to a specific step identified by an `id`. It can also persist field values. ```tsx render: ({ fields, onJump }) => ( ) ``` -------------------------------- ### Use Formity Component as a Wrapper Source: https://context7.com/martiserra99/formity/llms.txt A functional component wrapper for useFormity, useful for declarative composition. It accepts the same options as the hook and delegates directly to it. ```tsx import { Formity, Flow, s, OnReturn } from "@formity/react"; type Schema = { render: React.ReactNode; struct: [s.Form<{ email: string }>, s.Return<{ email: string }>]; inputs: Record; params: Record; }; const flow: Flow = [ { form: { fields: () => ({ email: ["", []] }), render: ({ fields, onNext }) => (
), }, }, { return: ({ email }) => ({ email }) }, ]; function App() { const onReturn: OnReturn = (values) => console.log(values); // Formity() returns the current step's React node return <>{Formity({ flow, onReturn })}; } ``` -------------------------------- ### Return to the previous step with `onBack` Source: https://context7.com/martiserra99/formity/llms.txt Use `onBack` to navigate backward in the form flow. It persists the current field values, allowing them to be pre-filled when the user returns to that step. ```tsx render: ({ fields, onBack }) => ( ) ``` -------------------------------- ### Save and resume form sessions with `initialState` and `State` Source: https://context7.com/martiserra99/formity/llms.txt The `State` type captures navigation history and field values, allowing forms to be resumed. Pass a serialized `State` object to `initialState` when initializing `useFormity`. ```tsx import { useState } from "react"; import { useFormity, Flow, s, State, OnReturn } from "@formity/react"; type Schema = { render: React.ReactNode; struct: [s.Form<{ step1: string }>, s.Form<{ step2: string }>, s.Return<{ step1: string; step2: string }>]; inputs: Record; params: Record; }; declare const flow: Flow; function ResumableForm() { // Load saved state from storage (null on first visit) const saved = localStorage.getItem("formState"); const initialState: State | undefined = saved ? JSON.parse(saved) : undefined; const onReturn: OnReturn = (values) => { localStorage.removeItem("formState"); console.log("Done:", values); }; return ( <> {useFormity({ flow, initialState, onReturn, // Use getState inside render to persist on each step })} ); } ``` -------------------------------- ### `onNext` — advance to the next step Source: https://context7.com/martiserra99/formity/llms.txt Advances the form to the next step, saving the provided field values into the form's state. ```APIDOC ## `onNext` — advance to the next step ### Description Advances the form to the next step, saving the provided field values into state. ### Usage ```tsx render: ({ fields, onNext }) => ( ) ``` ``` -------------------------------- ### useFormity Hook Source: https://context7.com/martiserra99/formity/llms.txt The primary hook for running a multi-step form. It accepts a flow definition, optional inputs/params, initial state, and callbacks for yielding and returning values. It returns the React node for the current step. ```APIDOC ## useFormity ### Description The primary hook for running a multi-step form. Accepts a `flow`, optional `inputs`/`params`, optional `initialState` for resuming, and `onYield`/`onReturn` callbacks. Returns the rendered React node for the current step. ### Signature ```typescript useFormity(options: { flow: Flow; inputs?: TSchema['inputs']; params?: TSchema['params']; initialState?: any; onYield?: OnYield; onReturn?: OnReturn; }): React.ReactNode; ``` ### Parameters - **flow** (Flow) - Required - The definition of the form's structure and behavior. - **inputs** (TSchema['inputs']) - Optional - Input values for the form. - **params** (TSchema['params']) - Optional - Parameters for the form. - **initialState** (any) - Optional - Initial state for resuming the form. - **onYield** (OnYield) - Optional - Callback function invoked at each yield element during navigation. - **onReturn** (OnReturn) - Optional - Callback function invoked when the form completes. ### Returns - **React.ReactNode** - The rendered React node for the current step of the form. ``` -------------------------------- ### Restore previously saved state with `setState` Source: https://context7.com/martiserra99/formity/llms.txt Use `setState` by passing a previously saved `State` object to `initialState` to resume a form session exactly where the user left off. ```tsx // Restore a saved form session import { useFormity, State } from "@formity/react"; const saved: State = JSON.parse(localStorage.getItem("state") ?? "null"); useFormity({ flow, initialState: saved, // resumes exactly where the user left off onReturn, }); ``` -------------------------------- ### Define schema struct helpers with `s.*` Source: https://context7.com/martiserra99/formity/llms.txt The `s` namespace provides type helpers for defining the `struct` array in a `Schema`. Use these to specify the types and structure of form steps and data transformations. ```typescript import type { s } from "@formity/react"; // Available struct helpers: // s.Form — a form step with given field types // s.Variables — injects new variables into the accumulated values // s.Condition<{then, else}> — conditional branch // s.Loop — loop with a do body // s.Switch<{branches, default}> — multi-branch switch // s.Jump — named jump target // s.Yield<{next, back}> — intermediate yield // s.Return — final return value type ExampleStruct: [ s.Form<{ name: string }>, // step 1: collects name s.Variables<{ greeting: string }>, // step 2: derives greeting s.Return<{ greeting: string }>, // step 3: returns result ] ``` -------------------------------- ### Looping through items with Formity Source: https://context7.com/martiserra99/formity/llms.txt Use `s.Loop` to repeat a sequence of steps while a condition holds. Variables are typically used alongside loops to track the iteration index and accumulate results. Ensure all necessary variables are declared and updated within the loop's `do` block. ```tsx import type { Flow, s } from "@formity/react"; type Schema = { render: React.ReactNode; struct: [ s.Variables<{ items: string[]; i: number; results: string[] }>, s.Loop<[ s.Variables<{ item: string }>, s.Form<{ response: string } >, s.Variables<{ i: number; results: string[] } >, ]>, s.Return<{ results: string[] }>, ]; inputs: Record; params: Record; }; const flow: Flow = [ { variables: () => ({ items: ["React", "TypeScript", "Node.js"], i: 0, results: [], }), }, { loop: { while: ({ i, items }) => i < items.length, do: [ { variables: ({ i, items }) => ({ item: items[i] }), }, { form: { fields: ({ item }) => ({ response: ["yes", [item]] }), render: ({ values, fields, onNext }) => (

Do you use {values.item}?

), }, }, { variables: ({ i, results, item, response }) => ({ i: i + 1, results: [...results, `${item}: ${response}`], }), }, ], }, }, { return: ({ results }) => ({ results }) }, // => { results: ["React: yes", "TypeScript: yes", "Node.js: no"] } ]; ``` -------------------------------- ### Form Component for User Input Source: https://context7.com/martiserra99/formity/llms.txt Use the `form` component to define fields for user input and render a form. It handles default values and submission logic, calling `onNext` with collected data. ```tsx import type { Flow, s } from "@formity/react"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; type Schema = { render: React.ReactNode; struct: [ s.Form<{ username: string; password: string }>, s.Return<{ username: string }>, ]; inputs: Record; params: { submitLabel: string }; }; const flow: Flow = [ { form: { fields: () => ({ username: ["", []], password: ["", []], }), render: ({ fields, params, onNext, onBack }) => (
{ e.preventDefault(); const fd = new FormData(e.currentTarget); onNext({ username: fd.get("username") as string, password: fd.get("password") as string, }); }} >
), }, }, { return: ({ username }) => ({ username }) }, ]; ``` -------------------------------- ### Conditional routing with Formity switch Source: https://context7.com/martiserra99/formity/llms.txt Use `s.Switch` for multi-branch routing. It routes to the first branch whose `case` predicate returns `true`, or falls through to `default`. Each branch is a full `ListFlow` and must be defined within the `branches` array. ```tsx import type { Flow, s } from "@formity/react"; type Schema = { render: React.ReactNode; struct: [ s.Form<{ plan: string }>, s.Switch<{ branches: [ [s.Form<{ seats: number }>, s.Return<{ plan: "team"; seats: number }>], [s.Form<{ domain: string }>, s.Return<{ plan: "enterprise"; domain: string }>], ]; default: [s.Return<{ plan: "free" }>]; }>, ]; inputs: Record; params: Record; }; const flow: Flow = [ { form: { fields: () => ({ plan: ["free", []] }), render: ({ fields, onNext }) => ( ), }, }, { switch: { branches: [ { case: ({ plan }) => plan === "team", then: [ { form: { fields: () => ({ seats: [5, []] }), render: ({ fields, onNext }) => (
), }, }, { return: ({ plan, seats }) => ({ plan: "team", seats }) }, ], }, { case: ({ plan }) => plan === "enterprise", then: [ { form: { fields: () => ({ domain: ["", []] }), render: ({ fields, onNext }) => (
), }, }, { return: ({ plan, domain }) => ({ plan: "enterprise", domain }) }, ], }, ], default: [ { return: () => ({ plan: "free" }) }, ], }, }, ]; ``` -------------------------------- ### `f.*` — flow element helpers Source: https://context7.com/martiserra99/formity/llms.txt The `f` namespace mirrors `s.*` but is used for constructing the actual `Flow` array values, though these are less commonly used as flow arrays are typically inferred from their structure automatically. ```APIDOC ### `f.*` — flow element helpers The `f` namespace mirrors `s.*` but for constructing the actual `Flow` array values (used less commonly — the flow arrays are inferred from their structure automatically). ```ts import type { f } from "@formity/react"; // f.Form // f.Variables // f.Condition<{then, else}> // f.Loop // f.Switch<{branches, default}> // f.Jump // f.Yield<{next, back}> // f.Return ``` ``` -------------------------------- ### `getState` — snapshot the current form state Source: https://context7.com/martiserra99/formity/llms.txt Captures a snapshot of the current form's state, including navigation history and all entered field values. This snapshot can be used to save progress. ```APIDOC ## `getState` — snapshot the current form state ### Description Captures a snapshot of the current form's state, including navigation history (`points`) and all entered field values (`memory`). This snapshot can be used to save progress. ### Usage ```tsx render: ({ fields, getState }) => { const snapshot = getState(fields); // returns a State object // { points: [...], memory: { ... } } // Use to save progress: localStorage.setItem("state", JSON.stringify(snapshot)) return ; } ``` ``` -------------------------------- ### Formity Component Source: https://context7.com/martiserra99/formity/llms.txt A functional wrapper around the `useFormity` hook. It accepts the same options as `useFormity` and is useful for declarative form composition. ```APIDOC ## Formity ### Description A functional wrapper component around `useFormity`. It delegates directly to `useFormity` and accepts the same options, making it useful for composing forms declaratively. ### Signature ```typescript function Formity(options: { flow: Flow; inputs?: TSchema['inputs']; params?: TSchema['params']; initialState?: any; onYield?: OnYield; onReturn?: OnReturn; }): React.ReactNode; ``` ### Parameters - **flow** (Flow) - Required - The definition of the form's structure and behavior. - **inputs** (TSchema['inputs']) - Optional - Input values for the form. - **params** (TSchema['params']) - Optional - Parameters for the form. - **initialState** (any) - Optional - Initial state for resuming the form. - **onYield** (OnYield) - Optional - Callback function invoked at each yield element during navigation. - **onReturn** (OnReturn) - Optional - Callback function invoked when the form completes. ### Returns - **React.ReactNode** - The rendered React node for the current step of the form. ``` -------------------------------- ### Snapshot current form state with `getState` Source: https://context7.com/martiserra99/formity/llms.txt The `getState` function captures the current form's state, including navigation history and all entered field values. This snapshot can be serialized for saving progress. ```tsx render: ({ fields, getState }) => { const snapshot = getState(fields); // returns a State object // { points: [...], memory: { ... } } // Use to save progress: localStorage.setItem("state", JSON.stringify(snapshot)) return ; } ``` -------------------------------- ### `s.*` — schema struct helpers Source: https://context7.com/martiserra99/formity/llms.txt The `s` namespace provides helper types for defining the `struct` array in a `Schema`. Each element in `struct` uses one of these types to encode what values the form element produces. ```APIDOC ## TypeScript Utilities: `s` and `f` ### `s.*` — schema struct helpers The `s` namespace provides helper types for defining the `struct` array in a `Schema`. Each element in `struct` uses one of these types to encode what values the form element produces. ```ts import type { s } from "@formity/react"; // Available struct helpers: // s.Form — a form step with given field types // s.Variables — injects new variables into the accumulated values // s.Condition<{then, else}> — conditional branch // s.Loop — loop with a do body // s.Switch<{branches, default}> — multi-branch switch // s.Jump — named jump target // s.Yield<{next, back}> — intermediate yield // s.Return — final return value type ExampleStruct: [ s.Form<{ name: string }>, s.Variables<{ greeting: string }>, s.Return<{ greeting: string }>, ] ``` ``` -------------------------------- ### Advance to the next step with `onNext` Source: https://context7.com/martiserra99/formity/llms.txt Use `onNext` to programmatically move to the next step in the form flow. It accepts an object to save specific field values into the form's state. ```tsx render: ({ fields, onNext }) => ( ) ``` -------------------------------- ### `onJump` — jump to a labelled step Source: https://context7.com/martiserra99/formity/llms.txt Jumps to a specific step in the form flow identified by a label. The `id` must match a jump element's `id` property in the flow. ```APIDOC ## `onJump` — jump to a labelled step ### Description Jumps to a specific step in the form flow identified by a label. The `id` must match a jump element's `id` property in the flow. ### Usage ```tsx render: ({ fields, onJump }) => ( ) ``` ``` -------------------------------- ### Terminate Flow and Emit Result with Return in Formity Source: https://context7.com/martiserra99/formity/llms.txt Every flow must end with a `return` element (or with a `return` in every branch). The function receives all accumulated values and returns the final typed output, which is passed to `onReturn`. ```tsx import type { Flow, s, OnReturn } from "@formity/react"; type Schema = { render: React.ReactNode; struct: [ s.Form<{ name: string; age: number }>; s.Variables<{ isAdult: boolean }>; s.Return<{ name: string; age: number; isAdult: boolean }>; ]; inputs: Record; params: Record; }; const flow: Flow = [ { form: { fields: () => ({ name: ["", []], age: [0, []] }), render: ({ fields, onNext }) => ( ), }, }, { variables: ({ age }) => ({ isAdult: age >= 18 }), }, { return: ({ name, age, isAdult }) => ({ name, age, isAdult }), // TypeScript infers return type as { name: string; age: number; isAdult: boolean } }, ]; const onReturn: OnReturn = (values) => { // values: { name: string; age: number; isAdult: boolean } console.log(values); // { name: "Alice", age: 28, isAdult: true } }; ``` -------------------------------- ### `setState` — restore a previously saved state Source: https://context7.com/martiserra99/formity/llms.txt Restores a previously saved form session using a `State` object, allowing users to resume exactly where they left off. ```APIDOC ## `setState` — restore a previously saved state ### Description Restores a previously saved form session using a `State` object, allowing users to resume exactly where they left off. ### Usage ```tsx // Restore a saved form session import { useFormity, State } from "@formity/react"; const saved: State = JSON.parse(localStorage.getItem("state") ?? "null"); useFormity({ flow, initialState: saved, // resumes exactly where the user left off onReturn, }); ``` ``` -------------------------------- ### Declare a Jump Target in Formity Source: https://context7.com/martiserra99/formity/llms.txt Use the `jump` element to declare a labelled form step that can be reached from any other step using `onJump(id, fields)`. This enables non-linear navigation, such as editing a previous answer. ```tsx import type { Flow, s } from "@formity/react"; type Schema = { render: React.ReactNode; struct: [ s.Form<{ name: string }>, s.Jump>, s.Return<{ name: string }>; ]; inputs: Record; params: Record; }; const flow: Flow = [ { form: { fields: () => ({ name: ["", []] }), render: ({ fields, onNext }) => (
), }, }, { jump: { id: "edit-name", // unique identifier for this jump target at: { form: { fields: () => ({ name: ["", []] }), render: ({ fields, onNext, onBack }) => (
), }, }, }, }, { return: ({ name }) => ({ name }) }, ]; // In a summary step, trigger the jump: // onJump("edit-name", currentFields) ``` -------------------------------- ### Construct flow elements with `f.*` Source: https://context7.com/martiserra99/formity/llms.txt The `f` namespace mirrors `s.*` but is used for constructing `Flow` array values directly. This is less common as flow arrays are typically inferred from their structure. ```typescript import type { f } from "@formity/react"; // f.Form // f.Variables // f.Condition<{then, else}> // f.Loop // f.Switch<{branches, default}> // f.Jump // f.Yield<{next, back}> // f.Return ``` -------------------------------- ### Configure ESLint for Type-Aware Linting Source: https://github.com/martiserra99/formity/blob/main/apps/react/README.md Update the top-level parserOptions property in your ESLint configuration to enable type-aware lint rules. Ensure tsconfig files are correctly specified. ```javascript export default tseslint.config({ languageOptions: { // other options... parserOptions: { project: ['./tsconfig.node.json', './tsconfig.app.json'], tsconfigRootDir: import.meta.dirname, }, }, }) ``` -------------------------------- ### Condition Component for Flow Branching Source: https://context7.com/martiserra99/formity/llms.txt Use the `condition` component to branch the flow based on a predicate. It routes to `then` or `else` branches depending on the evaluation of accumulated values. ```tsx import type { Flow, s } from "@formity/react"; type Schema = { render: React.ReactNode; struct: [ s.Form<{ isPro: boolean }>, s.Condition<{ then: [s.Form<{ proFeature: string }>, s.Return<{ isPro: true; proFeature: string }>]; else: [ s.Return<{ isPro: false }>]; }>, ]; inputs: Record; params: Record; }; const flow: Flow = [ { form: { fields: () => ({ isPro: [false, []] }), render: ({ fields, onNext }) => (
), }, }, { condition: { if: ({ isPro }) => isPro, then: [ { form: { fields: () => ({ proFeature: ["", []] }), render: ({ fields, onNext }) => (
), }, }, { return: ({ isPro, proFeature }) => ({ isPro: true, proFeature }) }, ], else: [ { return: ({ isPro }) => ({ isPro: false }) }, ], }, }, ]; ``` -------------------------------- ### Emit Intermediate Data with Yield in Formity Source: https://context7.com/martiserra99/formity/llms.txt The `yield` element emits data on forward (`next`) or backward (`back`) navigation without leaving the flow. This is useful for syncing partial form state to external storage, such as for analytics or save-and-resume functionality. ```tsx import type { Flow, s, OnYield } from "@formity/react"; type Schema = { render: React.ReactNode; struct: [ s.Form<{ email: string }>; s.Yield<{ next: [{ type: "next"; data: { email: string } }]; back: [{ type: "back"; data: { email: string } }]; }>; s.Form<{ plan: string }>; s.Return<{ email: string; plan: string }>; ]; inputs: Record; params: Record; }; const flow: Flow = [ { form: { fields: () => ({ email: ["", []] }), render: ({ fields, onNext }) => (
), }, }, { yield: { next: ({ email }) => [{ type: "next", data: { email } }], back: ({ email }) => [{ type: "back", data: { email } }], }, }, { form: { fields: () => ({ plan: ["free", []] }), render: ({ fields, onNext, onBack }) => (
), }, }, { return: ({ email, plan }) => ({ email, plan }) }, ]; // onYield is called each time the flow passes through a yield element const onYield: OnYield = (value) => { // value: { type: "next"; data: { email: string } } // | { type: "back"; data: { email: string } } console.log("Yielded:", value); // e.g. save to localStorage for resume support localStorage.setItem("formProgress", JSON.stringify(value)); }; ``` -------------------------------- ### Variables Component for Data Computation Source: https://context7.com/martiserra99/formity/llms.txt The `variables` component allows you to compute and inject new values into the flow based on accumulated data. The returned object is merged with the current values. ```tsx import type { Flow, s } from "@formity/react"; type Schema = { render: React.ReactNode; struct: [ s.Form<{ firstName: string; lastName: string }>, s.Variables<{ fullName: string; initials: string }>, s.Return<{ fullName: string; initials: string }>, ]; inputs: Record; params: Record; }; const flow: Flow = [ { form: { fields: () => ({ firstName: ["", []], lastName: ["", []] }), render: ({ fields, onNext }) => (
{ e.preventDefault(); onNext({ firstName: "John", lastName: "Doe" }); }}>
), }, }, { // Receives all accumulated values; returned object is merged into values variables: ({ firstName, lastName }) => ({ fullName: `${firstName} ${lastName}`, initials: `${firstName[0]}.${lastName[0]}.`, }), }, { return: ({ fullName, initials }) => ({ fullName, initials }), // => { fullName: "John Doe", initials: "J.D." } }, ]; ``` -------------------------------- ### Formity Integration with React Hook Form Source: https://context7.com/martiserra99/formity/llms.txt Integrates Formity with React Hook Form by wiring Formity's 'onNext' and 'onBack' callbacks to RHF's 'handleSubmit'. This allows leveraging RHF's validation and state management. ```tsx import { useFormity, Flow, s } from "@formity/react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; type Schema = { render: React.ReactNode; struct: [ s.Form<{ email: string; password: string }>, s.Return<{ email: string; password: string }>, ]; inputs: Record; params: Record; }; function EmailStep({ fields, onNext, onBack, }: { fields: { email: string; password: string }; onNext: (v: { email: string; password: string }) => void; onBack: (v: { email: string; password: string }) => void; }) { const { register, handleSubmit, formState: { errors } } = useForm({ defaultValues: fields, resolver: zodResolver( z.object({ email: z.string().email(), password: z.string().min(8), }), ), }); return (
{errors.email &&

{errors.email.message}

} {errors.password &&

{errors.password.message}

}
); } const flow: Flow = [ { form: { fields: () => ({ email: ["", []], password: ["", []] }), render: (props) => , }, }, { return: ({ email, password }) => ({ email, password }) }, ]; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.