taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 422aee9e959247af4df4938984a36e8ca2ad07eb
parent 4f1f0d96fc3ad5061b610c3075262b00332e1d0d
Author: Sebastian <sebasjm@gmail.com>
Date:   Mon, 20 Jan 2025 02:20:17 -0300

on component unload should be in web utils

Diffstat:
Mpackages/web-util/src/components/index.ts | 1+
Mpackages/web-util/src/components/utils.ts | 26+++++++++++++++++++++++---
2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/packages/web-util/src/components/index.ts b/packages/web-util/src/components/index.ts @@ -1,4 +1,5 @@ export * as utils from "./utils.js"; +export { onComponentUnload } from "./utils.js"; export * from "./Attention.js"; export * from "./CopyButton.js"; export * from "./ErrorLoading.js"; diff --git a/packages/web-util/src/components/utils.ts b/packages/web-util/src/components/utils.ts @@ -1,4 +1,5 @@ import { createElement, VNode } from "preact"; +import { useEffect, useRef } from "preact/hooks"; export type StateFunc<S> = (p: S) => VNode; @@ -12,7 +13,6 @@ export function compose<SType extends { status: string }, PType>( hook: (p: PType) => RecursiveState<SType>, viewMap: StateViewMap<SType>, ): (p: PType) => VNode { - function withHook(stateHook: () => RecursiveState<SType>): () => VNode { function ComposedComponent(): VNode { const state = stateHook(); @@ -39,7 +39,6 @@ export function compose<SType extends { status: string }, PType>( export function recursive<PType>( hook: (p: PType) => RecursiveState<VNode>, ): (p: PType) => VNode { - function withHook(stateHook: () => RecursiveState<VNode>): () => VNode { function ComposedComponent(): VNode { const state = stateHook(); @@ -61,7 +60,28 @@ export function recursive<PType>( }; } - +/** + * Call `callback` only once. + * + * Callback can be a closure with binding to the current caller context. This helper + * will always take the latest `callback` + * + * @param callback + */ +export function onComponentUnload(callback: () => void) { + /** + * we use a ref to avoid evaluating the effect function + * on every render and so the unload is called only once + */ + const ref = useRef<typeof callback>(); + ref.current = callback; + + useEffect(() => { + return () => { + ref.current!(); + }; + }, []); +} /** *