3.6 KiB
provider-context.ts
Purpose
Defines the React context that carries the active I18nInstance from
@suaveplan/i18n to every descendant of <TranslationProvider>. The
context is the single coupling point between the Provider and every
hook in @suaveplan/react-i18n — hooks read the instance through this
context, which means they all see the same instance even when the
Provider is mounted under a portal, a nested tree, or a Storybook
decorator.
The default value is intentionally null so the consuming hooks (which
land in sub-wave 1c) can detect a missing Provider ancestor and route
to either the dev-mode loud-failure throw
(ReactI18nError(REACT_I18N.NO_PROVIDER)) or the production-mode
soft-fail identity translator. A null default — rather than a
factory-default no-op instance — keeps the failure path explicit and
prevents silent fall-through to identity behaviour in development.
Features
- React-native
createContextso descendants get the standard context-update behaviour (re-render on value-reference change) for free. displayNameset so React DevTools showsSuaveplanTranslationContextinstead of the anonymousContext.Providerdefault.- Exports the context object (not a hook) so subpath consumers can
useContext(TranslationContext)directly when they need raw access outside the canonical hook surface.
Usage: Basic Example
import { useContext } from "react";
import { TranslationContext } from "@suaveplan/react-i18n/provider";
export function PreviewBadge() {
const i18n = useContext(TranslationContext);
if (!i18n) return null;
return <span>{i18n.catalog.defaultLocale}</span>;
}
Usage: Advanced Example
import { useContext } from "react";
import { TranslationContext } from "@suaveplan/react-i18n/provider";
import {
REACT_I18N_CODES,
ReactI18nError,
} from "@suaveplan/react-i18n/errors";
import { isProductionEnv } from "@suaveplan/react-i18n";
export function useI18n() {
const i18n = useContext(TranslationContext);
if (i18n) return i18n;
if (isProductionEnv()) {
return null;
}
throw new ReactI18nError(
REACT_I18N_CODES.NO_PROVIDER,
"react-i18n.no_provider",
{ context: { hook: "useI18n" } }
);
}
API Reference
TranslationContext: React.Context<I18nInstance | null>
The context whose value is the active I18nInstance (when a
<TranslationProvider> is mounted) or null (when no Provider is
present).
- Default value:
null. displayName:"SuaveplanTranslationContext".
Implementation Notes
- The default of
nullis deliberate. A "no-op identity instance" default would silently pass renders through in development and mask the missing-Provider misconfiguration the dev-mode loud-failure path exists to surface. - The context is exported (rather than wrapped behind a
useI18n()hook) because the hook lives in a separate sub-wave (1c) and consumers in 1b — primarily test fixtures, Storybook decorators, and the Provider itself — need raw access. Exporting both the context AND the eventual hook is the long-standing React pattern proven acrossreact-router,react-query, and dozens of other ecosystem libraries. - The display name is stamped at module load. React DevTools picks it
up automatically; production bundlers strip the assignment under
the standard
productionmode flag set by Webpack/Vite. - The context value type is
I18nInstance | null. Thenullarm forces every reader to handle the no-Provider case explicitly, which catches misconfigurations at type-check time rather than at runtime.