fluidstate-react
Version:
Library for using fine-grained reactivity state management library fluidstate in React
121 lines (120 loc) • 5.92 kB
TypeScript
import { FunctionComponent, Provider, PropsWithChildren, Context } from "react";
import { DeepPartial } from "./deep-partial";
/**
* A phantom symbol used to associate a `State` type with a component type.
* This enables utility types like `StateType` to extract the state type
* from the component type itself, a technique similar to nominal typing.
*/
declare const PhantomState: unique symbol;
/**
* A React Provider component for providing mock state, typically used in tests
* or Storybook. It provides a partial state object via its `value` prop to its children.
* @template State The full state type.
*/
export type MockProvider<State> = Provider<DeepPartial<State>>;
/**
* The core type definition for the ReactiveProvider component.
* @private
*/
type ReactiveProviderCore<SetupProps> = FunctionComponent<PropsWithChildren<undefined extends SetupProps ? {
setupProps?: undefined;
} : {
setupProps: SetupProps;
}>>;
/**
* A React Provider component that creates and provides reactive state to its children.
* It ensures that the state is created only once per component instance and automatically
* manages the lifecycle of any reactions defined in the state.
*
* It also carries a phantom `State` type, allowing utility types to infer the state shape.
*
* @template SetupProps The type of props required to initialize the state.
* @template State The type of the reactive state object.
*/
export type ReactiveProvider<SetupProps, State> = ReactiveProviderCore<SetupProps> & {
[PhantomState]: State;
};
/**
* A hook for consuming reactive state within a component.
* It subscribes to changes in the slice of state returned by `readReactiveState`
* and re-renders the component when that data changes.
*
* @template State The type of the global reactive state.
* @param readReactiveState A function that selects a part of the state to subscribe to.
* @returns The value returned by `readReactiveState`.
*/
export type UseReactiveState<State> = <T>(readReactiveState: (state: State) => T) => T;
/**
* A higher-order component (HOC) that injects reactive state into a component as a `state` prop.
* The wrapped component will automatically re-render when the reactive state it uses changes.
*
* @template State The type of the global reactive state.
* @param component The component to wrap.
* @returns A new component that receives the reactive state.
*/
export type WithReactiveState<State> = <ComponentProps>(component: FunctionComponent<ComponentProps & {
state: State;
}>) => FunctionComponent<ComponentProps>;
/**
* A factory function type for creating the reactive state.
* It receives `setupProps` and is expected to return the initial state object.
*
* @template SetupProps The type of props for state initialization.
* @template State The type of the reactive state object.
*/
export type CreateState<SetupProps, State> = (props: SetupProps) => State;
/**
* A utility type that extracts the `State` type from a `ReactiveProvider` type.
* @template T The `ReactiveProvider` type.
*/
export type StateType<T> = T extends ReactiveProvider<infer _SetupProps, infer State> ? State : never;
/**
* A utility type that extracts the `SetupProps` type from a `ReactiveProvider` type.
* @template T The `ReactiveProvider` type.
*/
export type SetupPropsType<T> = T extends ReactiveProvider<infer SetupProps, infer _State> ? SetupProps : never;
/**
* A utility type that extracts the `CreateState` function type from a `ReactiveProvider` type.
* @template T The `ReactiveProvider` type.
*/
export type CreateStateType<T> = T extends ReactiveProvider<infer SetupProps, infer State> ? CreateState<SetupProps, State> : never;
/**
* An object containing the complete set of utilities for a specific reactive state setup.
* This includes the provider, consumer hook, HOC, mock provider, and state factory.
*/
export type ReactiveSetup<SetupProps, State> = {
/** The Provider component to wrap parts of the application that need access to the state. */
ReactiveProvider: ReactiveProvider<SetupProps, State>;
/** A hook to access and react to changes in the state. */
useReactiveState: UseReactiveState<State>;
/** A HOC to inject the state as a prop into class or function components. */
withReactiveState: WithReactiveState<State>;
/** A mock provider for testing or Storybook environments. */
MockProvider: MockProvider<State>;
/**
* The original `createState` function, exposed for convenience,
* particularly for testing the state logic itself.
*/
createState: (props: SetupProps) => State;
/** React context containing the returned state. */
StateContext: Context<State>;
};
/**
* Creates a cohesive set of tools for managing a specific piece of reactive state
* within a React application. This pattern promotes encapsulation and simplifies
* state management by providing a dedicated Provider, consumer hook, and HOC.
*
* The created state is instantiated once per `ReactiveProvider` and is automatically
* cleaned up, including any associated reactions, when the provider unmounts.
*
* @template SetupProps The type of props needed by the `createState` function.
* If no props are needed, this can be `undefined`.
* @template State The shape of the reactive state object. If the state object contains
* a `reactions` property (an array of `Reaction` instances), they will be automatically
* cleaned up when the provider unmounts.
* @param {CreateState<SetupProps, State>} createState A factory function that initializes
* and returns the reactive state. It is called once when the `ReactiveProvider` mounts.
* @returns {ReactiveSetup<SetupProps, State>} An object containing the setup utilities.
*/
export declare const createReactiveSetup: <SetupProps, State>(createState: CreateState<SetupProps, State>) => ReactiveSetup<SetupProps, State>;
export {};