Skip to content
Back to skills

Atoms

ASecurity

How to create atoms and atomCollections in React and use their per-instance hooks (`useValue`, `useState`, `use`, `useWatch`, `Provider`) and custom actions.

  • 9 stars
  • 0 votes
  • 0 copies
  • 7 views
  • Added May 28, 2026
developmentreacttestingapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 30, 2026

npx -y skills add hassanzohdy/mongez-react-atom --skill atoms --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Atoms?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Atoms
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/hassanzohdy-atoms/badge)](https://www.skillsdirectory.com/skills/hassanzohdy-atoms)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: mongez-react-atom-atoms
description: |
  How to create atoms and atomCollections in React and use their per-instance hooks (`useValue`, `useState`, `use`, `useWatch`, `Provider`) and custom actions.
---
# Atoms in React

## Factory

```ts
import { atom, atomCollection } from "@mongez/react-atom";

const counterAtom = atom({ key: "counter", default: 0 });
const todosAtom   = atomCollection<Todo>({ key: "todos", default: [] });
```

> **Naming convention**: suffix atom variables with `Atom` (e.g. `counterAtom`, `userAtom`). This prevents name collisions with local variables and plain values, and makes it immediately clear at the call site that you're working with a reactive atom.

`atom(...)` is the React-aware version of `createAtom` from `@mongez/atom`. The returned atom carries all the base methods plus the React hooks below.

## The hooks every atom carries

### `useValue()`

Subscribes to changes; returns the current value. Re-renders when the value changes.

```tsx
function Greeting() {
  const user = userAtom.useValue();
  return <h1>Hello {user.name}</h1>;
}
```

### `useState()` — available but not recommended

Returns `[value, setValue]` — same shape as React's `useState`, but the value lives in the atom.

```tsx
function Counter() {
  const [count, setCount] = counterAtom.useState();
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
```

The setter accepts an updater function: `setCount(prev => prev + 1)`.

**Prefer `useValue()` + calling the atom's methods directly** — it keeps updates explicit and traceable:

```tsx
// ✅ preferred
function Counter() {
  const count = counterAtom.useValue();
  return <button onClick={() => counterAtom.update(count + 1)}>{count}</button>;
}

// Or better — give the increment semantic meaning via an action:
const counterAtom = atom({
  key: "counter",
  default: 0,
  actions: { increment() { this.update(this.value + 1); } },
});

function Counter() {
  const count = counterAtom.useValue();
  return <button onClick={() => counterAtom.increment()}>{count}</button>;
}
```

### `use(key)`

For object atoms: subscribes to ONE key only. Re-renders only when THAT key changes — sibling keys in the same atom don't wake this component.

```tsx
function NameOnly() {
  const name = userAtom.use("name");
  return <span>{name}</span>;
}
// Even if userAtom.merge({ age: 31 }), this component doesn't re-render.
```

### `useWatch(key, callback)`

Effect-style watcher. Use when you want a side effect (analytics, logging) without re-rendering. `useWatch` is itself a hook — call it at the top of your component, NOT inside a `useEffect`.

```tsx
function NameTracker() {
  userAtom.useWatch("name", (next, prev) =>
    analytics.track("name_changed", { from: prev, to: next }),
  );
  return null;
}
```

### `Provider`

A React component that sets the atom's value on mount and updates it when `value` prop changes.

```tsx
<userAtom.Provider value={initialUser}>
  <App />
</userAtom.Provider>
```

Useful for testing (inject a known value into the subtree) and for "set on mount" patterns.

## Custom actions in React atoms

Action methods declared in the factory still work — they're bound to the atom instance, available globally.

```ts
const auth = atom<AuthState, { login: (creds: Creds) => Promise<void> }>({
  key: "auth",
  default: { user: null },
  actions: {
    async login(creds) {
      const user = await api.login(creds);
      this.merge({ user });
    },
  },
});

// Anywhere:
await auth.login({ email, password });

// In components:
const user = auth.use("user");
```

## With store scoping (SSR)

```tsx
function Component() {
  // `useAtom(template)` resolves to the active store's scoped clone.
  // Without a provider, it returns the template itself in a browser (singleton mode); on a server it throws.
  const scoped = useAtom(userAtom);
  const value = scoped.useValue();   // tear-free read
  return <span>{value.name}</span>;
}
```

The per-atom hooks (`useValue`, `useState`, `use`, `useWatch`) ALREADY do this resolution internally — you don't need to call `useAtom(template)` explicitly unless you're invoking action methods on the scoped clone from an event handler. See [`../ssr/SKILL.md`](../ssr/SKILL.md).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.