# `useReactI18nRegistry` & `useOptionalReactI18nRegistry` ## Purpose These hooks read the active `ReactI18nRegistry` from React context. The strict variant `useReactI18nRegistry()` throws `REACT_I18N.REGISTRY_NOT_PROVIDED` when called outside a `` ancestor, which is the right behavior for code that genuinely requires the registry (e.g. plugin-aware components). The tolerant variant `useOptionalReactI18nRegistry()` returns `null` outside a provider, which is the right behavior for code that wants to opt into the registry when present but fall back to a non-registry implementation when absent — built-in hooks like `useNumber` use this so existing call sites without `` keep working. ## Features - Strict and tolerant variants with the same context source. - Stable error code (`REACT_I18N.REGISTRY_NOT_PROVIDED`) on the strict variant for programmatic handling. - Zero overhead — both hooks are a single `useContext` lookup. ## Usage: Basic Example ```tsx import { useReactI18nRegistry } from "@suaveplan/react-i18n/registry"; function MyComponent() { const registry = useReactI18nRegistry(); const formatter = registry.getFormatter<{ ms: number }, string>("duration"); return {formatter?.format("en-GB", { ms: 1500 })}; } ``` ## Usage: Advanced Example The tolerant variant is the right choice for any hook or component that should work both inside and outside a ``. The built-in hooks (`useNumber`, `useDate`, …) use it internally: ```ts import { useOptionalReactI18nRegistry } from "@suaveplan/react-i18n/registry"; function useNumber(value: number, options?: NumberOptions): string { const registry = useOptionalReactI18nRegistry(); if (registry) { const plugin = registry.getFormatter("number"); if (plugin) return plugin.format(useLocale(), { value, ...options }); } // Fallback path — direct call to @suaveplan/i18n-formatter-number return formatNumber(useLocale(), value, options); } ``` For test fixtures that mount a registry per-case, the strict hook is appropriate — a missing provider in a test is a wiring bug and should fail loudly. ## API Reference ### `useReactI18nRegistry(): ReactI18nRegistry` Reads the registry from `RegistryContext`. Throws `ReactI18nError(REACT_I18N.REGISTRY_NOT_PROVIDED)` when no `` is in scope. ### `useOptionalReactI18nRegistry(): ReactI18nRegistry | null` Reads the registry from `RegistryContext`. Returns `null` when no `` is in scope. ## Implementation Notes - Both hooks are bound to a single module-scoped `RegistryContext` so the brand identity of the context is preserved across SSR / hot-reload / dev-bundle scenarios. - Two `` ancestors in the same tree result in the inner one winning — React context resolution is closest-ancestor wins. This is the desired behavior for layered apps where a sub-tree wants its own registry overlay; if you do not want that, mount only one provider. - The tolerant variant returns `null` rather than an "empty" registry sentinel. A null check at the call site is more honest than papering over the missing-provider case with a no-op registry.