From 3ee35659cea374374e1672f8853ddbe9f6efcfd4 Mon Sep 17 00:00:00 2001 From: rlazarini <remi.lazarini@cea.fr> Date: Tue, 26 Mar 2024 10:48:46 +0100 Subject: [PATCH] [dome/forms] fix useForceUpdate() + commited state added to useBuffer() + status function added for fieldState --- ivette/src/dome/renderer/dome.tsx | 4 +- ivette/src/dome/renderer/layout/forms.tsx | 57 +++++++++++++++++++---- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/ivette/src/dome/renderer/dome.tsx b/ivette/src/dome/renderer/dome.tsx index a2922165005..4e3378c960a 100644 --- a/ivette/src/dome/renderer/dome.tsx +++ b/ivette/src/dome/renderer/dome.tsx @@ -562,8 +562,8 @@ export function popupMenu( Returns a callback to trigger a render on demand. */ export function useForceUpdate(): () => void { - const [tac, onTic] = React.useState(false); - return () => onTic(!tac); + const [, onTic] = React.useState(false); + return React.useCallback(() => onTic((tac) => !tac), []); } /** diff --git a/ivette/src/dome/renderer/layout/forms.tsx b/ivette/src/dome/renderer/layout/forms.tsx index 8a99feaabea..30ce592c92d 100644 --- a/ivette/src/dome/renderer/layout/forms.tsx +++ b/ivette/src/dome/renderer/layout/forms.tsx @@ -115,6 +115,33 @@ function isValidArray(err: FieldError[]): boolean { return true; } +/** + * A fieldState can be stable or unstable. + * + * A stable fieldState means that the value of the field valid + * and has no reset value. + * + * There are three cases of an unstable fieldState : + * - Error : There is an error in the field. + * - Resetable : The fieldState has a reset value. + * - Commitable : The fieldState has a reset value and is valid (!Error). + */ +export function isError<A>( state: FieldState<A> ): boolean { + return !isValid(state.error); +} + +export function isResetAble<A>( state: FieldState<A> ): boolean { + return state.reset !== undefined; +} + +export function isCommitAble<A>( state: FieldState<A> ): boolean { + return isResetAble(state) && !isError(state); +} + +export function isStable<A>( state: FieldState<A> ): boolean { + return !isResetAble(state) && !isError(state); +} + /* -------------------------------------------------------------------------- */ /* --- Buffer Controller --- */ /* -------------------------------------------------------------------------- */ @@ -241,11 +268,12 @@ export function useBuffer<A>( equal?: Equal<A>, ): FieldState<A> { const { value, error, reset, onChanged } = state; - const [modified, setModified] = React.useState(false); - const [buffer, setBuffer] = React.useState<A>(value); - const [berror, setBerror] = React.useState<FieldError>(error); + const [ modified, setModified ] = React.useState(false); + const [ commited, setCommited ] = React.useState(false); + const [ buffer, setBuffer ] = React.useState<A>(value); + const [ berror, setBerror ] = React.useState<FieldError>(error); - const valid = !isValid(berror); + const valid = isValid(berror); const rollback = reset ?? value; // --- Error Count @@ -255,6 +283,17 @@ export function useBuffer<A>( return () => remote.removeError(); }, [remote, valid]); + /* TODO : + * add a timeout to handle the case where the server takes + * this old value before the new value is returned to the field. + */ + React.useEffect(() => { + setCommited((val) => { + if(!val) setModified(false); + return true; + }); + }, [value]); + // --- Reset React.useEffect(() => { if (modified) { @@ -273,7 +312,7 @@ export function useBuffer<A>( if (modified) { const doCommit = (): void => { if (valid) { - setModified(false); + setCommited(false); onChanged(buffer, undefined, false); } else { setModified(false); @@ -292,13 +331,15 @@ export function useBuffer<A>( setModified(!isReset); setBuffer(newValue); setBerror(newError); - if (isReset && !compare(equal, newValue, value)) + if (isReset && !compare(equal, newValue, value)) { + setCommited(false); onChanged(newValue, newError, isReset); + } }, [equal, value, onChanged]); return { - value: modified ? buffer : value, - error: modified ? berror : error, + value: modified || !commited ? buffer : value, + error: modified || !commited ? berror : error, reset: reset ?? (modified ? value : undefined), onChanged: onLocalChange, }; -- GitLab