first commit
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# `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 `createContext` so descendants get the standard
|
||||
context-update behaviour (re-render on value-reference change) for
|
||||
free.
|
||||
- `displayName` set so React DevTools shows
|
||||
`SuaveplanTranslationContext` instead of the anonymous `Context.Provider`
|
||||
default.
|
||||
- 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
|
||||
|
||||
```tsx
|
||||
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
|
||||
|
||||
```tsx
|
||||
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 `null` is 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 across `react-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 `production` mode flag set by Webpack/Vite.
|
||||
- The context value type is `I18nInstance | null`. The `null` arm
|
||||
forces every reader to handle the no-Provider case explicitly,
|
||||
which catches misconfigurations at type-check time rather than at
|
||||
runtime.
|
||||
Reference in New Issue
Block a user