Token导航 LogoToken导航TokenDH.com
前端设计操作浏览器github未标认证来源可访问clear审计通过

atom-state原子态

Agent Skill

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

总安装

192

周安装

8

GitHub Stars

17

下载量

64
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:atom-state(原子态)
来源仓库:https://github.com/front-depiction/claude-setup
仓库路径:skills/atom-state
安装命令:
npx skills add https://github.com/front-depiction/claude-setup --skill atom-state
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/front-depiction/claude-setup --skill atom-state

简介

atom-state 是 Effect 生态的反应式状态管理库,专为 React 设计,以原子引用实现细粒度更新。

  • 适用于需要局部状态共享、自动清理与响应式 UI 更新的前端项目。
  • 原子自动重置无订阅状态,支持 keepAlive 标记持久化关键数据。
  • 使用前应确认项目已接入 Effect 运行时,并理解其副作用管理机制。
  • atom-state 属于前端设计类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Effect Atom State Management

Effect Atom is a reactive state management library for Effect that seamlessly integrates with React.

Core Concepts

Atoms as References

Atoms work by reference - they are stable containers for reactive state:

import * as Atom from "@effect-atom/atom-react"

// Atoms are created once and referenced throughout the app
export const counterAtom = Atom.make(0)

// Multiple components can reference the same atom
// All update when the atom value changes

Automatic Cleanup

Atoms automatically reset when no subscribers remain (unless marked with keepAlive):

// Resets when last subscriber unmounts
export const temporaryState = Atom.make(initialValue)

// Persists across component lifecycles
export const persistentState = Atom.make(initialValue).pipe(Atom.keepAlive)

Lazy Evaluation

Atom values are computed on-demand when subscribers access them.

Pattern: Basic Atoms

import * as Atom from "@effect-atom/atom-react"

// Simple atom
export const count = Atom.make(0)

// Atom with object state
export interface CartState {
  readonly items: ReadonlyArray<Item>
  readonly total: number
}

export const cart = Atom.make<CartState>({
  items: [],
  total: 0
})

Pattern: Derived Atoms

Use Atom.map or computed atoms with the get parameter:

// Derived via map
export const itemCount = Atom.map(cart, (c) => c.items.length)
export const isEmpty = Atom.map(cart, (c) => c.items.length === 0)

// Computed atom accessing other atoms
export const cartSummary = Atom.make((get) => {
  const cartData = get(cart)
  const count = get(itemCount)

  return {
    itemCount: count,
    total: cartData.total,
    isEmpty: count === 0
  }
})

Pattern: Atom Family (Dynamic Atoms)

Use Atom.family for stable references to dynamically created atoms:

// Create atoms per entity ID
export const userAtoms = Atom.family((userId: string) =>
  Atom.make<User | null>(null).pipe(Atom.keepAlive)
)

// Usage - always returns the same atom for a given ID
const userAtom = userAtoms(userId)

Pattern: Atom.fn for Async Actions

Use Atom.fn with Effect.fnUntraced for async operations:

  • Reading gives Result<Success, Error> with automatic .waiting flag
  • Triggering via useAtomSet runs the effect
import { Atom, useAtomValue, useAtomSet } from "@effect-atom/atom-react"
import { Effect, Exit } from "effect"

// Atom.fn with Effect.fnUntraced for generator syntax
const logAtom = Atom.fn(
  Effect.fnUntraced(function* (arg: number) {
    yield* Effect.log("got arg", arg)
  })
)

function LogComponent() {
  // useAtomSet returns a trigger function
  const logNumber = useAtomSet(logAtom)
  return <button onClick={() => logNumber(42)}>Log 42</button>
}

With services using Atom.runtime:

class Users extends Effect.Service<Users>()("app/Users", {
  effect: Effect.gen(function* () {
    const create = (name: string) => Effect.succeed({ id: 1, name })
    return { create } as const
  }),
}) {}

const runtimeAtom = Atom.runtime(Users.Default)

// runtimeAtom.fn provides service access
const createUserAtom = runtimeAtom.fn(
  Effect.fnUntraced(function* (name: string) {
    const users = yield* Users
    return yield* users.create(name)
  })
)

