[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-3717":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":22,"archived":23,"fork":23,"defaultBranch":24,"hasWiki":25,"hasPages":23,"topics":26,"createdAt":10,"pushedAt":10,"updatedAt":32,"readmeContent":33,"aiSummary":34,"trendingCount":16,"starSnapshotCount":16,"syncStatus":17,"lastSyncTime":35,"discoverSource":36},3717,"jotai","pmndrs\u002Fjotai","pmndrs","👻 Primitive and flexible state management for React","https:\u002F\u002Fjotai.org",null,"TypeScript",21193,718,67,1,0,2,10,47,8,43.57,"MIT License",false,"main",true,[27,28,29,30,31],"atomic","hacktoberfest","management","react","state","2026-06-12 02:00:53","\u003Cbr>\n\n![Jotai (light mode)](.\u002Fimg\u002Fjotai-header-light.png#gh-light-mode-only)\n![Jotai (dark mode)](.\u002Fimg\u002Fjotai-header-dark.png#gh-dark-mode-only)\n\n\u003Cbr>\n\nvisit [jotai.org](https:\u002F\u002Fjotai.org) or `npm i jotai`\n\n[![Build Status](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Factions\u002Fworkflow\u002Fstatus\u002Fpmndrs\u002Fjotai\u002Ftest.yml?branch=main&style=flat&colorA=000000&colorB=000000)](https:\u002F\u002Fgithub.com\u002Fpmndrs\u002Fjotai\u002Factions\u002Fworkflows\u002Ftest.yml?query=branch%3Amain)\n[![Build Size](https:\u002F\u002Fimg.shields.io\u002Fbundlephobia\u002Fminzip\u002Fjotai?label=bundle%20size&style=flat&colorA=000000&colorB=000000)](https:\u002F\u002Fbundlephobia.com\u002Fresult?p=jotai)\n[![Version](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002Fjotai?style=flat&colorA=000000&colorB=000000)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fjotai)\n[![Downloads](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fdt\u002Fjotai.svg?style=flat&colorA=000000&colorB=000000)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fjotai)\n[![Discord Shield](https:\u002F\u002Fimg.shields.io\u002Fdiscord\u002F740090768164651008?style=flat&colorA=000000&colorB=000000&label=discord&logo=discord&logoColor=ffffff)](https:\u002F\u002Fdiscord.gg\u002Fpoimandres)\n[![Open Collective](https:\u002F\u002Fimg.shields.io\u002Fopencollective\u002Fall\u002Fjotai?style=flat&colorA=000000&colorB=000000)](https:\u002F\u002Fopencollective.com\u002Fjotai)\n\nJotai scales from a simple useState replacement to an enterprise TypeScript application.\n\n- Minimal core API (2kb)\n- Many utilities and extensions\n- No string keys (compared to Recoil)\n\nExamples: [Demo 1](https:\u002F\u002Fcodesandbox.io\u002Fs\u002Fjotai-demo-47wvh) |\n[Demo 2](https:\u002F\u002Fcodesandbox.io\u002Fs\u002Fjotai-demo-forked-x2g5d)\n\n### First, create a primitive atom\n\nAn atom represents a piece of state. All you need is to specify an initial\nvalue, which can be primitive values like strings and numbers, objects, and\narrays. You can create as many primitive atoms as you want.\n\n```jsx\nimport { atom } from 'jotai'\n\nconst countAtom = atom(0)\nconst countryAtom = atom('Japan')\nconst citiesAtom = atom(['Tokyo', 'Kyoto', 'Osaka'])\nconst mangaAtom = atom({ 'Dragon Ball': 1984, 'One Piece': 1997, Naruto: 1999 })\n```\n\n### Use the atom in your components\n\nIt can be used like `React.useState`:\n\n```jsx\nimport { useAtom } from 'jotai'\n\nfunction Counter() {\n  const [count, setCount] = useAtom(countAtom)\n  return (\n    \u003Ch1>\n      {count}\n      \u003Cbutton onClick={() => setCount((c) => c + 1)}>one up\u003C\u002Fbutton>\n      ...\n```\n\n### Create derived atoms with computed values\n\nA new read-only atom can be created from existing atoms by passing a read\nfunction as the first argument. `get` allows you to fetch the contextual value\nof any atom.\n\n```jsx\nconst doubledCountAtom = atom((get) => get(countAtom) * 2)\n\nfunction DoubleCounter() {\n  const [doubledCount] = useAtom(doubledCountAtom)\n  return \u003Ch2>{doubledCount}\u003C\u002Fh2>\n}\n```\n\n### Creating an atom from multiple atoms\n\nYou can combine multiple atoms to create a derived atom.\n\n```jsx\nconst count1 = atom(1)\nconst count2 = atom(2)\nconst count3 = atom(3)\n\nconst sum = atom((get) => get(count1) + get(count2) + get(count3))\n```\n\nOr if you like fp patterns ...\n\n```jsx\nconst atoms = [count1, count2, count3, ...otherAtoms]\nconst sum = atom((get) => atoms.map(get).reduce((acc, count) => acc + count))\n```\n\n### Derived async atoms [\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002F-needs_suspense-black\" alt=\"needs suspense\" \u002F>](https:\u002F\u002Freact.dev\u002Freference\u002Freact\u002FSuspense)\n\nYou can make the read function an async function too.\n\n```jsx\nconst urlAtom = atom('https:\u002F\u002Fjson.host.com')\nconst fetchUrlAtom = atom(async (get) => {\n  const response = await fetch(get(urlAtom))\n  return await response.json()\n})\n\nfunction Status() {\n  \u002F\u002F Re-renders the component after urlAtom is changed and the async function above concludes\n  const [json] = useAtom(fetchUrlAtom)\n  ...\n```\n\n### You can create a writable derived atom\n\nSpecify a write function at the second argument. `get` will return the current\nvalue of an atom. `set` will update the value of an atom.\n\n```jsx\nconst decrementCountAtom = atom(\n  (get) => get(countAtom),\n  (get, set, _arg) => set(countAtom, get(countAtom) - 1)\n)\n\nfunction Counter() {\n  const [count, decrement] = useAtom(decrementCountAtom)\n  return (\n    \u003Ch1>\n      {count}\n      \u003Cbutton onClick={decrement}>Decrease\u003C\u002Fbutton>\n      ...\n```\n\n### Write only derived atoms\n\nJust do not define a read function.\n\n```jsx\nconst multiplyCountAtom = atom(null, (get, set, by) =>\n  set(countAtom, get(countAtom) * by),\n)\n\nfunction Controls() {\n  const [, multiply] = useAtom(multiplyCountAtom)\n  return \u003Cbutton onClick={() => multiply(3)}>triple\u003C\u002Fbutton>\n}\n```\n\n### Async actions\n\nJust make the write function an async function and call `set` when you're ready.\n\n```jsx\nconst fetchCountAtom = atom(\n  (get) => get(countAtom),\n  async (_get, set, url) => {\n    const response = await fetch(url)\n    set(countAtom, (await response.json()).count)\n  }\n)\n\nfunction Controls() {\n  const [count, compute] = useAtom(fetchCountAtom)\n  return (\n    \u003Cbutton onClick={() => compute('http:\u002F\u002Fcount.host.com')}>compute\u003C\u002Fbutton>\n    ...\n```\n\n### Note about functional programming\n\nJotai's fluid interface is no accident — atoms are monads, just like promises!\nMonads are an [established](\u003Chttps:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FMonad_(functional_programming)>)\npattern for modular, pure, robust and understandable code which is [optimized for change](https:\u002F\u002Foverreacted.io\u002Foptimized-for-change\u002F).\nRead more about [Jotai and monads.](https:\u002F\u002Fjotai.org\u002Fdocs\u002Fbasics\u002Ffunctional-programming-and-jotai)\n\n## Links\n\n- [website](https:\u002F\u002Fjotai.org)\n- [documentation](https:\u002F\u002Fjotai.org\u002Fdocs)\n- [course](https:\u002F\u002Fegghead.io\u002Fcourses\u002Fmanage-application-state-with-jotai-atoms-2c3a29f0)\n","Jotai 是一个为 React 应用设计的轻量级且灵活的状态管理库。它提供了最小化的核心 API（仅 2KB），支持从简单的 useState 替换到复杂的企业级 TypeScript 应用。Jotai 的主要特点包括无字符串键值、丰富的工具和扩展，以及基于原子（atom）的状态管理方式，允许开发者轻松创建和组合状态。适用于需要高效、简洁状态管理方案的 React 项目，特别是在追求高性能和代码可维护性的场景下表现尤为出色。","2026-06-11 02:55:47","top_language"]