feat: remove getInputProps to support React Native

This commit is contained in:
Corbin Crutchley
2023-09-03 01:34:25 -07:00
committed by Corbin Crutchley
parent 2a31bd8219
commit 7980336d03
6 changed files with 54 additions and 84 deletions

View File

@@ -5,8 +5,6 @@ title: Field API
### Creating a new FieldApi Instance
Normally, you will not need to create a new `FieldApi` instance directly. Instead, you will use a framework hook/function like `useField` or `createField` to create a new instance for you that utilizes your frameworks reactivity model. However, if you need to create a new instance manually, you can do so by calling the `new FieldApi` constructor.
```tsx
@@ -28,55 +26,58 @@ An object type representing the options for a field in a form.
- ```tsx
defaultMeta?: Partial<FieldMeta>
```
- An optional object with default metadata for the field.
- ```tsx
onMount?: (formApi: FieldApi<TData, TFormData>) => void
```
- An optional function that takes a param of `formApi` which is a generic type of `TData` and `TFormData`
- ```tsx
onChange?: ValidateFn<TData, TFormData>
```
- An optional property that takes a `ValidateFn` which is a generic of `TData` and `TFormData`
- ```tsx
onChangeAsync?: ValidateAsyncFn<TData, TFormData>
```
- An optional property similar to `onChange` but async validation
- An optional property similar to `onChange` but async validation
- ```tsx
onChangeAsyncDebounceMs?: number
```
- An optional number to represent how long the `onChangeAsync` should wait before running
- An optional number to represent how long the `onChangeAsync` should wait before running
- If set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds
- ```tsx
onBlur?: ValidateFn<TData, TFormData>
```
- An optional function, when that run when subscribing to blur event of input
- ```tsx
onBlurAsync?: ValidateAsyncFn<TData, TFormData>
```
- An optional function that takes a `ValidateFn` which is a generic of `TData` and `TFormData` happens async
```tsx
onBlurAsyncDebounceMs?: number
```
- An optional number to represent how long the `onBlurAsyncDebounceMs` should wait before running
- If set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds
- An optional number to represent how long the `onBlurAsyncDebounceMs` should wait before running
- If set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds
```tsx
onSubmitAsync?: number
```
- If set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds
- If set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds
### `ValidationCause`
@@ -205,13 +206,13 @@ A class representing the API for managing a form field.
```
- Validates the field value.
- ```tsx
getChangeProps<T extends UserChangeProps<any>>(props: T = {} as T): ChangeProps<TData> & Omit<T, keyof ChangeProps<TData>>
handleBlur(): void;
```
- Gets the change and blur event handlers.
- Handles the blur event.
- ```tsx
getInputProps<T extends UserInputProps>(props: T = {} as T): InputProps & Omit<T, keyof InputProps>
handleChange(value: TData): void
```
- Gets the input event handlers.
- Handles the change event.
### `FieldState<TData>`

View File

