99 Ref ,
1010 ComponentInternalInstance ,
1111 onBeforeUnmount ,
12- nextTick ,
13- WatchStopHandle ,
12+ warn ,
1413} from 'vue' ;
1514import { klona as deepCopy } from 'klona/full' ;
1615import { validate as validateValue } from './validate' ;
@@ -220,7 +219,7 @@ function _useField<TValue = unknown>(
220219 function handleChange ( e : unknown , shouldValidate = true ) {
221220 const newValue = normalizeEventValue ( e ) as TValue ;
222221
223- value . value = newValue ;
222+ setValue ( newValue , false ) ;
224223 if ( ! validateOnValueUpdate && shouldValidate ) {
225224 validateWithStateMutation ( ) ;
226225 }
@@ -243,35 +242,7 @@ function _useField<TValue = unknown>(
243242 meta . touched = isTouched ;
244243 }
245244
246- let unwatchValue : WatchStopHandle ;
247- let lastWatchedValue = deepCopy ( value . value ) ;
248- function watchValue ( ) {
249- unwatchValue = watch (
250- value ,
251- ( val , oldVal ) => {
252- if ( form ?. isResetting . value ) {
253- return ;
254- }
255-
256- if ( isEqual ( val , oldVal ) && isEqual ( val , lastWatchedValue ) ) {
257- return ;
258- }
259-
260- const validateFn = validateOnValueUpdate ? validateWithStateMutation : validateValidStateOnly ;
261- validateFn ( ) ;
262- lastWatchedValue = deepCopy ( val ) ;
263- } ,
264- {
265- deep : true ,
266- }
267- ) ;
268- }
269-
270- watchValue ( ) ;
271-
272245 function resetField ( state ?: Partial < FieldState < TValue > > ) {
273- unwatchValue ?.( ) ;
274-
275246 const newValue = state && 'value' in state ? ( state . value as TValue ) : initialValue . value ;
276247
277248 setState ( {
@@ -284,26 +255,50 @@ function _useField<TValue = unknown>(
284255 meta . pending = false ;
285256 meta . validated = false ;
286257 validateValidStateOnly ( ) ;
287-
288- // need to watch at next tick to avoid triggering the value watcher
289- nextTick ( ( ) => {
290- watchValue ( ) ;
291- } ) ;
292258 }
293259
294- function setValue ( newValue : TValue ) {
260+ function setValue ( newValue : TValue , validate = true ) {
295261 value . value = newValue ;
262+ if ( ! validate ) {
263+ return ;
264+ }
265+
266+ const validateFn = validateOnValueUpdate ? validateWithStateMutation : validateValidStateOnly ;
267+ validateFn ( ) ;
296268 }
297269
298270 function setErrors ( errors : string [ ] | string ) {
299271 setState ( { errors : Array . isArray ( errors ) ? errors : [ errors ] } ) ;
300272 }
301273
274+ const valueProxy = computed ( {
275+ get ( ) {
276+ return value . value ;
277+ } ,
278+ set ( newValue : TValue ) {
279+ setValue ( newValue , validateOnValueUpdate ) ;
280+ } ,
281+ } ) ;
282+
283+ if ( __DEV__ ) {
284+ watch (
285+ valueProxy ,
286+ ( value , oldValue ) => {
287+ if ( value === oldValue && isEqual ( value , oldValue ) ) {
288+ warn (
289+ 'Detected a possible deep change on field `value` ref, for nested changes please either set the entire ref value or use `setValue` or `handleChange`.'
290+ ) ;
291+ }
292+ } ,
293+ { deep : true }
294+ ) ;
295+ }
296+
302297 const field : PrivateFieldContext < TValue > = {
303298 id,
304299 name,
305300 label,
306- value,
301+ value : valueProxy ,
307302 meta,
308303 errors,
309304 errorMessage,
0 commit comments