Hook result types
Shared shapes behind the action hooks: loading and error state, actions resolving to success, and the wishlist, like and coupon results.
import { AsyncState, AsyncStateWithValue, AsyncAction, AsyncActionWithParam, ToggleActions, ToggleActionsWithItem, ApplyActions, UseToggleWithItems, UseToggle, UseApply, FetchState, FetchStateWithRefresh, AsyncFnState } from '@salla.sa/twilight-theme-engine/hooks';In plain words
Three engine hooks follow three patterns, and these types name them: a list you add items to and remove them from (the wishlist), one thing you switch on and off with a count (a blog like), and a value you apply or remove (a coupon). Each has loading, an error message, and actions that resolve true on success.
Use them to give your own hooks the same shape, so they feel familiar next to the engine's.
Signature
interface AsyncState { loading: boolean; error: string | null }
interface AsyncStateWithValue<T> extends AsyncState { value: T }
type AsyncAction = () => Promise<boolean>;
type AsyncActionWithParam<T> = (param: T) => Promise<boolean>;
interface ToggleActions { add: AsyncAction; remove: AsyncAction; toggle: AsyncAction }
interface ToggleActionsWithItem<T = number> {
has: (item: T) => boolean;
add: AsyncActionWithParam<T>; remove: AsyncActionWithParam<T>; toggle: AsyncActionWithParam<T>;
}
interface ApplyActions<T = string> { apply: AsyncActionWithParam<T>; remove: AsyncAction }
interface UseToggleWithItems<T = number> extends AsyncState, ToggleActionsWithItem<T> { ids: T[]; count: number } // useWishlist
interface UseToggle extends AsyncState, ToggleActions { active: boolean; count: number } // useBlogLike
interface UseApply<T = string> extends AsyncState, ApplyActions<T> { value: T | null } // useCoupon
interface FetchState<T> { data: T; loading: boolean; error: Error | null }
interface FetchStateWithRefresh<T> extends FetchState<T> { refresh: () => Promise<void> }
// AsyncFnState<T>: useAsyncFn's generic AsyncState<T>, renamed in this barrelExample
import { useState } from 'react';
import type { AsyncActionWithParam, AsyncState } from '@salla.sa/twilight-theme-engine/hooks';
export interface UseSubmitResult extends AsyncState {
submit: AsyncActionWithParam<string>;
}
/** The engine's action-hook shape around any async call of yours. */
export function useSubmit(send: (value: string) => Promise<void>): UseSubmitResult {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const submit = async (value: string) => {
setLoading(true);
setError(null);
try {
await send(value);
return true;
} catch (caught) {
setError(caught instanceof Error ? caught.message : String(caught));
return false;
} finally {
setLoading(false);
}
};
return { loading, error, submit };
}
How it behaves
UseWishlistResultisUseToggleWithItems<number>,UseBlogLikeResultisUseToggle, andUseCouponResultisUseApply<string>.All of them are reachable only through the
@salla.sa/twilight-theme-engine/hooksbarrel:hooks/types.tshas no subpath.No engine hook returns
AsyncStateWithValue,FetchStateorFetchStateWithRefresh; engine data fetching uses TanStack Query instead.
Gotchas
Two different types share the name
AsyncState. From@salla.sa/twilight-theme-engine/hooksit is this{ loading; error: string | null }; from@salla.sa/twilight-theme-engine/hooks/useAsyncFnit is the genericAsyncState<T>whoseerroris anError, which the barrel renamesAsyncFnState. Check the import path when the types do not line up.errorisstring | nullinAsyncStatebutError | nullinFetchState.
Related
The shopper's wishlist, shared by every component on the page: check a product, and add, remove or toggle it through the Salla SDK.
useBlogLikeLikes or unlikes a blog article through the Salla API, with a local like count and a per-browser memory of liked articles.
useCouponApplies or removes a discount coupon on the shopper's cart through the Salla SDK, with loading and error state.
useAsyncFnWraps an async function with loading, error and value state; only the newest call updates state, and nothing updates after unmount.
Source and docs
- Engine source:
packages/theme-engine/src/hooks/types.ts