diff --git a/src/component/sugar/array.ts b/src/component/sugar/array.ts index 9f2d8f7..50cae2f 100644 --- a/src/component/sugar/array.ts +++ b/src/component/sugar/array.ts @@ -11,6 +11,7 @@ export function useArray( ): SugarArrayNode { const newId = useCountingId(); const mountedRef = useRef(false); + const keysRef = useRef([]); const managedSugars = useRef }>>([]); let defaultKeys: string[] = []; @@ -22,7 +23,7 @@ export function useArray( const newSugar = createEmptySugar(sugar.path, template); managedSugars.current.push({ id, sugar: newSugar }); newSugar.upstream.listen('updateDirty', ({ isDirty }) => { - if (!keys.includes(id)) return; + if (!keysRef.current.includes(id)) return; dirtyControl({ isDirty }); }); return newSugar; @@ -34,8 +35,8 @@ export function useArray( sugar.asMounted(sugar => { notDirtyCheck: if (!isDirty) { - if (keys.length !== sugar.template.length) break notDirtyCheck; - if (keys.some(i => { + if (keysRef.current.length !== sugar.template.length) break notDirtyCheck; + if (keysRef.current.some(i => { const managed = getManagedSugar(i); return managed.mounted && managed.isDirty; })) return; @@ -43,6 +44,7 @@ export function useArray( setDirty(sugar, isDirty); }); }; + if (!mountedRef.current && sugar.mounted) { debug('WARN', `Sugar is already mounted, but items are not initialized. Remounting... Path: ${sugar.path}`); mountedRef.current = false; @@ -65,6 +67,7 @@ export function useArray( } const [ keys, setKeys ] = useState(defaultKeys); + keysRef.current = keys; const mountedSugar = sugar as Sugar & { mounted: true }; mountedSugar.get = (): SugarValue => { @@ -86,8 +89,8 @@ export function useArray( const keys = value.map((v, i) => { const id = newId(); const managed = getManagedSugar(id, sugar.template[i] ?? options.template); - managed.upstream.listenOnce('mounted', () => { - ( managed as Sugar & { mounted: true } ).set(v); + managed.asMounted(s => { + setTimeout(() => s.set(v)); }); return id; }); @@ -95,16 +98,27 @@ export function useArray( }; mountedSugar.setTemplate = (template: T[], mode: SetTemplateMode = 'merge'): void => { sugar.template = template; - keys.forEach((id, i) => { - const managed = getManagedSugar(id); - if (!managed.mounted) { - debug('WARN', `Sugar is not mounted when tried to set. Path: ${managed.path}`); - return; - } - managed.setTemplate(template[i] ?? options.template, mode); + const keys = template.map(v => { + const id = newId(); + getManagedSugar(id, options.template).asMounted(s => s.setTemplate(v, mode)); + return id; }); + setKeys(keys); }; + // refresh dirty for new items or removed items + setDirty( + sugar, + ((): boolean => { + if (keysRef.current.length !== sugar.template.length) return true; + if (keysRef.current.some(i => { + const managed = getManagedSugar(i); + return managed.mounted && managed.isDirty; + })) return true; + return false; + })(), + ); + return { useNewId: () => newId(), useKeys: () => [ keys, (keys: string[]):void => setKeys(keys) ],