From 9a98b0e5d218ce447e29be65bbcbdf483cf18570 Mon Sep 17 00:00:00 2001 From: Martin Turoci Date: Wed, 16 Aug 2023 09:13:39 +0200 Subject: [PATCH] fix: Prevent memory leak. --- ui/src/nav.test.tsx | 12 +++++------ ui/src/nav.tsx | 49 +++++++++++++++++++++++---------------------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/ui/src/nav.test.tsx b/ui/src/nav.test.tsx index 867abdf249..17375e1294 100644 --- a/ui/src/nav.test.tsx +++ b/ui/src/nav.test.tsx @@ -168,31 +168,31 @@ describe('Nav.tsx', () => { it('Selects nav item when value is updated to the same value twice', () => { const props: T.Model = { ...navProps, state: { items } }, - checkIfFirstItemIsSelected = () => { + expectFirstSelected = () => { expect(getByTitle('Nav 1').parentElement).toHaveClass('is-selected') expect(getByTitle('Nav 2').parentElement).not.toHaveClass('is-selected') }, - checkIfSecondItemIsSelected = () => { + expectSecondSelected = () => { expect(getByTitle('Nav 1').parentElement).not.toHaveClass('is-selected') expect(getByTitle('Nav 2').parentElement).toHaveClass('is-selected') }, { rerender, getByTitle } = render() - checkIfFirstItemIsSelected() + expectFirstSelected() props.state.value = 'nav2' rerender() expect(wave.args['nav2']).toBe(true) - checkIfSecondItemIsSelected() + expectSecondSelected() fireEvent.click(getByTitle('Nav 1')) expect(wave.args['nav1']).toBe(true) - checkIfFirstItemIsSelected() + expectFirstSelected() props.state.value = 'nav2' rerender() expect(wave.args['nav2']).toBe(true) - checkIfSecondItemIsSelected() + expectSecondSelected() }) it('Does not set args on value update when name starts with hash', () => { diff --git a/ui/src/nav.tsx b/ui/src/nav.tsx index 3ebb7bcc6d..3b69ddcc5d 100644 --- a/ui/src/nav.tsx +++ b/ui/src/nav.tsx @@ -147,26 +147,28 @@ export const return }, View = bond(({ name, state, changed }: Model) => { - const valueB = box(state.value) - const render = () => { - const { title, subtitle, icon, color = 'card', icon_color = color === 'primary' ? '$card' : '$text', image, persona, secondary_items } = state - return ( -
-
- {(image || icon) && ( -
- {image && } - {icon && !image && } -
- )} - {title &&
{title}
} - {subtitle &&
{subtitle}
} - {!image && !icon && persona?.persona &&
} -
- - {secondary_items &&
} -
) - }, + const + valueB = box(state.value), + valueWatcher = on(valueB, val => state.value = val), + render = () => { + const { title, subtitle, icon, color = 'card', icon_color = color === 'primary' ? '$card' : '$text', image, persona, secondary_items } = state + return ( +
+
+ {(image || icon) && ( +
+ {image && } + {icon && !image && } +
+ )} + {title &&
{title}
} + {subtitle &&
{subtitle}
} + {!image && !icon && persona?.persona &&
} +
+ + {secondary_items &&
} +
) + }, update = (prevProps: Model) => { if (prevProps.state.value === valueB()) return valueB(prevProps.state.value) @@ -174,11 +176,10 @@ export const if (name.startsWith('#')) window.location.hash = name.substring(1) else wave.args[name] = true - } - - on(valueB, val => state.value = val) + }, + dispose = () => valueWatcher.dispose() - return { render, changed, update, valueB } + return { render, changed, update, valueB, dispose } }) cards.register('nav', View, { effect: CardEffect.Flat, marginless: true }) \ No newline at end of file