UNPKG

react-rv

Version:

react-rv is a lightweight and efficient state management library for React that allows you to create reactive variables and subscribe to them with minimal overhead.

199 lines (195 loc) 6.28 kB
/** * A function that listens to reactive variable updates. * * @template T The type of the value being listened to. * * @param val The updated value of the reactive variable. * @param old The old value of the reactive variable. */ type Listener<T> = (val: T, old: T) => void; /** * A function that cleans up event listener. */ type CleanupFn = () => void; /** * A function to compare old and new values for equality. * * @template T The type of values being compared. * * @param oldValue The previous value. * @param newValue The new value to compare against. * * @returns `true` if values are considered equal, `false` otherwise. */ type EqualFn<T> = (oldValue: T, newValue: T) => boolean; /** * Options for configuring a reactive variable. * * @template T The type of the reactive variable's value. */ type RvOptions<T> = { /** * Custom equality function to determine if the value should update. * If set to `false`, the default equality function will be used. */ eq?: false | EqualFn<T>; }; /** * A reactive variable (RV) function that allows getting, setting, and subscribing to changes. * * @template T The type of the stored value. */ interface Rv<T> { /** * Retrieves the current value of the reactive variable. * * @returns The current value of type `T`. */ (): T; /** * Updates the value of the reactive variable. * * @param newValue The new value to set. * @param options Optional configuration for the update. * * @returns The updated value. */ (newValue: T, options?: RvOptions<T>): T; /** * Subscribes a listener to value changes. * * @param listener A callback function that is triggered when the value changes. * * @returns A cleanup function to remove the listener. */ on(listener: Listener<T>): CleanupFn; } /** * Configuration options for initializing a reactive variable. * * @template T The type of the reactive variable's value. */ type RvInitOptions<T> = { /** * Custom equality function to determine if the value should update. */ eq?: EqualFn<T>; /** * A callback function triggered whenever the reactive variable is updated. * * @param val The new value of the reactive variable. */ on?: Listener<T>; }; /** * A factory function for creating reactive variables. */ interface RvInit { /** * Creates a reactive variable (RV), allowing value retrieval, updates, and subscriptions. * * @template T The type of the stored value. * * @param val The initial value of the reactive variable. * @param options Optional configuration for the reactive variable. * * @returns A reactive variable function that allows getting, setting, and listening for updates. */ <T>(val: T, options?: RvInitOptions<T>): Rv<T>; /** * Creates a reactive variable from an initializer function. * The function is immediately executed to determine the initial value. * * @template T The type of the stored value. * * @param init A function that returns the initial value. * @param options Optional configuration for equality comparison and event listeners. * * @returns A reactive variable function. */ fn<T>(init: () => T, options?: RvInitOptions<T>): Rv<T>; } /** * Creates a reactive variable (RV), allowing value retrieval, updates, and subscriptions. * * @template T The type of the stored value. * * @param val The initial value of the reactive variable. * @param options Optional configuration for the reactive variable. * * @returns A reactive variable function that allows getting, setting, and listening for updates. * * @example * ```ts * // initialize a state variable with initial value set to 0 * const positiveVar = rv(0, { * // all options are optional * * // define custom `eq` function that will be run on every value set to determine * // whether or not value is going to be updated * eq: (oldValue, newValue) => newValue > oldValue && newValue >= 0, * * // define callback that's going to be run on every change * on: (newValue, oldValue) => {} * }) * * // alternatively, there's a handy function initializer * // all options are identical * const positiveVar = rv.fn(() => 0) * * // call variable function with no arguments to get its current value * const currentValue = positiveVar() * * // call variable function passing an argument in order to set it * // Won't trigger an update because the values are "equal" under this custom rule. * positiveVar(-3, { * // override the initial `eq` function for this update call. * eq: (oldValue, newValue) => newValue > oldValue * // additionally, you can disable initial `eq` function by passing `false` here * // it will use a default `eq` function which is just a strict check: `===` * eq: false // in this case, update WILL happen * }) * * // you can also subscribe to value without using any hooks * const unsubscribe = positiveVar.on((newValue, oldValue) => console.log(newValue, oldValue)) * * positiveVar(4) // logs: 4 * * unsubscribe() * * positiveVar(5) // there will be no logs * ``` */ declare function rv<T>(val: T, options?: RvInitOptions<T>): Rv<T>; declare namespace rv { var fn: <T>(init: () => T, options?: RvInitOptions<T>) => Rv<T>; } /** * Subscribes to a reactive variable and provides its current value, * updating the state when the variable is updated. * * @template T The type of the reactive variable's value. * @param rv The reactive variable to subscribe to. * * @returns The current value of the reactive variable. * * @example * ```tsx * import React from 'react' * import { rv, useRv } from 'react-rv' * * const counter = rv(0) * * const Counter = () => { * const value = useRv(counter) * return ( * <div> * <p>Count: {value}</p> * <button onClick={() => counter(value + 1)}>Increment</button> * </div> * ) * } * ``` */ declare const useRv: <T>(rv: Rv<T>) => T; export { type CleanupFn, type EqualFn, type Listener, type Rv, type RvInit, type RvInitOptions, type RvOptions, rv, useRv };