function CreateUserComponent() {
  // mode: "promiseExit" for async handlers with Exit result
  const createUser = useAtomSet(createUserAtom, { mode: "promiseExit" })
  return (
    <button onClick={async () => {
      const exit = await createUser("John")
      if (Exit.isSuccess(exit)) {
        console.log(exit.value)
      }
    }}>
      Create user
    </button>
  )
}

Reading result state:

function UserList() {
  const [result, createUser] = useAtom(createUserAtom)  // Result<User, Error>

  // Use matchWithWaiting for proper waiting state handling
  return Result.matchWithWaiting(result, {
    onWaiting: () => <Spinner />,
    onSuccess: ({ value }) => <UserCard user={value} />,
    onError: (error) => <Error message={String(error)} />,
    onDefect: (defect) => <Error message={String(defect)} />
  })
}

Anti-pattern: Manual void wrappers

// ❌ DON'T - manual state management loses waiting control
const loading$ = Atom.make(false)
const user$ = Atom.make<User | null>(null)

const fetchUser = (id: string): void => {
  registry.set(loading$, true)
  Effect.runPromise(userService.getById(id)).then(user => {
    registry.set(user$, user)
    registry.set(loading$, false)
  })
}

// ✅ DO - Atom.fn handles loading/success/failure automatically
const fetchUserAtom = Atom.fn(
  Effect.fnUntraced(function* (id: string) {
    return yield* userService.getById(id)
  })
)
// result.waiting, Result.match - all built-in

Pattern: Runtime with Services

Wrap Effect layers/services for use in atoms:

import { Layer } from "effect"

// Create runtime with services
export const runtime = Atom.runtime(
  Layer.mergeAll(
    DatabaseService.Live,
    LoggerService.Live,
    ApiClient.Live
  )
)

// Use services in function atoms
export const fetchUserData = runtime.fn(
  Effect.fnUntraced(function* (userId: string) {
    const db = yield* DatabaseService
    const user = yield* db.getUser(userId)

    yield* Atom.set(userAtoms(userId), user)
    return user
  })
)

Global Layers

Configure global layers once at app initialization:

// App setup
Atom.runtime.addGlobalLayer(
  Layer.mergeAll(
    Logger.Live,
    Tracer.Live,
    Config.Live
  )
)

Pattern: Result Types (Error Handling)

Atoms can return Result types for explicit error handling:

import * as Result from "@effect-atom/atom/Result"

export const userData = Atom.make<Result.Result<User, Error>>(
  Result.initial()
)

// In component - use matchWithWaiting for proper waiting state
const result = useAtomValue(userData)

Result.matchWithWaiting(result, {
  onWaiting: () => <Loading />,
  onSuccess: ({ value }) => <UserProfile user={value} />,
  onError: (error) => <Error message={String(error)} />,
  onDefect: (defect) => <Error message={String(defect)} />
})

Pattern: Stream Integration

Convert streams into atoms that capture the latest value:

import { Stream } from "effect"

// Infinite stream becomes reactive atom
export const notifications = Atom.make(
  Stream.fromEventListener(window, "notification").pipe(
    Stream.map(parseNotification),
    Stream.filter(isValid),
    Stream.scan([], (acc, n) => [...acc, n].slice(-10))
  )
)

Pattern: Pull Atoms (Pagination)

Use Atom.pull for stream-based pagination:

export const pagedItems = Atom.pull(
  Stream.fromIterable(itemsSource).pipe(
    Stream.grouped(10) // Pages of 10 items
  )
)

// In component - automatically fetches next page when called
const loadMore = useAtomSet(pagedItems)

Pattern: Persistence

Use Atom.kvs for persisted state:

import { BrowserKeyValueStore } from "@effect/platform-browser"
import * as Schema from "effect/Schema"

export const userSettings = Atom.kvs({
  runtime: Atom.runtime(BrowserKeyValueStore.layerLocalStorage),
  key: "user-settings",
  schema: Schema.Struct({
    theme: Schema.Literal("light", "dark"),
    notifications: Schema.Boolean,
    language: Schema.String
  }),
  defaultValue: () => ({
    theme: "light",
    notifications: true,
    language: "en"
  })
})

React Integration

Hooks

import { useAtomValue, useAtomSet, useAtom, useAtomSetPromise } from "@effect-atom/atom-react"

