UNPKG

recoil

Version:

Recoil - A state management library for React

582 lines (492 loc) 20.6 kB
// Minimum TypeScript Version: 3.7 /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @emails oncall+recoil */ /** * This file is a manual translation of the flow types, which are the source of truth, so we should not introduce new terminology or behavior in this file. */ export { }; import * as React from 'react'; // state.d.ts type NodeKey = string; // node.d.ts export class DefaultValue { private __tag: 'DefaultValue'; } // recoilRoot.d.ts export type RecoilRootProps = { initializeState?: (mutableSnapshot: MutableSnapshot) => void, override?: true, children: React.ReactNode, } | { override: false, children: React.ReactNode, }; /** * Root component for managing Recoil state. Most Recoil hooks should be * called from a component nested in a <RecoilRoot> */ export const RecoilRoot: React.FC<RecoilRootProps>; // Snapshot.d.ts declare const SnapshotID_OPAQUE: unique symbol; export interface SnapshotID { readonly [SnapshotID_OPAQUE]: true; } interface ComponentInfo { name: string; } interface RecoilStateInfo<T> { loadable?: Loadable<T>; isActive: boolean; isSet: boolean; isModified: boolean; // TODO report modified selectors type: 'atom' | 'selector'; deps: Iterable<RecoilValue<T>>; subscribers: { nodes: Iterable<RecoilValue<T>>, components: Iterable<ComponentInfo>, }; } export class Snapshot { getID(): SnapshotID; getLoadable<T>(recoilValue: RecoilValue<T>): Loadable<T>; getPromise<T>(recoilValue: RecoilValue<T>): Promise<T>; getNodes_UNSTABLE(opts?: { isModified?: boolean, isInitialized?: boolean }): Iterable<RecoilValue<unknown>>; getInfo_UNSTABLE<T>(recoilValue: RecoilValue<T>): RecoilStateInfo<T>; map(cb: (mutableSnapshot: MutableSnapshot) => void): Snapshot; asyncMap(cb: (mutableSnapshot: MutableSnapshot) => Promise<void>): Promise<Snapshot>; retain(): () => void; isRetained(): boolean; } export class MutableSnapshot extends Snapshot { set: SetRecoilState; reset: ResetRecoilState; } declare const WrappedValue_OPAQUE: unique symbol; export interface WrappedValue<T> { readonly [WrappedValue_OPAQUE]: true; } // Effect is called the first time a node is used with a <RecoilRoot> export type AtomEffect<T> = (param: { node: RecoilState<T>, storeID: StoreID, trigger: 'set' | 'get', // Call synchronously to initialize value or async to change it later setSelf: (param: | T | DefaultValue | Promise<T | DefaultValue> | ((param: T | DefaultValue) => T | DefaultValue), ) => void, resetSelf: () => void, // Subscribe callbacks to events. // Atom effect observers are called before global transaction observers onSet: ( param: (newValue: T, oldValue: T | DefaultValue, isReset: boolean) => void, ) => void, // Accessors to read other atoms/selectors getPromise: <S>(recoilValue: RecoilValue<S>) => Promise<S>, getLoadable: <S>(recoilValue: RecoilValue<S>) => Loadable<S>, getInfo_UNSTABLE: <S>(recoilValue: RecoilValue<S>) => RecoilStateInfo<S>, }) => void | (() => void); // atom.d.ts interface AtomOptionsWithoutDefault<T> { key: NodeKey; effects?: ReadonlyArray<AtomEffect<T>>; effects_UNSTABLE?: ReadonlyArray<AtomEffect<T>>; dangerouslyAllowMutability?: boolean; } interface AtomOptionsWithDefault<T> extends AtomOptionsWithoutDefault<T> { default: RecoilValue<T> | Promise<T> | Loadable<T> | WrappedValue<T> | T; } export type AtomOptions<T> = AtomOptionsWithoutDefault<T> | AtomOptionsWithDefault<T>; /** * Creates an atom, which represents a piece of writeable state */ export function atom<T>(options: AtomOptions<T>): RecoilState<T>; export namespace atom { function value<T>(value: T): WrappedValue<T>; } export type GetRecoilValue = <T>(recoilVal: RecoilValue<T>) => T; export type SetterOrUpdater<T> = (valOrUpdater: ((currVal: T) => T) | T) => void; export type Resetter = () => void; export interface TransactionInterface_UNSTABLE { get<T>(a: RecoilValue<T>): T; set<T>(s: RecoilState<T>, u: ((currVal: T) => T) | T): void; reset(s: RecoilState<any>): void; } export interface CallbackInterface { set: <T>(recoilVal: RecoilState<T>, valOrUpdater: ((currVal: T) => T) | T) => void; reset: (recoilVal: RecoilState<any>) => void; // eslint-disable-line @typescript-eslint/no-explicit-any refresh: (recoilValue: RecoilValue<any>) => void; snapshot: Snapshot; gotoSnapshot: (snapshot: Snapshot) => void; transact_UNSTABLE: (cb: (i: TransactionInterface_UNSTABLE) => void) => void; } // selector.d.ts export interface SelectorCallbackInterface extends CallbackInterface { node: RecoilState<unknown>; // TODO This isn't properly typed } export type GetCallback = <Args extends ReadonlyArray<unknown>, Return>( fn: (interface: SelectorCallbackInterface) => (...args: Args) => Return, ) => (...args: Args) => Return; export type SetRecoilState = <T>( recoilVal: RecoilState<T>, newVal: T | DefaultValue | ((prevValue: T) => T | DefaultValue), ) => void; export type ResetRecoilState = (recoilVal: RecoilState<any>) => void; // eslint-disable-line @typescript-eslint/no-explicit-any // export type EqualityPolicy = 'reference' | 'value'; TODO: removing while we discuss long term API export type EvictionPolicy = 'lru' | 'keep-all' | 'most-recent'; // TODO: removing while we discuss long term API // export type CachePolicy = // | {eviction: 'lru', maxSize: number, equality?: EqualityPolicy} // | {eviction: 'none', equality?: EqualityPolicy} // | {eviction?: undefined, equality: EqualityPolicy}; // TODO: removing while we discuss long term API // export interface CachePolicyWithoutEviction { // equality: EqualityPolicy; // } export type CachePolicyWithoutEquality = {eviction: 'lru', maxSize: number} | {eviction: 'keep-all'} | {eviction: 'most-recent'}; export interface ReadOnlySelectorOptions<T> { key: string; get: (opts: { get: GetRecoilValue, getCallback: GetCallback, }) => Promise<T> | RecoilValue<T> | Loadable<T> | WrappedValue<T> | T; dangerouslyAllowMutability?: boolean; cachePolicy_UNSTABLE?: CachePolicyWithoutEquality; // TODO: using the more restrictive CachePolicyWithoutEquality while we discuss long term API } export interface ReadWriteSelectorOptions<T> extends ReadOnlySelectorOptions<T> { set: ( opts: { set: SetRecoilState; get: GetRecoilValue; reset: ResetRecoilState; }, newValue: T | DefaultValue, ) => void; } /** * Creates a selector which represents derived state. */ export function selector<T>(options: ReadWriteSelectorOptions<T>): RecoilState<T>; export function selector<T>(options: ReadOnlySelectorOptions<T>): RecoilValueReadOnly<T>; export namespace selector { function value<T>(value: T): WrappedValue<T>; } // hooks.d.ts /** * Returns the value of an atom or selector (readonly or writeable) and * subscribes the components to future updates of that state. */ export function useRecoilValue<T>(recoilValue: RecoilValue<T>): T; /** * Returns a Loadable representing the status of the given Recoil state * and subscribes the component to future updates of that state. Useful * for working with async selectors. */ export function useRecoilValueLoadable<T>(recoilValue: RecoilValue<T>): Loadable<T>; /** * Returns a tuple where the first element is the value of the recoil state * and the second is a setter to update that state. Subscribes component * to updates of the given state. */ export function useRecoilState<T>(recoilState: RecoilState<T>): [T, SetterOrUpdater<T>]; /** * Returns a tuple where the first element is a Loadable and the second * element is a setter function to update the given state. Subscribes * component to updates of the given state. */ export function useRecoilStateLoadable<T>(recoilState: RecoilState<T>): [Loadable<T>, SetterOrUpdater<T>]; /** * Returns a setter function for updating Recoil state. Does not subscribe * the component to the given state. */ export function useSetRecoilState<T>(recoilState: RecoilState<T>): SetterOrUpdater<T>; /** * Returns a function that will reset the given state to its default value. */ export function useResetRecoilState(recoilState: RecoilState<any>): Resetter; // eslint-disable-line @typescript-eslint/no-explicit-any /** * Returns current info about an atom */ export function useGetRecoilValueInfo_UNSTABLE(): <T>(recoilValue: RecoilValue<T>) => RecoilStateInfo<T>; /** * Experimental version of hooks for useTransition() support */ export function useRecoilValue_TRANSITION_SUPPORT_UNSTABLE<T>(recoilValue: RecoilValue<T>): T; export function useRecoilValueLoadable_TRANSITION_SUPPORT_UNSTABLE<T>(recoilValue: RecoilValue<T>): Loadable<T>; export function useRecoilState_TRANSITION_SUPPORT_UNSTABLE<T>(recoilState: RecoilState<T>): [T, SetterOrUpdater<T>]; /** * Returns a function that will run the callback that was passed when * calling this hook. Useful for accessing Recoil state in response to * events. */ export function useRecoilCallback<Args extends ReadonlyArray<unknown>, Return>( fn: (interface: CallbackInterface) => (...args: Args) => Return, deps?: ReadonlyArray<unknown>, ): (...args: Args) => Return; /** * Returns a function that executes an atomic transaction for updating Recoil state. */ export function useRecoilTransaction_UNSTABLE<Args extends ReadonlyArray<unknown>>( fn: (interface: TransactionInterface_UNSTABLE) => (...args: Args) => void, deps?: ReadonlyArray<unknown>, ): (...args: Args) => void; export function useRecoilTransactionObserver_UNSTABLE( callback: (opts: { snapshot: Snapshot, previousSnapshot: Snapshot, }) => void, ): void; /** * Updates Recoil state to match the provided snapshot. */ export function useGotoRecoilSnapshot(): (snapshot: Snapshot) => void; /** * Returns a snapshot of the current Recoil state and subscribes the component * to re-render when any state is updated. */ export function useRecoilSnapshot(): Snapshot; // useRecoilRefresher.d.ts /** * Clears the cache for a selector causing it to be reevaluated. */ export function useRecoilRefresher_UNSTABLE(recoilValue: RecoilValue<any>): () => void; // useRecoilBridgeAcrossReactRoots.d.ts export const RecoilBridge: React.FC<{children: React.ReactNode}>; /** * Returns a component that acts like a <RecoilRoot> but shares the same store * as the current <RecoilRoot>. */ export function useRecoilBridgeAcrossReactRoots_UNSTABLE(): typeof RecoilBridge; // useRecoilStoreID declare const StoreID_OPAQUE: unique symbol; export interface StoreID { readonly [StoreID_OPAQUE]: true; } /** * Returns an ID for the currently active state store of the host <RecoilRoot> */ export function useRecoilStoreID(): StoreID; // loadable.d.ts interface BaseLoadable<T> { getValue: () => T; toPromise: () => Promise<T>; valueOrThrow: () => T; errorOrThrow: () => any; promiseOrThrow: () => Promise<T>; is: (other: Loadable<any>) => boolean; map: <S>(map: (from: T) => Loadable<S> | Promise<S> | S) => Loadable<S>; } interface ValueLoadable<T> extends BaseLoadable<T> { state: 'hasValue'; contents: T; valueMaybe: () => T; errorMaybe: () => undefined; promiseMaybe: () => undefined; } interface LoadingLoadable<T> extends BaseLoadable<T> { state: 'loading'; contents: Promise<T>; valueMaybe: () => undefined; errorMaybe: () => undefined; promiseMaybe: () => Promise<T>; } interface ErrorLoadable<T> extends BaseLoadable<T> { state: 'hasError'; contents: any; valueMaybe: () => undefined; errorMaybe: () => any; promiseMaybe: () => undefined; } export type Loadable<T> = | ValueLoadable<T> | LoadingLoadable<T> | ErrorLoadable<T>; // recoilValue.d.ts declare class AbstractRecoilValue<T> { __tag: [T]; __cTag: (t: T) => void; // for contravariance key: NodeKey; constructor(newKey: NodeKey); } declare class AbstractRecoilValueReadonly<T> { __tag: [T]; key: NodeKey; constructor(newKey: NodeKey); } export class RecoilState<T> extends AbstractRecoilValue<T> {} export class RecoilValueReadOnly<T> extends AbstractRecoilValueReadonly<T> {} export type RecoilValue<T> = RecoilValueReadOnly<T> | RecoilState<T>; /** * Returns true if the parameter is a Recoil atom or selector. */ export function isRecoilValue(val: unknown): val is RecoilValue<any>; // eslint-disable-line @typescript-eslint/no-explicit-any /** Utilities */ // bigint not supported yet type Primitive = undefined | null | boolean | number | symbol | string; interface HasToJSON { toJSON(): SerializableParam; } export type SerializableParam = | Primitive | HasToJSON | ReadonlyArray<SerializableParam> | ReadonlySet<SerializableParam> | ReadonlyMap<SerializableParam, SerializableParam> | Readonly<{[key: string]: SerializableParam}>; interface AtomFamilyOptionsWithoutDefault<T, P extends SerializableParam> { key: NodeKey; dangerouslyAllowMutability?: boolean; effects?: | ReadonlyArray<AtomEffect<T>> | ((param: P) => ReadonlyArray<AtomEffect<T>>); effects_UNSTABLE?: | ReadonlyArray<AtomEffect<T>> | ((param: P) => ReadonlyArray<AtomEffect<T>>); // cachePolicyForParams_UNSTABLE?: CachePolicyWithoutEviction; TODO: removing while we discuss long term API } interface AtomFamilyOptionsWithDefault<T, P extends SerializableParam> extends AtomFamilyOptionsWithoutDefault<T, P> { default: | RecoilValue<T> | Promise<T> | Loadable<T> | WrappedValue<T> | T | ((param: P) => T | RecoilValue<T> | Promise<T> | Loadable<T> | WrappedValue<T>); } export type AtomFamilyOptions<T, P extends SerializableParam> = | AtomFamilyOptionsWithDefault<T, P> | AtomFamilyOptionsWithoutDefault<T, P>; /** * Returns a function which returns a memoized atom for each unique parameter value. */ export function atomFamily<T, P extends SerializableParam>( options: AtomFamilyOptions<T, P>, ): (param: P) => RecoilState<T>; export interface ReadOnlySelectorFamilyOptions<T, P extends SerializableParam> { key: string; get: (param: P) => (opts: { get: GetRecoilValue, getCallback: GetCallback, }) => Promise<T> | RecoilValue<T> | Loadable<T> | WrappedValue<T> | T; // cachePolicyForParams_UNSTABLE?: CachePolicyWithoutEviction; TODO: removing while we discuss long term API cachePolicy_UNSTABLE?: CachePolicyWithoutEquality; // TODO: using the more restrictive CachePolicyWithoutEquality while we discuss long term API dangerouslyAllowMutability?: boolean; } export interface ReadWriteSelectorFamilyOptions<T, P extends SerializableParam> { key: string; get: (param: P) => (opts: { get: GetRecoilValue, getCallback: GetCallback, }) => Promise<T> | Loadable<T> | WrappedValue<T> | RecoilValue<T> | T; set: ( param: P, ) => ( opts: { set: SetRecoilState; get: GetRecoilValue; reset: ResetRecoilState }, newValue: T | DefaultValue, ) => void; // cachePolicyForParams_UNSTABLE?: CachePolicyWithoutEviction; TODO: removing while we discuss long term API cachePolicy_UNSTABLE?: CachePolicyWithoutEquality; // TODO: using the more restrictive CachePolicyWithoutEquality while we discuss long term API dangerouslyAllowMutability?: boolean; } /** * Returns a function which returns a memoized atom for each unique parameter value. */ export function selectorFamily<T, P extends SerializableParam>( options: ReadWriteSelectorFamilyOptions<T, P>, ): (param: P) => RecoilState<T>; /** * Returns a function which returns a memoized atom for each unique parameter value. */ export function selectorFamily<T, P extends SerializableParam>( options: ReadOnlySelectorFamilyOptions<T, P>, ): (param: P) => RecoilValueReadOnly<T>; /** * Returns a selector that always has a constant value. */ export function constSelector<T extends SerializableParam>(constant: T): RecoilValueReadOnly<T>; /** * Returns a selector which is always in the provided error state. */ export function errorSelector(message: string): RecoilValueReadOnly<never>; /** * Casts a selector to be a read-only selector */ export function readOnlySelector<T>(atom: RecoilValue<T>): RecoilValueReadOnly<T>; /** * Returns a selector that has the value of the provided atom or selector as a Loadable. * This means you can use noWait() to avoid entering an error or suspense state in * order to manually handle those cases. */ export function noWait<T>(state: RecoilValue<T>): RecoilValueReadOnly<Loadable<T>>; /* eslint-disable @typescript-eslint/no-explicit-any */ export type UnwrapRecoilValue<T> = T extends RecoilValue<infer R> ? R : never; export type UnwrapRecoilValues<T extends Array<RecoilValue<any>> | { [key: string]: RecoilValue<any> }> = { [P in keyof T]: UnwrapRecoilValue<T[P]>; }; export type UnwrapRecoilValueLoadables<T extends Array<RecoilValue<any>> | { [key: string]: RecoilValue<any> }> = { [P in keyof T]: Loadable<UnwrapRecoilValue<T[P]>>; }; export function waitForNone<RecoilValues extends Array<RecoilValue<any>> | [RecoilValue<any>]>( param: RecoilValues, ): RecoilValueReadOnly<UnwrapRecoilValueLoadables<RecoilValues>>; export function waitForNone<RecoilValues extends { [key: string]: RecoilValue<any> }>( param: RecoilValues, ): RecoilValueReadOnly<UnwrapRecoilValueLoadables<RecoilValues>>; export function waitForAny<RecoilValues extends Array<RecoilValue<any>> | [RecoilValue<any>]>( param: RecoilValues, ): RecoilValueReadOnly<UnwrapRecoilValueLoadables<RecoilValues>>; export function waitForAny<RecoilValues extends { [key: string]: RecoilValue<any> }>( param: RecoilValues, ): RecoilValueReadOnly<UnwrapRecoilValueLoadables<RecoilValues>>; export function waitForAll<RecoilValues extends Array<RecoilValue<any>> | [RecoilValue<any>]>( param: RecoilValues, ): RecoilValueReadOnly<UnwrapRecoilValues<RecoilValues>>; export function waitForAll<RecoilValues extends { [key: string]: RecoilValue<any> }>( param: RecoilValues, ): RecoilValueReadOnly<UnwrapRecoilValues<RecoilValues>>; export function waitForAllSettled<RecoilValues extends Array<RecoilValue<any>> | [RecoilValue<any>]>( param: RecoilValues, ): RecoilValueReadOnly<UnwrapRecoilValueLoadables<RecoilValues>>; export function waitForAllSettled<RecoilValues extends { [key: string]: RecoilValue<any> }>( param: RecoilValues, ): RecoilValueReadOnly<UnwrapRecoilValueLoadables<RecoilValues>>; export type UnwrapLoadable<T> = T extends Loadable<infer R> ? R : T extends Promise<infer P> ? P : T; export type UnwrapLoadables<T extends any[] | { [key: string]: any }> = { [P in keyof T]: UnwrapLoadable<T[P]>; }; /* eslint-disable @typescript-eslint/no-unused-vars */ export namespace RecoilLoadable { /** * Factory to make a Loadable object. If a Promise is provided the Loadable will * be in a 'loading' state until the Promise is either resolved or rejected. */ function of<T>(x: T | Promise<T> | Loadable<T>): Loadable<T>; /** * Factory to make a Loadable object in an error state. */ function error(x: any): ErrorLoadable<any>; /** * Factory to make a loading Loadable which never resolves. */ function loading(): LoadingLoadable<any>; /** * Factory to make a Loadable which is resolved when all of the Loadables provided * to it are resolved or any one has an error. The value is an array of the values * of all of the provided Loadables. This is comparable to Promise.all() for Loadables. * Similar to Promise.all(), inputs may be Loadables, Promises, or literal values. */ function all<Inputs extends any[] | [Loadable<any>]>(inputs: Inputs): Loadable<UnwrapLoadables<Inputs>>; function all<Inputs extends {[key: string]: any}>(inputs: Inputs): Loadable<UnwrapLoadables<Inputs>>; /** * Returns true if the provided parameter is a Loadable type. */ function isLoadable(x: any): x is Loadable<any>; } /* eslint-enable @typescript-eslint/no-unused-vars */ /* eslint-enable @typescript-eslint/no-explicit-any */ /** * Factory to produce a Recoil snapshot object with all atoms in the default state. */ export function snapshot_UNSTABLE(initializeState?: (shapshot: MutableSnapshot) => void): Snapshot;