Recoil is an experimental state management framework for React applications that provides atoms and selectors for fine-grained reactivity.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Recoil is an experimental React state management framework that provides fine-grained reactivity through atoms (units of state) and selectors (derived state). It offers minimal boilerplate with automatic optimization, where components only re-render when specific state they depend on changes, and includes built-in support for asynchronous operations and concurrent React features.
npm install recoilimport {
RecoilRoot,
atom,
selector,
useRecoilState,
useRecoilValue,
useSetRecoilState
} from "recoil";CommonJS:
const {
RecoilRoot,
atom,
selector,
useRecoilState,
useRecoilValue,
useSetRecoilState
} = require("recoil");import React from 'react';
import {
RecoilRoot,
atom,
selector,
useRecoilState,
useRecoilValue,
} from 'recoil';
// Define atoms (state)
const textState = atom({
key: 'textState',
default: '',
});
// Define selectors (derived state)
const charCountState = selector({
key: 'charCountState',
get: ({get}) => {
const text = get(textState);
return text.length;
},
});
// Component using Recoil state
function TextInput() {
const [text, setText] = useRecoilState(textState);
return (
<input
value={text}
onChange={(e) => setText(e.target.value)}
/>
);
}
function CharacterCount() {
const count = useRecoilValue(charCountState);
return <div>Character Count: {count}</div>;
}
// App with RecoilRoot
function App() {
return (
<RecoilRoot>
<TextInput />
<CharacterCount />
</RecoilRoot>
);
}Recoil is built around several key concepts:
Core component for managing Recoil state throughout your React application.
interface RecoilRootProps {
initializeState?: (mutableSnapshot: MutableSnapshot) => void;
override?: boolean;
children: React.ReactNode;
}
const RecoilRoot: React.FC<RecoilRootProps>;Core functions for defining atoms and selectors that form the state graph.
interface AtomOptions<T> {
key: string;
default?: T | RecoilValue<T> | Promise<T> | Loadable<T> | WrappedValue<T>;
effects?: ReadonlyArray<AtomEffect<T>>;
dangerouslyAllowMutability?: boolean;
}
function atom<T>(options: AtomOptions<T>): RecoilState<T>;
interface ReadOnlySelectorOptions<T> {
key: string;
get: (opts: { get: GetRecoilValue; getCallback: GetCallback }) =>
T | RecoilValue<T> | Promise<T> | Loadable<T> | WrappedValue<T>;
cachePolicy_UNSTABLE?: CachePolicyWithoutEquality;
dangerouslyAllowMutability?: boolean;
}
interface ReadWriteSelectorOptions<T> extends ReadOnlySelectorOptions<T> {
set: (opts: {
set: SetRecoilState;
get: GetRecoilValue;
reset: ResetRecoilState;
}, newValue: T | DefaultValue) => void;
}
function selector<T>(options: ReadWriteSelectorOptions<T>): RecoilState<T>;
function selector<T>(options: ReadOnlySelectorOptions<T>): RecoilValueReadOnly<T>;Essential React hooks for reading and writing Recoil state with automatic subscriptions.
function useRecoilValue<T>(recoilValue: RecoilValue<T>): T;
function useRecoilState<T>(recoilState: RecoilState<T>): [T, SetterOrUpdater<T>];
function useSetRecoilState<T>(recoilState: RecoilState<T>): SetterOrUpdater<T>;
function useResetRecoilState(recoilState: RecoilState<any>): () => void;
function useRecoilValueLoadable<T>(recoilValue: RecoilValue<T>): Loadable<T>;
function useRecoilStateLoadable<T>(recoilState: RecoilState<T>): [Loadable<T>, SetterOrUpdater<T>];Functions for creating parameterized atoms and selectors that are memoized by parameter.
function atomFamily<T, P extends SerializableParam>(
options: AtomFamilyOptions<T, P>
): (param: P) => RecoilState<T>;
function selectorFamily<T, P extends SerializableParam>(
options: ReadWriteSelectorFamilyOptions<T, P>
): (param: P) => RecoilState<T>;
function selectorFamily<T, P extends SerializableParam>(
options: ReadOnlySelectorFamilyOptions<T, P>
): (param: P) => RecoilValueReadOnly<T>;Utilities for coordinating multiple async operations and handling loading states.
function noWait<T>(state: RecoilValue<T>): RecoilValueReadOnly<Loadable<T>>;
function waitForAll<T extends Array<RecoilValue<any>>>(
param: T
): RecoilValueReadOnly<UnwrapRecoilValues<T>>;
function waitForNone<T extends Array<RecoilValue<any>>>(
param: T
): RecoilValueReadOnly<UnwrapRecoilValueLoadables<T>>;Powerful hooks for complex operations including callbacks, transactions, and state introspection.
function useRecoilCallback<Args extends ReadonlyArray<unknown>, Return>(
fn: (interface: CallbackInterface) => (...args: Args) => Return,
deps?: ReadonlyArray<unknown>
): (...args: Args) => Return;
function useRecoilSnapshot(): Snapshot;
function useGotoRecoilSnapshot(): (snapshot: Snapshot) => void;System for handling async state with loading, error, and success states.
type Loadable<T> = ValueLoadable<T> | LoadingLoadable<T> | ErrorLoadable<T>;
interface ValueLoadable<T> {
state: 'hasValue';
contents: T;
getValue(): T;
valueOrThrow(): T;
}
namespace RecoilLoadable {
function of<T>(x: T | Promise<T> | Loadable<T>): Loadable<T>;
function error(x: any): ErrorLoadable<any>;
function loading(): LoadingLoadable<any>;
}Tools for managing memory usage and preventing unwanted garbage collection of state.
function useRetain(
toRetain: RecoilValue<any> | RetentionZone | Array<RecoilValue<any> | RetentionZone>
): void;
function retentionZone(): RetentionZone;// Base types
type NodeKey = string;
type SerializableParam =
| undefined | null | boolean | number | symbol | string
| ReadonlyArray<SerializableParam>
| ReadonlySet<SerializableParam>
| Readonly<{[key: string]: SerializableParam}>;
// ID types
interface StoreID {
readonly [StoreID_OPAQUE]: true;
}
interface SnapshotID {
readonly [SnapshotID_OPAQUE]: true;
}
// Snapshot types
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;
}
class MutableSnapshot extends Snapshot {
set: SetRecoilState;
reset: ResetRecoilState;
}
// State info for debugging
interface RecoilStateInfo<T> {
loadable?: Loadable<T>;
isActive: boolean;
isSet: boolean;
isModified: boolean;
type: 'atom' | 'selector';
deps: Iterable<RecoilValue<T>>;
subscribers: {
nodes: Iterable<RecoilValue<T>>;
components: Iterable<ComponentInfo>;
};
}
interface ComponentInfo {
name: string;
}
// State types
class RecoilState<T> {
key: NodeKey;
toJSON(): {key: string};
}
class RecoilValueReadOnly<T> {
key: NodeKey;
toJSON(): {key: string};
}
type RecoilValue<T> = RecoilValueReadOnly<T> | RecoilState<T>;
// Special values
class DefaultValue {
private __tag: 'DefaultValue';
}
interface WrappedValue<T> {
readonly [WrappedValue_OPAQUE]: true;
}
// Function types
type SetterOrUpdater<T> = (valOrUpdater: ((currVal: T) => T) | T) => void;
type GetRecoilValue = <T>(recoilVal: RecoilValue<T>) => T;
type SetRecoilState = <T>(
recoilVal: RecoilState<T>,
newVal: T | DefaultValue | ((prevValue: T) => T | DefaultValue)
) => void;
type ResetRecoilState = (recoilVal: RecoilState<any>) => void;
type GetCallback = <Args extends ReadonlyArray<unknown>, Return>(
fn: (interface: SelectorCallbackInterface) => (...args: Args) => Return
) => (...args: Args) => Return;
// Selector callback interface
interface SelectorCallbackInterface extends CallbackInterface {
node: RecoilState<unknown>;
}
// Utility function
function isRecoilValue(val: unknown): val is RecoilValue<any>;