export function CartView() {
  // Read only
  const cartData = useAtomValue(cart)
  const isEmpty = useAtomValue(isEmpty)

  // Write only
  const addItem = useAtomSet(addItem)
  const clearCart = useAtomSet(clearCart)

  // Both read and write
  const [count, setCount] = useAtom(counterAtom)

  // For async function atoms
  const fetchData = useAtomSetPromise(fetchUserData)

  return (
    <div>
      <div>Items: {cartData.items.length}</div>
      <button onClick={() => addItem(newItem)}>Add</button>
      <button onClick={() => clearCart()}>Clear</button>
    </div>
  )
}

Separation of Concerns

Different components can read/write the same atom reactively:

// Component A - reads state
function CartDisplay() {
  const cart = useAtomValue(cart)
  return <div>Items: {cart.items.length}</div>
}

// Component B - modifies state
function CartActions() {
  const addItem = useAtomSet(addItem)
  return <button onClick={() => addItem(item)}>Add</button>
}

// Both update reactively when atom changes

Scoped Resources & Finalizers

Atoms support scoped effects with automatic cleanup:

export const wsConnection = Atom.make(
  Effect.gen(function* () {
    // Acquire resource
    const ws = yield* Effect.acquireRelease(
      connectWebSocket(),
      (ws) => Effect.sync(() => ws.close())
    )

    return ws
  })
)

// Finalizer runs when atom rebuilds or becomes unused

Key Principles

  1. Atom.fn for Async: Use Atom.fn() for effects—gives automatic waiting flag and Result type
  2. Never Manual Void Wrappers: Don't wrap Effects in void functions—you lose waiting control
  3. Reference Stability: Use Atom.family for dynamically generated atom sets
  4. Lazy Evaluation: Values computed on-demand when accessed
  5. Automatic Cleanup: Atoms reset when unused (unless keepAlive)
  6. Derive, Don't Coordinate: Use computed atoms to derive state
  7. Result Types: Handle errors explicitly with Result.match
  8. Services in Runtime: Wrap layers once, use in multiple atoms
  9. Immutable Updates: Always create new values, never mutate
  10. Scoped Effects: Leverage finalizers for resource cleanup

Common Patterns

Loading States

Use Atom.fn with Effect.fnUntraced which automatically provides Result with .waiting flag:

import { Atom, useAtomValue, useAtomSet } from "@effect-atom/atom-react"
import { Effect } from "effect"

// Atom.fn handles loading/success/failure automatically
const loadUserAtom = Atom.fn(
  Effect.fnUntraced(function* (id: string) {
    return yield* userService.fetchUser(id)
  })
)

// In component
function UserProfile() {
  const [result, loadUser] = useAtom(loadUserAtom)

  // Use matchWithWaiting for proper waiting state handling
  return Result.matchWithWaiting(result, {
    onWaiting: () => <Loading />,
    onSuccess: ({ value }) => <UserCard user={value} />,
    onError: (error) => <Error message={String(error)} />,
    onDefect: (defect) => <Error message={String(defect)} />
  })
}

Optimistic Updates

export const updateItem = runtime.fn(
  Effect.fnUntraced(function* (id: string, updates: Partial<Item>) {
    const current = yield* Atom.get(itemsAtom)

    // Optimistic update
    yield* Atom.set(
      itemsAtom,
      current.map(item => item.id === id ? { ...item, ...updates } : item)
    )

    // Persist to server
    const result = yield* Effect.either(api.updateItem(id, updates))

    // Revert on failure
    if (result._tag === "Left") {
      yield* Atom.set(itemsAtom, current)
    }
  })
)

Computed Queries

// Filter atom accessing other atoms
export const filteredItems = Atom.make((get) => {
  const items = get(itemsAtom)
  const searchTerm = get(searchAtom)
  const activeFilters = get(filtersAtom)

  return items.filter(item =>
    item.name.includes(searchTerm) &&
    activeFilters.every(f => f.predicate(item))
  )
})

Effect Atom bridges Effect's powerful type system with React's rendering model, providing type-safe reactive state management with automatic cleanup and seamless Effect integration.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

30.17%
按下载量换算19

windsurf

22.81%
按下载量换算15

trae

15.16%
按下载量换算10

OpenCode

13.12%
按下载量换算8

Codex

6.62%
按下载量换算4

Antigravity

3.4%
按下载量换算2

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

操作浏览器

该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills