@msflib/react-shared¶
Shared React utilities for all msflib modules. Provides common hooks and helpers that are used consistently across react-auth, react-notification, react-profile, and other modules.
Table of Contents¶
Installation¶
pnpm add @msflib/react-shared
Peer Dependencies¶
| Package | Version |
|---|---|
react |
>= 18 |
@tanstack/react-query |
>= 5 |
API Reference¶
useActiveWorkspace¶
A React hook that returns the currently active workspace slug, and automatically triggers a re-render whenever the workspace changes via setActiveWorkspace() from @msflib/core.
useActiveWorkspace(): string | null
Returns:
string— the active workspace slug (e.g.'acme-corp','globex')null— when no workspace is active (single-workspace mode)
Usage:
import { useActiveWorkspace } from '@msflib/react-shared';
function WorkspaceBadge() {
const workspace = useActiveWorkspace();
if (!workspace) return null;
return <span>Workspace: {workspace}</span>;
}
Usage in module providers (query key scoping):
Workspace-first query keys ensure React Query caches data separately per workspace and automatically refetches when the workspace switches.
import { useActiveWorkspace } from '@msflib/react-shared';
import { useQuery } from '@tanstack/react-query';
const NO_WORKSPACE = '__no_workspace__';
function NotificationProvider({ children }: { children: React.ReactNode }) {
const workspace = useActiveWorkspace();
const { data } = useQuery({
// Workspace is first in the key so all workspace's data is partitioned separately.
// When workspace changes, RQ sees a new key and auto-refetches — no extra code needed.
queryKey: [workspace ?? NO_WORKSPACE, 'react-notification', 'list'],
queryFn: () => api.list(),
});
return <>{children}</>;
}
How it works: The hook uses React 18's
useSyncExternalStoreto subscribe tosubscribeActiveWorkspacefrom@msflib/core. WhensetActiveWorkspace()is called anywhere in the app, all components usinguseActiveWorkspacere-render synchronously with the new value — no React context or prop drilling needed.
createCallbackHandler¶
A utility that normalises TanStack Query mutation callback options to ensure onSuccess, onError, and onSettled are always safely forwarded — even when options is undefined.
createCallbackHandler<TData, TError, TVariables, TContext>(
options?: MutateOptions<TData, TError, TVariables, TContext>
): MutateOptions<TData, TError, TVariables, TContext>
Usage in module providers:
import { createCallbackHandler } from '@msflib/react-shared';
import type { MutateOptions } from '@msflib/react-shared';
// Inside a module provider
const removeNotification = (
id: number,
options?: MutateOptions<void, Error, number>,
) => deleteMutation.mutate(id, createCallbackHandler(options));
Usage in your app:
import { useNotification } from '@msflib/react-notification';
function NotificationItem({ id }: { id: number }) {
const { removeNotification } = useNotification();
function handleDelete() {
removeNotification(id, {
onSuccess: () => toast('Notification removed'),
onError: (err) => toast.error(err.message),
});
}
return <button onClick={handleDelete}>Delete</button>;
}
Without
createCallbackHandler, calling.mutate(vars, undefined)inside a mutation handler can cause runtime errors in some TanStack Query versions. This utility makes the pattern safe and consistent across all modules.
MutateOptions¶
A re-export of MutateOptions from @tanstack/react-query. Provided here so module consumers don't need to install @tanstack/react-query separately just for type imports.
import type { MutateOptions } from '@msflib/react-shared';