From e0d31a21016f9043a69de8dc8716b772501e741e Mon Sep 17 00:00:00 2001 From: Yoann Fleury Date: Thu, 12 Sep 2024 14:10:50 +0200 Subject: [PATCH] feat: add watch to trigger hook --- src/lib/form/useWatchToTrigger.ts | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/lib/form/useWatchToTrigger.ts diff --git a/src/lib/form/useWatchToTrigger.ts b/src/lib/form/useWatchToTrigger.ts new file mode 100644 index 000000000..58f72bbfb --- /dev/null +++ b/src/lib/form/useWatchToTrigger.ts @@ -0,0 +1,37 @@ +import { useEffect } from 'react'; + +import { FieldPath, FieldValues, UseFormReturn } from 'react-hook-form'; + +/** + * Use this hook to subscribe to fields and listen for changes to revalidate the + * form. + * + * Using the form "onBlur" validation will validate the field you just updated. + * But imagine a field that has to validate itself based on an another field update. + * That's the point of this hook. + * + * Example: imagine those fields: `min`, `default`, `max`. The `min` should be + * lower than the `default` and the `default` should lower than the `max`. + * `min` is equal to 2, `default` is equal to 4 and `max` is equal to 6. + * You update the `min` so the value is 5, the form (using superRefine and + * custom issues) will tell you that the `min` should be lower than the default. + * You update the `default` so the new value is 5.5. Without this hook, the + * field `min` will not revalidate. With this hook, if you gave the name, it will. + */ +export const useWatchToTrigger = < + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath, +>(params: { + form: Pick, 'watch' | 'trigger'>; + names: Array; +}) => { + const { watch, trigger } = params.form; + useEffect(() => { + const subscription = watch((_, { name }) => { + if (name && params.names.includes(name as TName)) { + trigger(params.names); + } + }); + return () => subscription.unsubscribe(); + }, [watch, trigger, params.names]); +};