Dev Tools

Recoil has functionality to allow you to observe and update state changes.


IMPORTANT NOTE

This API is currently under development and will change. Please stay tuned...


Observing All State Changes

You can use a hook such as useRecoilSnapshot() or useRecoilTransactionObserver_UNSTABLE() to subscribe to state changes and obtain a Snapshot of the new state.

Once you have a Snapshot, you can use methods such as getLoadable(), getPromise(), and getInfo() to inspect the state and use getNodes() to iterate over the set of known atoms.

function DebugObserver(): React.Node {
const snapshot = useRecoilSnapshot();
useEffect(() => {
console.debug('The following atoms were modified:');
for (const node of snapshot.getNodes({modified: true})) {
console.debug(node.key, snapshot.getLoadable(node));
}
}, [snapshot]);
return null;
}
function MyApp() {
return (
<RecoilRoot>
<DebugObserver />
...
</RecoilRoot>
);
}

Observing State Changes On-Demand

Or, you can use the useRecoilCallback() hook to obtain a Snapshot on-demand.

function DebugButton(): React.Node {
const onClick = useRecoilCallback(({snapshot}) => async () => {
console.debug('Atom values:');
for (const node of snapshot.getNodes()) {
const value = await snapshot.getPromise(node);
console.debug(node.key, value);
}
}, []);
return <button onClick={onClick}>Dump State</button>
}

Time Travel

The useGotoRecoilSnapshot() hook can be used to update the entire Recoil state to match the provided Snapshot. This example maintains a history of state changes with the ability to go back and restore previous global state.

Snapshot's also provide a getID() method. That can be used, for example, to help determine if you are reverting to a previous known state to avoid updating your snapshot history.

function TimeTravelObserver() {
const [snapshots, setSnapshots] = useState([]);
const snapshot = useRecoilSnapshot();
useEffect(() => {
if (snapshots.every(s => s.getID() !== snapshot.getID())) {
setSnapshots([...snapshots, snapshot]);
}
}, [snapshot]);
const gotoSnapshot = useGotoRecoilSnapshot();
return (
<ol>
{snapshots.map((snapshot, i) => (
<li key={i}>
Snapshot {i}
<button onClick={() => gotoSnapshot(snapshot)}>
Restore
</button>
</li>
))}
</ol>
);
}