My learning diary

useContext, useForm, and useFieldArray

I’m fortunate to have the opportunity to work with react-hook-form again. And work with it better. The following worked well for me:

// MultiStepForm.tsx

import { createContext, Dispatch, SetStateAction } from 'react'
import {
} from 'react-hook-form'

interface SomeComplexInput {
    someKey: string
    someValue: string

interface MultiStepFormInput {
    formFieldA: string
    formFieldB: SomeComplexInput[]

interface OtherContext {
    // Other frontend-specific values e.g. active form step index

export const MultiStepFormContext = createContext(
  {} as UseFormReturn<MultiStepFormInput> &
    UseFieldArrayReturn<MultiStepFormInput, 'formFieldB', 'id'> &

export const MultiStepForm = () => {
    const form = useForm<MultiStepFormInput>({
        mode: 'all',
    // Use fieldArray.replace and the like to change form fields on the fly
    const fieldArray = useFieldArray<MultiStepFormInput>({
        control: form.control,
        name: 'formFieldB',

    const onSubmit: SubmitHandler<MultiStepFormInput> = (data: MultiStepFormInput) => {
        // Send data to your server

    return (
        <form onSubmit={form.handleSubmit(onSubmit)}>
                    // values from OtherContext
                <SubsetOfFormFields />
// SubsetOfFormFields.tsx

import { Input } from '@chakra-ui/react'

import { useContext } from 'react'

import { MultiStepFormContext } from './MultiStepForm'

export const SubsetOfFormFields = () => {
    const { fields, register } = useContext(MultiStepFormContext)

    // Inside map, field has access to both someKey and someValue
    return, index) => (

Although SubsetOfFormFields is a direct child of MultiStepForm, I pass information via context. Any other child component won’t have to define extensive prop interfaces. They can call useContext.

This decision doesn’t suggest we should always opt for context. I use context when sharing information between stateful components. As for presentational ones, I pass information to them via props. I see SubsetOfFormFields as a stateful component. I see presentational components as pure functions that don’t mutate any state outside of itself.

For the sharp-eyed, you might’ve seen useFormContext and FormProvider in react-hook-form’s docs. Well, I forgot about it. If time and mood permit, I’ll investigate if I can add values from OtherContext into FormProvider. With type safety.


Relevant posts