Skip to content

Commit

Permalink
fix(form-react): Make sure to only update form and field options with…
Browse files Browse the repository at this point in the history
…in a layout effect

This is used to prevent setting state during a React render
  • Loading branch information
gutentag2012 committed Apr 12, 2024
1 parent 453c898 commit e7ee994
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 18 deletions.
22 changes: 14 additions & 8 deletions packages/form-react/src/field/field.hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,26 @@ export function useField<
TMixin
>,
): FieldContextType<TData, TName, TBoundValue, TAdapter, TFormAdapter, TMixin> {
const field = form.getOrCreateField(name, options)
const finalField = React.useMemo(
() => fieldLogicToFieldContext(field),
[field],
// biome-ignore lint/correctness/useExhaustiveDependencies: We only ever want to create a field once, and we have to update the options in a layout effect to avoid setting state during render
const field = React.useMemo(
() => fieldLogicToFieldContext(form.getOrCreateField(name, options)),
[form, name],
)

useIsomorphicLayoutEffect(() => {
finalField.mount()
// That way we can make sure to not update the options for the first render
if (!field.isMounted.peek()) return
field.updateOptions(options)
}, [field, options])

useIsomorphicLayoutEffect(() => {
field.mount()
return () => {
finalField.unmount()
field.unmount()
}
}, [finalField])
}, [field])

return finalField
return field
}

/**
Expand Down
21 changes: 11 additions & 10 deletions packages/form-react/src/form/form.hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,23 @@ export function useForm<
>(
options?: FormLogicOptions<TData, TAdapter>,
): FormContextType<TData, TAdapter> {
// biome-ignore lint/correctness/useExhaustiveDependencies: We only ever want to create a form once
const finalForm = React.useMemo(() => {
const form = new FormLogic(options)
return formLogicToFormContext(form)
}, [])
// biome-ignore lint/correctness/useExhaustiveDependencies: We only ever want to create a form once, and we have to update the options in a layout effect to avoid setting state during render
const form = React.useMemo(() => formLogicToFormContext(new FormLogic(options)), [])

finalForm.updateOptions(options)
useIsomorphicLayoutEffect(() => {
// That way we can make sure to not update the options for the first render
if(!form.isMounted.peek()) return
form.updateOptions(options)
}, [form, options]);

useIsomorphicLayoutEffect(() => {
finalForm.mount()
form.mount()
return () => {
finalForm.unmount()
form.unmount()
}
}, [finalForm])
}, [form])

return finalForm
return form
}

/**
Expand Down

0 comments on commit e7ee994

Please # to comment.