UNPKG

fluidstate-react

Version:

Library for using fine-grained reactivity state management library fluidstate in React

121 lines (120 loc) 5.92 kB
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 {};