UNPKG

@stripe/ui-extension-sdk

Version:

The suite of functionality available to UI extensions in Stripe apps

85 lines (84 loc) 3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useStorage = useStorage; const react_1 = require("react"); function getStorage() { try { return ( // Injected as a part of Sandbox initialisation by @sail/ext globalThis.__memoryStorage || // Used solely for tests (in a real sandbox, access to web storage is blocked) globalThis.sessionStorage); } catch (e) { return null; } } /** * Hook for reading and writing shared data across different viewports of a Stripe App. * * Provides a way to synchronize state between all active instances * (viewports) of your Stripe App within the same browser context. When the * value is updated in one instance, all other instances in the same browser * will reflect the change automatically. This is session-based storage that * exists only while the app is running. * * Accepts a unique identifier for the storage item. * * Returns a tuple containing the current value from storage and a function to * update the value in storage. * * Potential use cases: * - Coordinating state between multiple viewports of your app * - Avoiding redundant API calls by caching and sharing fetched data across viewports. * * Example: * ```tsx * // Share state across viewports * const [currentTab, setCurrentTab] = useStorage('activeTab'); * * // Update the shared value * const handleTabChange = (tabName) => { * setCurrentTab(tabName); * }; * * // All viewports will display the same tab * return <Box>Active tab: {currentTab || 'home'}</Box>; * ``` * * Please note that * - Values are limited to strings. For complex objects, please use JSON.stringify/parse. * - Storage is not persistent between app sessions. * - Changes won't synchronize between different browsers or devices. * * See: https://docs.stripe.com/stripe-apps/reference/extensions-sdk-api#useStorage */ function useStorage(key) { const storage = getStorage(); const [value, setValueInternal] = (0, react_1.useState)(() => storage?.getItem(key)); const setItem = (0, react_1.useCallback)((val) => { setValueInternal(val); storage?.setItem(key, val); }, [storage, key]); (0, react_1.useEffect)(() => { if (!storage) { return; } function handleStorageEvent(event) { const { storageArea, key: updatedKey, newValue, oldValue } = event; if (storageArea !== storage) { return; } if (updatedKey === key) { setValueInternal(newValue); } // storage is cleared if (updatedKey === null && oldValue === null && newValue === null) { setValueInternal(null); } } addEventListener('storage', handleStorageEvent); return () => removeEventListener('storage', handleStorageEvent); }, [storage, key]); return [value ?? null, setItem]; }