mirror of
https://github.com/LukeHagar/form.git
synced 2025-12-07 12:27:45 +00:00
fix: onSubmit should now behave as expected
* fix: memoize all non-function form props by default * chore: migrate useStableFormOpts to useMemo * fix: options passed to useField will not always cause a re-render * chore: minor code cleanups * test: add previously failing test to demonstrate fix * chore: fix linting * fix: running form.update repeatedly should not wipe form state * test: add test to validate formapi update behavior * test: add initial tests for useStableOptions * chore: remove useStableOpts and useFormCallback
This commit is contained in:
@@ -2,9 +2,10 @@ import type { FormState, FormOptions } from '@tanstack/form-core'
|
||||
import { FormApi, functionalUpdate } from '@tanstack/form-core'
|
||||
import type { NoInfer } from '@tanstack/react-store'
|
||||
import { useStore } from '@tanstack/react-store'
|
||||
import React from 'react'
|
||||
import React, { type ReactNode, useState } from 'react'
|
||||
import { type UseField, type FieldComponent, Field, useField } from './useField'
|
||||
import { formContext } from './formContext'
|
||||
import { useIsomorphicLayoutEffect } from './utils/useIsomorphicLayoutEffect'
|
||||
|
||||
declare module '@tanstack/form-core' {
|
||||
// eslint-disable-next-line no-shadow
|
||||
@@ -17,15 +18,13 @@ declare module '@tanstack/form-core' {
|
||||
) => TSelected
|
||||
Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
|
||||
selector?: (state: NoInfer<FormState<TFormData>>) => TSelected
|
||||
children:
|
||||
| ((state: NoInfer<TSelected>) => React.ReactNode)
|
||||
| React.ReactNode
|
||||
children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode
|
||||
}) => any
|
||||
}
|
||||
}
|
||||
|
||||
export function useForm<TData>(opts?: FormOptions<TData>): FormApi<TData> {
|
||||
const [formApi] = React.useState(() => {
|
||||
const [formApi] = useState(() => {
|
||||
// @ts-ignore
|
||||
const api = new FormApi<TData>(opts)
|
||||
|
||||
@@ -58,9 +57,13 @@ export function useForm<TData>(opts?: FormOptions<TData>): FormApi<TData> {
|
||||
|
||||
formApi.useStore((state) => state.isSubmitting)
|
||||
|
||||
React.useEffect(() => {
|
||||
/**
|
||||
* formApi.update should not have any side effects. Think of it like a `useRef`
|
||||
* that we need to keep updated every render with the most up-to-date information.
|
||||
*/
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
formApi.update(opts)
|
||||
}, [formApi, opts])
|
||||
})
|
||||
|
||||
return formApi as any
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user