Pre-built atom shapes — `openAtom` (boolean toggle), `loadingAtom` (loading flag), `fetchingAtom` (full fetch lifecycle), and `portalAtom` (modal/drawer coordinator) — and when to reach for each. TRIGGER when: code imports or calls `openAtom`, `loadingAtom`, `fetchingAtom`, or `portalAtom` from `@mongez/react-atom`; code uses `useOpened`, `useLoading`, `useData`, `useError`, `usePagination`, `startLoading`, `stopLoading`, `toggleLoading`, `success`, `failed`, `append`, `prepend`, or `toggle` ...
Scanned 5/28/2026
Install via CLI
openskills install hassanzohdy/mongez-react-atom---
name: mongez-react-atom-presets
description: |
Pre-built atom shapes — `openAtom` (boolean toggle), `loadingAtom` (loading flag), `fetchingAtom` (full fetch lifecycle), and `portalAtom` (modal/drawer coordinator) — and when to reach for each.
TRIGGER when: code imports or calls `openAtom`, `loadingAtom`, `fetchingAtom`, or `portalAtom` from `@mongez/react-atom`; code uses `useOpened`, `useLoading`, `useData`, `useError`, `usePagination`, `startLoading`, `stopLoading`, `toggleLoading`, `success`, `failed`, `append`, `prepend`, or `toggle` methods on a preset atom; user asks "how do I make a toggle / open-close atom", "how do I model a loading flag", "how do I do a fetch lifecycle with isLoading/data/error", or "how do I coordinate a modal/drawer"; typical import `import { openAtom, portalAtom } from "@mongez/react-atom"`.
SKIP: hand-rolling a custom action atom from scratch — use `mongez-react-atom-atoms`; richer cache-keyed server state (invalidation, refetch on focus) belongs in `@mongez/atomic-query`, not `fetchingAtom`; SSR scoping/hydration of preset atoms still uses `mongez-react-atom-ssr`; end-to-end flow examples use `mongez-react-atom-recipes`.
---
# Preset atoms
Four pre-built atom shapes that collapse common patterns to one line.
## `openAtom`
A boolean-shaped toggle with `open`, `close`, `toggle`, and a `useOpened()` hook.
```ts
import { openAtom } from "@mongez/react-atom";
const sidebar = openAtom("sidebar", /* defaultOpened */ false);
// Anywhere:
sidebar.open();
sidebar.close();
sidebar.toggle();
// In components:
function Sidebar() {
const opened = sidebar.useOpened();
return opened ? <Drawer /> : null;
}
```
Equivalent to writing:
```ts
const sidebar = atom<boolean, { open(): void; close(): void; toggle(): void; useOpened(): boolean }>({
key: "sidebar",
default: false,
actions: {
open() { this.update(true); },
close() { this.update(false); },
toggle() { this.update(!this.value); },
useOpened() { return (this as any).useValue(); },
},
});
```
## `loadingAtom`
A boolean with `startLoading` / `stopLoading` / `toggleLoading` verbs.
```ts
import { loadingAtom } from "@mongez/react-atom";
const usersLoading = loadingAtom("usersLoading");
async function fetchUsers() {
usersLoading.startLoading();
try {
const users = await api.users.list();
setUsers(users);
} finally {
usersLoading.stopLoading();
}
}
```
## `fetchingAtom`
A full fetch lifecycle: `isLoading`, `data`, `error`, optional `pagination`. Comes with `startLoading`, `stopLoading`, `success(data, pagination?)`, `failed(error)`, `append(data)`, `prepend(data)`, plus hooks `useLoading()`, `useData()`, `useError()`, `usePagination()`.
```ts
import { fetchingAtom } from "@mongez/react-atom";
type User = { id: number; name: string };
const usersAtom = fetchingAtom<User[]>("users");
async function loadUsers() {
usersAtom.startLoading();
try {
const { data, pagination } = await api.users.list();
usersAtom.success(data, pagination);
} catch (err) {
usersAtom.failed(err);
}
}
function UsersList() {
const isLoading = usersAtom.useLoading();
const data = usersAtom.useData();
const error = usersAtom.useError();
if (isLoading) return <Spinner />;
if (error) return <ErrorBox e={error} />;
return <ul>{data?.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}
```
For richer cache management, prefer [`@mongez/atomic-query`](https://github.com/hassanzohdy/mongez-atomic-query). `fetchingAtom` is for one-off fetch flows; `queryAtom.useQuery` is for keyed cache.
## `portalAtom`
A coordinator atom for modals, drawers, tooltips, dropdowns. Holds `{ opened: boolean, data: T }` and exposes `open(data?)`, `close()`, `toggle(data?)`, `useOpened()`, `useData()`.
```ts
import { portalAtom } from "@mongez/react-atom";
type DeleteData = { userId: number; userName: string };
const deleteUserModal = portalAtom<DeleteData>("deleteUserModal");
// Anywhere:
deleteUserModal.open({ userId: 7, userName: "Alice" });
function ConfirmDeleteUser() {
const opened = deleteUserModal.useOpened();
const { userId, userName } = deleteUserModal.useData();
if (!opened) return null;
return (
<Dialog>
<p>Delete {userName}?</p>
<button onClick={() => deleteUserModal.close()}>Cancel</button>
<button onClick={async () => { await api.users.remove(userId); deleteUserModal.close(); }}>
Delete
</button>
</Dialog>
);
}
```
Each `portalAtom` key is suffixed with `-portal` internally, so `portalAtom("deleteUser")` creates an atom whose key is `deleteUser-portal`.
No comments yet. Be the first to comment!