useEnvironment / EnvironmentProvider
Relay is opt-in.
@apollion-dsi/relayis the recommended path only if your app uses Relay. Apollion for SSR — or any non-Relay consumer — never needs this package:@apollion-dsi/corecarries no Relay dependency and no core component requires a Relay environment. Themes and rendering work with zero Relay. Everything below applies once you have chosen Relay.
The single Relay provider for an app. EnvironmentProvider publishes the Relay
Environment to the whole React tree and backs both hook systems at once:
- the DS
useEnvironment()hook — for imperative access to theEnvironment(fetchQuery,requestSubscription, the Promise-basedcommitMutation); - every
react-relaystore hook —useLazyLoadQuery,usePreloadedQuery,useFragment,useSubscription.
Internally it mounts react-relay's RelayEnvironmentProvider over the same
Environment, so consumers never import or mount RelayEnvironmentProvider
themselves — that is package plumbing the DS owns. This is why the Relay
integration lives in the design system: EnvironmentProvider is the single seam
where DS themes and Relay meet. Pair it with CreateRelayEnvironment: the
Environment the factory exposes goes into one EnvironmentProvider at the app
root, and everything below reads it — imperatively or through Relay hooks.
The provider also accepts a MockEnvironment from relay-test-utils, so the
backend swaps out in tests with no extra wrappers — the same single mount drives
useEnvironment() and the store hooks under the mock.
When to use
| ✅ Use when… | 🚫 Avoid when… |
|---|---|
|
|
Example — one provider, both hook systems
import { CreateRelayEnvironment, EnvironmentProvider, useEnvironment } from '@apollion-dsi/relay';
import { graphql, useLazyLoadQuery } from 'react-relay';
const { Environment } = new CreateRelayEnvironment({ url: '...' });
function App() {
return (
<EnvironmentProvider environment={Environment}>
<Profile />
<SaveButton />
</EnvironmentProvider>
);
}
// react-relay store hook — resolves under EnvironmentProvider, no
// RelayEnvironmentProvider needed.
function Profile() {
const data = useLazyLoadQuery(graphql`
query ReadmeProfileQuery {
viewer { username }
}
`, {});
return <span>{data.viewer?.username}</span>;
}
// DS imperative hook — reads the same Environment.
function SaveButton() {
const { environment } = useEnvironment();
return <button onClick={() => commitMutation(environment, { ... })}>Save</button>;
}Backward compatibility
Consumers that still wrap their tree in react-relay's
RelayEnvironmentProvider over the same Environment keep working: mounting it
twice is idempotent (the nearest provider wins and it is the same instance).
Migration is therefore a deletion — drop your own RelayEnvironmentProvider and
keep only EnvironmentProvider.
Granular imports
import { useEnvironment, EnvironmentProvider } from '@apollion-dsi/relay/useEnvironment';
// or via the root barrel
import { useEnvironment, EnvironmentProvider } from '@apollion-dsi/relay';See also
- Full API:
useEnvironment.tsx. - Environment factory:
setupRelayEnvironment.