Hydrator
The Hydrator
component in Igris is a wrapper component that manages the hydration process for persisted stores and states. It provides a declarative way to handle hydration with loading states and ensures your application only renders after data is properly hydrated.
Basic Usage
Using with Stores Directly
import { Hydrator } from "igris/persistence";
function App() {
return (
<Hydrator stores={[usePersistedStore, usePersistedState]}>
<Main />
</Hydrator>
);
}
Using with Pre-configured Hydrator
import { Hydrator, setupHydrator } from "igris/persistence";
const hydrator = setupHydrator([usePersistedStore, usePersistedState], {
storage: sessionStorage
});
function App() {
return (
<Hydrator handler={hydrator}>
<Main />
</Hydrator>
);
}
API Reference
Hydrator
Props
The Hydrator
component accepts two different prop configurations:
Configuration with Stores
interface HydratorStoresConfig {
stores: (StateHook<AnyType> | StoreHook<AnyType, AnyType>)[];
config?: {
storage?: StorageProvider;
};
loadingComponent?: React.ReactNode | React.ReactNode[];
children: React.ReactNode | React.ReactNode[];
}
Configuration with Handler
interface HydratorHandlerConfig {
handler: () => void | Promise<void>;
loadingComponent?: React.ReactNode | React.ReactNode[];
children: React.ReactNode | React.ReactNode[];
}
Advanced Usage
Custom Loading Component
function App() {
return (
<Hydrator
stores={[usePersistedStore, usePersistedState]}
loadingComponent={<CustomLoadingSpinner />}
>
<Main />
</Hydrator>
);
}
With Custom Storage
function App() {
return (
<Hydrator
stores={[usePersistedStore, usePersistedState]}
config={{
storage: sessionStorage
}}
>
<Main />
</Hydrator>
);
}
With Pre-configured Handler and Loading State
const hydrator = setupHydrator([usePersistedStore, usePersistedState]);
function App() {
return (
<Hydrator
handler={hydrator}
loadingComponent={
<div className="loading-state">
<Spinner />
<p>Loading application state...</p>
</div>
}
>
<Main />
</Hydrator>
);
}
TypeScript Interface
export type HydratorOption =
| {
handler: () => void | Promise<void>;
stores?: never;
config?: never;
loadingComponent?: React.ReactNode | React.ReactNode[];
}
| {
handler?: never;
stores: (StateHook<AnyType> | StoreHook<AnyType, AnyType>)[];
config?: Partial<{
storage: StorageProvider;
}>;
loadingComponent?: React.ReactNode | React.ReactNode[];
};
export type HydratorProps = HydratorOption & {
children: React.ReactNode | React.ReactNode[];
};
Important Notes
-
The
Hydrator
component must be used at the root level of your application, above any components that use persisted stores or states. -
You must use either the
stores
prop or thehandler
prop, but not both:- Use
stores
for direct configuration - Use
handler
when you have a pre-configured hydrator fromsetupHydrator
- Use
-
The
loadingComponent
prop is optional:- If not provided, nothing will be rendered during hydration
- Can be any valid React node or array of nodes
-
The component automatically manages the hydration lifecycle:
- Initiates hydration on mount
- Renders loading component during hydration
- Renders children only after successful hydration
Example with Multiple Configuration Options
import { Hydrator, setupHydrator } from "igris/persistence";
import { usePersistedStore, usePersistedState } from "./stores";
// Option 1: Direct configuration
function App1() {
return (
<Hydrator
stores={[usePersistedStore, usePersistedState]}
config={{ storage: sessionStorage }}
loadingComponent={<LoadingScreen />}
>
<Main />
</Hydrator>
);
}
// Option 2: Pre-configured handler
const hydrator = setupHydrator([usePersistedStore, usePersistedState], {
storage: sessionStorage
});
function App2() {
return (
<Hydrator
handler={hydrator}
loadingComponent={<LoadingScreen />}
>
<Main />
</Hydrator>
);
}