Skip to content

Commit ea0c9c6

Browse files
committed
feat: update formValidation setValue to be optional across components
1 parent 6080d54 commit ea0c9c6

7 files changed

Lines changed: 26 additions & 29 deletions

File tree

src/components/editor/Editor.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ export const Editor: React.FC<EditorProps> = (props) => {
492492
try {
493493
const json = JSON.parse(val)
494494
onChange?.(json)
495-
formValidation?.setValue(json)
495+
formValidation?.setValue?.(json)
496496
} catch (e) {
497497
}
498498
} else {

src/components/form/CheckboxInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export const CheckboxInput: React.FC<CheckboxInputProps> = (props) => {
2828
const [checked, setChecked] = React.useState<CheckedState>(props.initialValue ?? "indeterminate");
2929

3030
React.useEffect(() => {
31-
formValidation.setValue(checked)
31+
formValidation.setValue?.(checked)
3232
}, [checked])
3333

3434
return <>

src/components/form/EditorInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export const EditorInput: React.FC<EditorInputProps> = (props) => {
6363
formValidation={formValidation}>
6464

6565
<CodeMirror extensions={internalExtensions} onChange={value => {
66-
formValidation?.setValue(value)
66+
formValidation?.setValue?.(value)
6767
onChange?.(value)
6868
}} theme={myTheme} {...mergeComponentProps("editor-input", rest)} basicSetup={{
6969
lineNumbers: false,

src/components/form/PinInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export const PinInput: React.FC<PinInputProps> = (props) => {
4343
<OneTimePasswordField {...mergeComponentProps("pin-input", {
4444
...rest, onValueChange: (value: string) => {
4545
if (rest.onValueChange) rest.onValueChange!!(value)
46-
formValidation.setValue(value)
46+
formValidation.setValue?.(value)
4747
}
4848
})}/>
4949
</div>

src/components/form/RadioGroup.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export const RadioGroup: React.FC<RadioGroupProps> = (props) => {
3535
defaultValue={initialValue ?? props.defaultValue} {...mergeComponentProps("radio-group", {
3636
...rest, onValueChange: (value: string) => {
3737
if (rest.onValueChange) rest.onValueChange!!(value)
38-
formValidation.setValue(value)
38+
formValidation.setValue?.(value)
3939
}
4040
})}/>
4141

src/components/form/SelectInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export const SelectInput: React.FC<SelectProps> = (props) => {
2929
formValidation={formValidation}>
3030
<RadixSelect.Root {...mergeComponentProps("select-input", {
3131
...rest, onValueChange: (value: string) => {
32-
formValidation?.setValue(value)
32+
formValidation?.setValue?.(value)
3333
rest.onValueChange?.(value)
3434
}
3535
}) as SelectProps}/>

src/components/form/useForm.ts

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client"
22

3-
import {useCallback, useEffect, useRef, useState} from "react";
3+
import React, {useCallback, useEffect, useRef, useState} from "react";
44

55
export type Validations<Values> = Partial<{
66
[Key in keyof Values]: (value: Values[Key], values?: Values) => string | null;
@@ -20,7 +20,7 @@ export interface ValidationProps<Value> {
2020
value?: Value | undefined
2121
required?: boolean
2222
formValidation?: {
23-
setValue: (value: any) => void
23+
setValue?: (value: any) => void
2424
valid?: boolean
2525
notValidMessage?: string | null
2626
}
@@ -30,11 +30,10 @@ export type ValidationsProps<Values> = Partial<{
3030
[Key in keyof Values]: ValidationProps<Values[Key]>
3131
}>
3232

33-
export type FormValidationReturn<Values> = [IValidation<Values>, <Key extends keyof Values>(key?: Key | any) => void]
33+
export type FormValidationReturn<Values> = [IValidation<Values>, <Key extends keyof Values>(key?: Key | any, submit?: boolean) => void, Values]
3434

3535
export interface IValidation<Values> {
3636
getInputProps<Key extends keyof Values>(key: Key): ValidationProps<Values[Key]>
37-
3837
isValid(): boolean
3938
}
4039

@@ -127,64 +126,62 @@ export const useForm = <
127126
onSubmit
128127
} = props
129128

130-
const [values, setValues] = useState<Values>(initialValues)
131-
const valuesRef = useRef<Values>(initialValues)
129+
const initValues = React.useMemo(() => initialValues as Values, [])
130+
const [values, setValues] = useState<Values>(initValues)
132131
const cachedMessagesRef = useRef<Map<keyof Values, string | null>>(new Map())
133132

134133
const changeValue = useCallback((key: keyof Values, value: any) => {
135134
setValues(prevState => {
136-
const nextState = {
135+
return {
137136
...prevState,
138137
[key]: value,
139138
}
140-
valuesRef.current = nextState
141-
return nextState
142139
})
143140
}, [])
144141

145142
const [validation, setValidation] = useState<Validation<Values>>(new Validation<Values>(
146143
changeValue,
147144
values,
148145
validate,
149-
useInitialValidation ? new Map<keyof Values, boolean>(Object.keys(initialValues).map(k => [k as keyof Values, true])) : new Map<keyof Values, boolean>(),
146+
useInitialValidation ? new Map<keyof Values, boolean>(Object.keys(initValues).map(k => [k as keyof Values, true])) : new Map<keyof Values, boolean>(),
150147
cachedMessagesRef.current
151148
))
152149

153150
useEffect(() => {
154-
setValues(initialValues)
155-
valuesRef.current = initialValues
151+
setValues(initValues)
156152
setValidation(new Validation<Values>(
157153
changeValue,
158-
initialValues,
154+
initValues,
159155
validate,
160-
useInitialValidation ? new Map<keyof Values, boolean>(Object.keys(initialValues).map(k => [k as keyof Values, true])) : new Map<keyof Values, boolean>(),
156+
useInitialValidation ? new Map<keyof Values, boolean>(Object.keys(initValues).map(k => [k as keyof Values, true])) : new Map<keyof Values, boolean>(),
161157
cachedMessagesRef.current
162158
))
163-
}, [initialValues])
159+
}, [initValues])
164160

165-
const validateFunction = useCallback(<Key extends keyof Values>(key?: Key) => {
161+
const validateFunction = useCallback(<Key extends keyof Values>(key?: Key, submit = true) => {
166162

167-
const shouldValidateMap = key && new Set(Object.keys(initialValues)).has(String(key))
163+
const shouldValidateMap = key && new Set(Object.keys(values)).has(String(key))
168164
? new Map<keyof Values, boolean>([[key, true]])
169-
: new Map<keyof Values, boolean>(Object.keys(initialValues).map(k => [String(k) as keyof Values, true]))
165+
: new Map<keyof Values, boolean>(Object.keys(values).map(k => [String(k) as keyof Values, true]))
170166

171167
const currentValidation = new Validation<Values>(
172168
changeValue,
173-
valuesRef.current,
169+
values,
174170
validate,
175171
shouldValidateMap,
176172
cachedMessagesRef.current
177173
)
178174

179175
setValidation(currentValidation)
180176

181-
if (!new Set(Object.keys(initialValues)).has(String(key)) && onSubmit && (!truthyValidationBeforeSubmit || currentValidation.isValid())) {
182-
onSubmit(valuesRef.current as Values)
177+
if (submit && !new Set(Object.keys(values)).has(String(key)) && onSubmit && (!truthyValidationBeforeSubmit || currentValidation.isValid())) {
178+
onSubmit(values as Values)
183179
}
184-
}, [changeValue, validate, onSubmit, truthyValidationBeforeSubmit, initialValues])
180+
}, [changeValue, validate, onSubmit, truthyValidationBeforeSubmit, values])
185181

186182
return [
187183
validation,
188-
validateFunction
184+
validateFunction,
185+
values
189186
]
190187
}

0 commit comments

Comments
 (0)