Devtools
安装
将 jotai-devtools
安装到你的项目中以开始使用。
npm i jotai-devtools
注意事项
<DevTools/>
已优化为生产构建的 tree-shakable,仅在非生产环境中工作- Hooks 是仅开发者使用的,设计为在非生产环境中工作
- 欢迎反馈,如有问题请在 Jotai DevTools GitHub Repo 提出
快速链接
- UI Devtools
- Hooks
- 迁移指南
UI DevTools
使用基于 UI 的 Jotai DevTool 提升你的开发体验。
Babel 插件设置 - (可选但强烈推荐)
使用 Jotai babel 插件以获得最佳的调试体验。在 babel 页面和/或 swc 页面找到完整指南。
示例:
{"presets": [// 预设包含两个插件:// - jotai/babel/plugin-react-refresh 以启用 atoms 的热重载// - jotai/babel/plugin-debug-label 以自动向 atoms 添加调试标签'jotai/babel/preset']}
Vite + React 项目的示例:
// vite.config.tsexport default defineConfig({plugins: [react({babel: {presets: ['jotai/babel/preset'],},}),],})
Next JS 设置
如果你不使用 Next.js,你可以跳过这一部分。
启用 transpilePackages
以正确地转译 UI CSS 和组件。
// next.config.tsconst nextConfig = {// 在这里了解更多 - https://nextjs.org/docs/advanced-features/compiler#module-transpilation// 为了正确地转译 UI css,这是必需的 👇transpilePackages: ['jotai-devtools'],}module.exports = nextConfig
可用的 props
type DevToolsProps = {// 默认为 falseisInitialOpen?: boolean// 传递一个自定义的 storestore?: Store// 默认为 lighttheme?: 'dark' | 'light'// 设置触发按钮的位置// 默认为 `bottom-left`position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'// 自定义 nonce 以通过 CSP 允许 jotai-devtools 特定的内联样式nonce?: stringoptions?: {// 私有 atoms 在 atom creators(如 `atomWithStorage` 或 `atomWithLocation` 等)内部使用,以管理内部状态。// 默认为 `false`shouldShowPrivateAtoms?: boolean// 在 Atom Viewer 标签、Timeline 标签等的初始渲染上展开 JSON 树视图。// 默认为 `false`shouldExpandJsonTreeViewInitially?: boolean// 时间旅行回放的每一步之间的间隔(以毫秒为单位)。// 默认为 `750ms`timeTravelPlaybackInterval?: number// 在历史记录中保留的快照的最大数量。// 数字越大,消耗的内存就越多。// 默认为 `Infinity`。推荐:`~30`snapshotHistoryLimit?: number}}
使用
无 Provider
import { DevTools } from 'jotai-devtools'import 'jotai-devtools/styles.css'const App = () => {return (<><DevTools />{/* 你的应用 */}</>)}
有 Provider
import { createStore } from 'jotai'import { DevTools } from 'jotai-devtools'import 'jotai-devtools/styles.css'const customStore = createStore()const App = () => {return (<Provider store={customStore}><DevTools store={customStore} />{/* 你的应用 */}</Provider>)}
预览
useAtomsDebugValue
useAtomsDebugValue
是一个 React 钩子,它会在 React Devtools 中显示所有的 atom 值。
function useAtomsDebugValue(options?: {store?: Storeenabled?: boolean}): void
在内部,它使用 useDebugValue
,这只在 DEV 模式下有效。
它会捕获从钩子所在位置可以访问的所有 atoms。
示例
import { useAtomsDebugValue } from 'jotai-devtools/utils'const textAtom = atom('hello')textAtom.debugLabel = 'textAtom'const lenAtom = atom((get) => get(textAtom).length)lenAtom.debugLabel = 'lenAtom'const TextBox = () => {const [text, setText] = useAtom(textAtom)const [len] = useAtom(lenAtom)return (<span><input value={text} onChange={(e) => setText(e.target.value)} />({len})</span>)}const DebugAtoms = () => {useAtomsDebugValue()return null}const App = () => (<Provider><DebugAtoms /><TextBox /></Provider>)
useAtomDevtools
useAtomDevtools
是一个 React 钩子,它为特定的 atom 管理 ReduxDevTools 扩展。
function useAtomDevtools<Value>(anAtom: WritableAtom<Value, Value>,options?: {store?: Storename?: stringenabled?: boolean},): void
useAtomDevtools
钩子接受一个泛型类型参数(反映存储在 atom 中的类型)。此外,钩子接受两个调用参数,anAtom
和 name
。
anAtom
是将附加到 devtools 实例的 atom。name
是一个可选参数,定义 devtools 实例的调试标签。如果 name
未定义,将使用 atom.debugLabel
。
示例
import { useAtomDevtools } from 'jotai-devtools/utils'// 存储在 atom 中的类型的接口。export interface Task {label: stringcomplete: boolean}// 要调试的 atom。export const tasksAtom = atom<Task[]>([])// 如果 useAtomDevtools 的 name 参数未定义,将使用此值。tasksAtom.debugLabel = 'Tasks'export const useTasksDevtools = () => {// 只需传递一个用于调试的 atom 即可调用钩子。useAtomDevtools(tasksAtom)// 指定一个自定义类型参数useAtomDevtools<Task[]>(tasksAtom)// 你可以将两个 devtools 实例附加到同一个 atom,并使用自定义名称区分它们。useAtomDevtools(tasksAtom, 'Tasks (Instance 1)')useAtomDevtools(tasksAtom, 'Tasks (Instance 2)')}
useAtomsDevtools
⚠️ 注意:此钩子处于实验阶段(欢迎反馈),并且只在 process.env.NODE_ENV !== 'production'
环境中工作。
useAtomsDevtools
是 useAtomDevtools
的全捕获版本,它显示存储中的所有 atoms,而不是显示特定的一个。
function useAtomsDevtools(name: string,options?: {store?: Storeenabled?: boolean},): void
它需要一个 name
参数,用于命名 Redux devtools 实例,以及一个 store
参数。
作为此 API 的限制,我们需要将 useAtomsDevtools
放在一个组件中,该组件中消耗的 atoms 应位于 React 树的该组件(下面示例中的 AtomsDevtools
)下方。
AtomsDevtools
组件可以被视为我们应用的最佳实践。
示例
const countAtom = atom(0);const doubleCountAtom = atom((get) => get(countAtom) * 2);function Counter() {const [count, setCount] = useAtom(countAtom);const [doubleCount] = useAtom(doubleCountAtom);...}const AtomsDevtools = ({ children }) => {useAtomsDevtools('demo')return children}export default function App() {return (<AtomsDevtools><Counter /></AtomsDevtools>)}
useAtomsSnapshot
⚠️ 注意:此钩子只在 process.env.NODE_ENV !== 'production'
环境中工作。在生产环境中,它返回一个静态的空值。
useAtomsSnapshot
会对当前挂载的 atoms 及其状态进行快照。
function useAtomsSnapshot(options?: { store?: Store }): AtomsSnapshot
它接受一个 store
参数,并将返回一个 AtomsSnapshot
,基本上是一个 Map<AnyAtom, unknown>
。你可以使用 Map
API 来遍历 atoms 及其状态。
这个钩子主要用于调试和 devtools 的用例。
使用这个钩子时要小心,因为它会导致组件在所有状态变化时重新渲染。
示例
import { Provider } from 'jotai'import { useAtomsSnapshot } from 'jotai-devtools/utils'const RegisteredAtoms = () => {const atoms = useAtomsSnapshot()return (<div><p>Atom count: {atoms.size}</p><div>{Array.from(atoms).map(([atom, atomValue]) => (<p key={`${atom}`}>{`${atom.debugLabel}: ${atomValue}`}</p>))}</div></div>)}const App = () => (<Provider><RegisteredAtoms /></Provider>)
useGotoAtomsSnapshot
⚠️ 注意:此钩子只在 process.env.NODE_ENV !== 'production'
环境中工作。在生产环境中,它像一个空函数一样工作。
useGotoAtomsSnapshot
将更新当前的 Jotai 状态以匹配传递的快照。
function useGotoAtomsSnapshot(options?: {store?: Store}): (values: Iterable<readonly [AnyAtom, unknown]>) => void
此钩子返回一个回调,该回调接受来自 useAtomsSnapshot
钩子的 snapshot
并将更新 Jotai 状态。它接受一个 store
参数。
此钩子主要用于调试和 devtools 的用例。
示例
import { Provider } from 'jotai'import { useAtomsSnapshot, useGotoAtomsSnapshot } from 'jotai-devtools/utils'const petAtom = atom('cat')const colorAtom = atom('blue')const UpdateSnapshot = () => {const snapshot = useAtomsSnapshot()const goToSnapshot = useGotoAtomsSnapshot()return (<buttononClick={() => {const newSnapshot = new Map(snapshot)newSnapshot.set(petAtom, 'dog')newSnapshot.set(colorAtom, 'green')goToSnapshot(newSnapshot)}}>Go to snapshot</button>)}