调试
在基本的应用中,console.log
可以是我们调试原子的最好朋友,但是当应用变得更大,我们需要使用更多的原子时,日志可能不是调试原子的好方法。
Jotai 提供了两种调试原子的方法,React Dev Tools 和 Redux Dev tools。对于读取值和简单的调试,React Dev Tools 可能适合你,但对于更复杂的任务,如时间旅行和设置值,Redux Dev Tools 可能是更好的选择。
调试标签
值得一提的是,我们在 Jotai 中有一个叫做 调试标签 的概念,它可能会帮助我们进行调试。
默认情况下,每个 Jotai 状态都有像 1:<no debugLabel>
这样的标签,数字是自动分配给每个原子的内部 key
。但是你可以使用 debugLabel
给原子添加标签,以便更容易地 区分它们。
const countAtom = atom(0)// 默认情况下,countAtom 的 debugLabel 是 'atom1'if (process.env.NODE_ENV !== 'production') {countAtom.debugLabel = 'count'// 现在 debugLabel 是 'count'}
Jotai 提供了一个 Babel 和一个 SWC 插件,它们会自动为每个原子添加一个 debugLabel,这使得事情对我们来说更容易。更多信息,请查看 jotai/babel 和 @swc-jotai/debug-label
使用 React Dev Tools
你可以使用 React Dev Tools
来检查 Jotai 状态。为了实现这一点,我们在自定义钩子中使用了 useDebugValue。请记住,它只在开发模式下工作
(例如 NODE_ENV === 'development'
)。
useAtom
useAtom
为原子值调用 useDebugValue
,所以如果你在 React Dev Tools 中选择使用 Jotai 原子的组件,你会看到每个在组件中使用的原子都有一个 "Atom" 钩子,以及它现在的值。
useAtomsDebugValue
useAtomsDebugValue
捕获 Provider 下的组件树中的所有原子(或者对于无 Provider 模式的整个树),并为所有原子值使用 useDebugValue
。
如果你在 React Dev Tools 中导航到有 useAtomsDebugValue
的组件,我们可以看到一个自定义钩子 "AtomsDebugValue",它允许你查看所有原子值及其依赖项。
一个用例是将钩子放在 Provider
组件下:
const DebugAtoms = () => {useAtomsDebugValue()return null}const Root = () => (<Provider><DebugAtoms /><App /></Provider>)
使用 Redux DevTools
你也可以使用 Redux DevTools 来检查原子,它有许多功能,如时间旅行和值分派。
useAtomDevtools
useAtomDevtools
是一个 React 钩子,它为特定的原子管理 ReduxDevTools 扩展。
如果你有一个特定的原子你可能想要调试,useAtomDevtools
可以是一个好选择。
const countAtom = atom(0)// 如果我们有更多的原子,建议设置 countAtom.debugLabelfunction Counter() {const [count, setCount] = useAtom(countAtom)useAtomDevtools(countAtom)}
现在如果我们尝试 setCount
,我们可以看到 Redux Dev Tools 立即记录了这些更改。
时间旅行
有时我们需要切换到我们原子状态的特定值,有了时间旅行,这是可能的。 你可以在 devtools 中看到每个动作上的 Jump 选项,点击它,你就能切换到那个特定的值。
暂停
如果我们不记录原子上的更改,我们可以使用暂停功能停止观察这些原子。
调度
我们可以使用调度功能在原子上设置值。你可以通过点击显示调度器按钮来实现这一点。
这将把 countAtoms
的值设置为 5
。
我们应该注意,值将由 JSON.parse 解析,所以传递支持的值。
useAtomsDevtools
useAtomsDevtools
是useAtomDevtools
的全能版本,它显示存储中的所有原子,而不是显示一个特定的原子。
如果你想在一个地方跟踪所有的原子,我们推荐这个钩子。这意味着每一个在这个钩子底部(在 React 树中)的原子上的每一个动作都会被 Redux Dev Tools 捕获。
useAtomDevtools
的每一个功能在这个钩子中都被支持,但是还有一个额外的功能,它包括提供更多关于原子依赖的信息,如:
{"values": {"atom1:count": 0,"atom2:doubleCount": 0,"atom3:half": 0,"atom4:sum": 0},"dependents": {"atom1:count": ["atom1:count", "atom2:doubleCount", "atom4:sum"],"atom2:doubleCount": ["atom3:half", "atom4:sum"],"atom3:half": ["atom4:sum"],"atom4:sum": []}}
冻结原子
为了找到你意外尝试改变存储在原子中的对象的错误,你可以使用 jotai/utils
包中的 freezeAtom
或 freezeAtomCreator
。它返回一个深度冻结的原子值,使用 Object.freeze
。
freezeAtom
freezeAtom(anAtom): AtomType
freezeAtom
接受一个现有的原子并使其"冻结"。
它返回相同的原子。
原子值将被 Object.freeze
深度冻结。
它对于找到你无意中尝试改变对象(状态)的错误非常有用,这可能会导致意外的行为。
你可以使用 freezeAtom
与所有原子一起防止这种情况。
参数
anAtom (必需): 你希望冻结的原子。
示例
import { atom } from 'jotai'import { freezeAtom } from 'jotai/utils'const objAtom = freezeAtom(atom({ count: 0 }))
freezeAtomCreator
如果你需要,你可以为 freezeAtom
定义一个工厂。
import { freezeAtom } from 'jotai/utils'export function freezeAtomCreator<CreateAtom extends (...args: unknown[]) => Atom<unknown>,>(createAtom: CreateAtom): CreateAtom {return ((...args: unknown[]) => freezeAtom(createAtom(...args))) as never}