Recoil is an experimental state management framework for React applications that provides atoms and selectors for fine-grained reactivity.
—
Essential React hooks for reading and writing Recoil state with automatic subscriptions. These hooks form the primary interface between React components and Recoil state.
Hooks for reading atom and selector values with automatic component subscriptions.
/**
* Returns the value of an atom or selector (readonly or writeable) and
* subscribes the components to future updates of that state.
*/
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.
*/
function useRecoilValueLoadable<T>(recoilValue: RecoilValue<T>): Loadable<T>;Usage Examples:
import React from 'react';
import { useRecoilValue, useRecoilValueLoadable } from 'recoil';
// Reading synchronous state
function UserName() {
const userName = useRecoilValue(userNameState);
return <div>Hello, {userName}!</div>;
}
// Reading async state with loadable
function AsyncUserProfile() {
const userProfileLoadable = useRecoilValueLoadable(userProfileState);
switch (userProfileLoadable.state) {
case 'hasValue':
return <div>Profile: {userProfileLoadable.contents.name}</div>;
case 'loading':
return <div>Loading profile...</div>;
case 'hasError':
return <div>Error: {userProfileLoadable.contents.message}</div>;
}
}Hooks that provide both the value and setter for writeable Recoil state.
/**
* 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.
*/
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.
*/
function useRecoilStateLoadable<T>(recoilState: RecoilState<T>): [Loadable<T>, SetterOrUpdater<T>];
type SetterOrUpdater<T> = (valOrUpdater: ((currVal: T) => T) | T) => void;Usage Examples:
import React from 'react';
import { useRecoilState, useRecoilStateLoadable } from 'recoil';
// Basic state management
function Counter() {
const [count, setCount] = useRecoilState(countState);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(c => c - 1)}>Decrement</button>
</div>
);
}
// Form input with state
function NameInput() {
const [name, setName] = useRecoilState(nameState);
return (
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Enter your name"
/>
);
}
// Async state with loadable
function AsyncDataEditor() {
const [dataLoadable, setData] = useRecoilStateLoadable(asyncDataState);
const handleSave = (newData) => {
setData(newData); // This will trigger async update
};
if (dataLoadable.state === 'loading') {
return <div>Loading...</div>;
}
if (dataLoadable.state === 'hasError') {
return <div>Error loading data</div>;
}
return (
<div>
<DataEditor
data={dataLoadable.contents}
onSave={handleSave}
/>
</div>
);
}Hooks for updating state without subscribing to value changes.
/**
* Returns a setter function for updating Recoil state. Does not subscribe
* the component to the given state.
*/
function useSetRecoilState<T>(recoilState: RecoilState<T>): SetterOrUpdater<T>;
/**
* Returns a function that will reset the given state to its default value.
*/
function useResetRecoilState(recoilState: RecoilState<any>): () => void;Usage Examples:
import React from 'react';
import { useSetRecoilState, useResetRecoilState } from 'recoil';
// Component that only updates state (no subscription)
function ActionButtons() {
const setCount = useSetRecoilState(countState);
const resetUser = useResetRecoilState(userState);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>
Increment Counter
</button>
<button onClick={resetUser}>
Reset User
</button>
</div>
);
}
// Event handler that updates multiple states
function useDataActions() {
const setLoading = useSetRecoilState(loadingState);
const setError = useSetRecoilState(errorState);
const setData = useSetRecoilState(dataState);
const loadData = async () => {
setLoading(true);
setError(null);
try {
const response = await fetch('/api/data');
const data = await response.json();
setData(data);
} catch (error) {
setError(error.message);
} finally {
setLoading(false);
}
};
return { loadData };
}Hooks with React Concurrent Mode transition support for performance optimization.
/**
* Experimental version of useRecoilValue with useTransition() support
*/
function useRecoilValue_TRANSITION_SUPPORT_UNSTABLE<T>(recoilValue: RecoilValue<T>): T;
/**
* Experimental version of useRecoilValueLoadable with useTransition() support
*/
function useRecoilValueLoadable_TRANSITION_SUPPORT_UNSTABLE<T>(recoilValue: RecoilValue<T>): Loadable<T>;
/**
* Experimental version of useRecoilState with useTransition() support
*/
function useRecoilState_TRANSITION_SUPPORT_UNSTABLE<T>(recoilState: RecoilState<T>): [T, SetterOrUpdater<T>];Usage Examples:
import React, { useTransition } from 'react';
import { useRecoilValue_TRANSITION_SUPPORT_UNSTABLE } from 'recoil';
// Component using transition-compatible hooks
function SearchResults() {
const [isPending, startTransition] = useTransition();
const searchResults = useRecoilValue_TRANSITION_SUPPORT_UNSTABLE(searchResultsState);
const handleSearch = (query) => {
startTransition(() => {
// This update will be marked as a transition
setSearchQuery(query);
});
};
return (
<div>
{isPending ? <div>Searching...</div> : null}
<SearchResultsList results={searchResults} />
</div>
);
}Debugging hook for inspecting state metadata and dependencies.
/**
* Returns current info about an atom or selector
*/
function useGetRecoilValueInfo_UNSTABLE(): <T>(recoilValue: RecoilValue<T>) => RecoilStateInfo<T>;
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;
}Usage Examples:
import React from 'react';
import { useGetRecoilValueInfo_UNSTABLE } from 'recoil';
// Debug component for inspecting state
function StateDebugger({ recoilValue }) {
const getRecoilValueInfo = useGetRecoilValueInfo_UNSTABLE();
const info = getRecoilValueInfo(recoilValue);
return (
<div>
<h3>State Info</h3>
<p>Type: {info.type}</p>
<p>Is Active: {info.isActive.toString()}</p>
<p>Is Set: {info.isSet.toString()}</p>
<p>Is Modified: {info.isModified.toString()}</p>
<p>Dependencies: {Array.from(info.deps).length}</p>
<p>Component Subscribers: {Array.from(info.subscribers.components).length}</p>
</div>
);
}Hook for manually clearing selector caches to force reevaluation.
/**
* Clears the cache for a selector causing it to be reevaluated
*/
function useRecoilRefresher_UNSTABLE(recoilValue: RecoilValue<any>): () => void;Usage Examples:
import React from 'react';
import { useRecoilRefresher_UNSTABLE } from 'recoil';
// Component with manual refresh capability
function DataDisplay() {
const data = useRecoilValue(asyncDataState);
const refreshData = useRecoilRefresher_UNSTABLE(asyncDataState);
return (
<div>
<div>Data: {JSON.stringify(data)}</div>
<button onClick={refreshData}>
Refresh Data
</button>
</div>
);
}Install with Tessl CLI
npx tessl i tessl/npm-recoil