What is the type of previousState when using React useState hook for a dynamic form?

Viewed 21

So I have Page which has a custom component called FormModal, which displays form fields based on props that are passed into it.

My code is as follows.

Page:

const prepareForm = (formArr: TFormField[]) => {
    return formArr.reduce((r, v) => ({ ...r, [v.name]: '' }), {})
}

const formArr: TFormField[] = [
    {
        label: 'Day name',
        name: 'name',
        type: 'text',
    },
    {
        label: 'Day date',
        name: 'date',
        type: 'date',
    },
]


const AddDayModal = (props: TModalProps) => {
    const [form, setForm] = useState(prepareForm(formArr))

    /* stuff */

    const formModalProps: TFormModalProps = {
        formArr,
        setForm,
    }

    return (
        <div>
            <FormModal {...formModalProps} />
        </div>
    )
}

FormModal:

type TFormField = {
    label: string
    name: string
    type: string
}

type TFormModalProps = {
    formArr: TFormField[]
    setForm: (prev) => void
}

const FormModal = (props: TFormModalProps) => {
    const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const { name, value, type } = e.target

        props.setForm((prev) => {
            if (type == 'date') {
                return { ...prev, [name]: new Date(value) }
            } else {
                return { ...prev, [name]: value }
            }
        })
    }

     return ( /* jsx */ )
}

Basically, in the Page I am creating a formArr which determines which fields the FormModal component should display ans pass that as props to the component.

However, in FormModal, I am not sure what the type of the prev in setForm is supposed to be and I get the following error:

enter image description here

Given my logic and the fact that the form is dynamic, what's the best way to determine what type it should be?

1 Answers

You can use type from definition of useState:

here is useState definition

function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];

You need second item from returning array for typing prev, here is Dispatch

type TFormModalProps = {
    formArr: TFormField[]
    setForm: Dispatch<SetStateAction<{}>> // should be you base type
                                          // for ex., `ReturnType<typeof prepareForm>`
                                          // or just `{}`
}

You need to import these types:

import type { Dispatch, SetStateAction } from "react"
Related