@@ -57,28 +57,6 @@ export type FieldMeta = {
isValidating: boolean
}
export type UserChangeProps<TData> = {
onChange?: (updater: Updater<TData>) => void
onBlur?: (event: any) => void
}
export type UserInputProps = {
onChange?: (event: any) => void
onBlur?: (event: any) => void
}
export type ChangeProps<TData> = {
value: TData
onChange: (value: TData) => void
onBlur: (event: any) => void
}
export type InputProps<T> = {
value: T
onChange: (event: any) => void
onBlur: (event: any) => void
}
let uid = 0
export type FieldState<TData> = {
@@ -409,43 +387,17 @@ export class FieldApi<TData, TFormData> {
return this.validateAsync(value, cause)
}
getChangeProps = <T extends UserChangeProps<any>>(
props: T = {} as T,
): ChangeProps<typeof this._tdata> &
Omit<T, keyof ChangeProps<typeof this._tdata>> => {
return {
...props,
value: this.state.value,
onChange: (value) => {
this.setValue(value as never)
props.onChange?.(value)
},
onBlur: (e) => {
const prevTouched = this.state.meta.isTouched
this.setMeta((prev) => ({ ...prev, isTouched: true }))
if (!prevTouched) {
this.validate('change')
}
this.validate('blur')
},
} as ChangeProps<typeof this._tdata> &
Omit<T, keyof ChangeProps<typeof this._tdata>>
handleChange = (updater: Updater<typeof this._tdata>) => {
this.setValue(updater, { touch: true })
}
getInputProps = <T extends UserInputProps>(
props: T = {} as T,
): InputProps<typeof this._tdata> &
Omit<T, keyof InputProps<typeof this._tdata>> => {
return {
...props,
value: this.state.value,
onChange: (e) => {
this.setValue(e.target.value)
props.onChange?.(e.target.value)
},
onBlur: this.getChangeProps(props).onBlur,
} as InputProps<typeof this._tdata> &
Omit<T, keyof InputProps<typeof this._tdata>>
handleBlur = () => {
const prevTouched = this.state.meta.isTouched
if (!prevTouched) {
this.setMeta((prev) => ({ ...prev, isTouched: true }))
this.validate('change')
}
this.validate('blur')
}
}

View File

@@ -1,5 +1,4 @@
export type {
ChangeProps,
DeepKeys,
DeepValue,
FieldApiOptions,
@@ -9,12 +8,9 @@ export type {
FieldState,
FormOptions,
FormState,
InputProps,
RequiredByKey,
Updater,
UpdaterFn,
UserChangeProps,
UserInputProps,
ValidationCause,
ValidationError,
ValidationMeta,

View File

@@ -1,3 +1,4 @@
/// <reference lib="dom" />
import { render } from '@testing-library/react'
import '@testing-library/jest-dom'
import * as React from 'react'
@@ -25,7 +26,7 @@ describe('createFormFactory', () => {
<form.Field
name="firstName"
children={(field) => {
return <p>{field.getInputProps().value}</p>
return <p>{field.state.value}</p>
}}
/>
</form.Provider>

View File

@@ -1,3 +1,4 @@
/// <reference lib="dom" />
import * as React from 'react'
import { render, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
@@ -26,7 +27,12 @@ describe('useField', () => {
defaultValue="FirstName"
children={(field) => {
return (
<input data-testid="fieldinput" {...field.getInputProps()} />
<input
data-testid="fieldinput"
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
)
}}
/>
@@ -61,7 +67,9 @@ describe('useField', () => {
<input
data-testid="fieldinput"
name={field.name}
{...field.getInputProps()}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.setValue(e.target.value)}
/>
<p>{field.getMeta().error}</p>
</div>
@@ -100,7 +108,9 @@ describe('useField', () => {
<input
data-testid="fieldinput"
name={field.name}
{...field.getInputProps()}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
<p>{field.getMeta().error}</p>
</div>
@@ -143,7 +153,9 @@ describe('useField', () => {
<input
data-testid="fieldinput"
name={field.name}
{...field.getInputProps()}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
<p>{field.getMeta().error}</p>
</div>
@@ -189,7 +201,9 @@ describe('useField', () => {
<input
data-testid="fieldinput"
name={field.name}
{...field.getInputProps()}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
<p>{field.getMeta().error}</p>
</div>

View File

@@ -1,3 +1,4 @@
/// <reference lib="dom" />
import { render } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import '@testing-library/jest-dom'
@@ -25,7 +26,12 @@ describe('useForm', () => {
defaultValue={''}
children={(field) => {
return (
<input data-testid="fieldinput" {...field.getInputProps()} />
<input
data-testid="fieldinput"
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
)
}}
/>
@@ -61,7 +67,7 @@ describe('useForm', () => {
<form.Field
name="firstName"
children={(field) => {
return <p>{field.getInputProps().value}</p>
return <p>{field.state.value}</p>
}}
/>
</form.Provider>