jazz-ui-development
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseJazz UI Development
Jazz UI 开发
When to Use This Skill
何时使用此技能
- Building user interfaces that display or interact with Jazz data
- Setting up authentication providers and contexts
- Debugging reactivity, data loading, or sync issues in the UI
- Optimizing performance of data subscriptions
- Handling media (images, files) in the UI
- 构建展示Jazz数据或与Jazz数据交互的用户界面
- 配置身份认证providers和contexts
- 调试UI中的响应性、数据加载或同步问题
- 优化数据订阅的性能
- 在UI中处理媒体资源(图片、文件)
Do NOT Use This Skill For
请勿将此技能用于
- Defining data schemas (use )
jazz-schema-design - Complex permission logic or sharing workflows (use )
jazz-permissions-security - Testing questions (use )
jazz-testing
- 定义数据schemas(请使用 )
jazz-schema-design - 复杂权限逻辑或共享工作流(请使用 )
jazz-permissions-security - 测试相关问题(请使用 )
jazz-testing
Key Heuristic for Agents
给Agent的关键判断规则
Use this skill when the user asks about rendering data, handling user input, managing authentication state, or framework-specific integration (React, Svelte, etc.). If the issue is "data not appearing" but permissions are correct, look here for loading and subscription patterns.
当用户询问渲染数据、处理用户输入、管理身份认证状态或特定框架集成(React、Svelte等)相关问题时使用此技能。如果出现「数据不展示」但权限校验正常的问题,可在此查找加载和订阅模式相关的解决方案。
Framework Guides
框架指南
Select the guide for your specific framework:
- React: React Reference
- React Native (Bare): As well as the React guide, also see React Native Reference
- React Native (Expo): As well as the React guide, also seeReact Native (Expo) Reference
- Svelte: Svelte Reference
- Vanilla JS: Vanilla JS Reference
选择适配你所用框架的指南:
- React: React 参考文档
- React Native (裸项目):除React指南外,还可参考 React Native 参考文档
- React Native (Expo):除React指南外,还可参考 React Native (Expo) 参考文档
- Svelte: Svelte 参考文档
- Vanilla JS: 原生JS 参考文档
Universal CoValue API
通用CoValue API
These APIs are available on all CoValue instances, regardless of the framework.
以下API在所有CoValue实例上都可用,与所用框架无关。
Core Properties
核心属性
All CoValues (CoMaps, CoLists, etc.) have these properties directly on the instance:
- (
$isLoaded): Returnsbooleanif the CoValue is fully loaded and ready to read.true - : Returns a plain JavaScript object representation of the CoValue. Use this for debugging only, not for rendering.
.toJSON()
所有CoValues(CoMaps、CoLists等)的实例都直接具备以下属性:
- (
$isLoaded): 当CoValue完全加载完毕可读取时返回booleantrue - : 返回CoValue的普通JavaScript对象表示形式。仅用于调试,不要用于渲染逻辑。
.toJSON()
The .$jazz
Namespace
.$jazz.$jazz
命名空间
.$jazzEvery CoValue instance has a property containing metadata and utility methods.
.$jazz每个CoValue实例都有一个属性,包含元数据和工具方法。
.$jazzMetadata
元数据
- (
.$jazz.id): The globally unique ID of the CoValue (e.g.,ID<CoValue>).co_zXy... - (
.$jazz.owner): The Group that owns this CoValue. Access control is determined by membership in this group.Group - (
.$jazz.createdAt): Creation timestamp (ms since epoch).number - (
.$jazz.createdBy): ID of the creating account.ID<Account> | undefined - (
.$jazz.lastUpdatedAt): Last update timestamp (ms since epoch).number
- (
.$jazz.id): CoValue的全局唯一ID(例如ID<CoValue>)co_zXy... - (
.$jazz.owner): 拥有此CoValue的Group。访问权限由该组的成员资格决定Group - (
.$jazz.createdAt): 创建时间戳(纪元以来的毫秒数)number - (
.$jazz.createdBy): 创建账号的IDID<Account> | undefined - (
.$jazz.lastUpdatedAt): 最后更新时间戳(纪元以来的毫秒数)number
Loading & Inspection
加载与检查
- (
.$jazz.loadingState): The current loading state."loading" | "loaded" | "unavailable" | "unauthorized" - : Waits for nested references to load. Returns a promise with a new instance where requested fields are guaranteed available.
.$jazz.ensureLoaded({ resolve: { ... } })
ts
const detailedPost = await post.$jazz.ensureLoaded({
resolve: {
comments: {
$each: {
author: true
}
}
}
});- (CoMap/CoRecord only): Access nested CoValues as references (with IDs) without loading them.
.$jazz.refs - (CoMap/CoRecord only): Checks if a key exists.
.$jazz.has(key)
- (
.$jazz.loadingState): 当前加载状态"loading" | "loaded" | "unavailable" | "unauthorized" - : 等待嵌套引用加载完成。返回一个带新实例的Promise,其中请求的字段保证可用。
.$jazz.ensureLoaded({ resolve: { ... } })
ts
const detailedPost = await post.$jazz.ensureLoaded({
resolve: {
comments: {
$each: {
author: true
}
}
}
});- (仅CoMap/CoRecord支持): 无需加载即可作为引用(带ID)访问嵌套CoValues
.$jazz.refs - (仅CoMap/CoRecord支持): 检查某个key是否存在
.$jazz.has(key)
Subscription & Sync
订阅与同步
- : Manually subscribe to changes. Returns an unsubscribe function. Prefer framework-specific hooks (e.g.,
.$jazz.subscribe(callback)) over this.useCoState - : Promise that resolves when changes are synced to peers. Useful for critical saves or logout flows.
.$jazz.waitForSync()
- : 手动订阅变更,返回取消订阅的函数。优先使用框架专属hooks(例如
.$jazz.subscribe(callback))而非此方法useCoState - : 变更同步到对等节点后resolve的Promise,适用于关键保存或登出流程
.$jazz.waitForSync()
Version Control
版本控制
- (
.$jazz.isBranched): Whether the CoValue is currently in a local branch.boolean - (
.$jazz.branchName): The name of the current branch.string - : Merges a branch back into the main history.
.$jazz.unstable_merge()
- (
.$jazz.isBranched): CoValue当前是否处于本地分支boolean - (
.$jazz.branchName): 当前分支的名称string - : 将分支合并回主历史记录
.$jazz.unstable_merge()
Working with Data Types
数据类型使用指南
CoMap / CoRecord
CoMap / CoRecord
- Read: Access properties like a standard JS object (e.g., ).
user.name - Write:
.$jazz.set(key, value).$jazz.delete(key).$jazz.applyDiff(diff)
- 读取: 像标准JS对象一样访问属性(例如 )
user.name - 写入:
.$jazz.set(key, value).$jazz.delete(key).$jazz.applyDiff(diff)
CoList
CoList
- Read: Access by index (), iterate (
list[0],map).forEach - Write:
.$jazz.push(item).$jazz.unshift(item).$jazz.splice(...).$jazz.remove(index or predicate)
- 读取: 按下标访问()、迭代(
list[0]、map)forEach - 写入:
.$jazz.push(item).$jazz.unshift(item).$jazz.splice(...).$jazz.remove(index or predicate)
CoText (CoPlainText / CoRichText)
CoText (CoPlainText / CoRichText)
- Read: or use directly in template.
toString() - Write:
insertAfter(index, text)deleteRange({ from, to }).$jazz.applyDiff(newText)
- 读取: 调用或直接在模板中使用
toString() - 写入:
insertAfter(index, text)deleteRange({ from, to }).$jazz.applyDiff(newText)
CoFeed
CoFeed
- Read: Iterate over (returns per-session feeds).
feed.all - Write: (Append-only).
.$jazz.push(item)
ts
// Subscribing to all entries across all accounts
const allEntries = Object.values(feed.perAccount).flatMap(accountFeed => Array.from(accountFeed.all));
// Pushing a new entry
feed.$jazz.push({ message: "Hello", timestamp: Date.now() });- 读取: 遍历(返回按会话划分的feed)
feed.all - 写入: (仅支持追加)
.$jazz.push(item)
ts
// 订阅所有账号的所有条目
const allEntries = Object.values(feed.perAccount).flatMap(accountFeed => Array.from(accountFeed.all));
// 推送新条目
feed.$jazz.push({ message: "Hello", timestamp: Date.now() });DiscriminatedUnion
DiscriminatedUnion
- Read: Check the discriminator property (e.g. ) to narrow the type.
type - Write: Overwrite the property with a new object of the desired variant.
ts
const list = co.list(MyUnion);
const item = list[0];
if (item.type === "text") {
console.log(item.value); // item is narrowed to TextVariant
} else if (item.type === "image") {
console.log(item.image.$jazz.id); // item is narrowed to ImageVariant
}- 读取: 检查判别属性(例如 )来收窄类型
type - 写入: 用目标变体的新对象覆盖对应属性
ts
const list = co.list(MyUnion);
const item = list[0];
if (item.type === "text") {
console.log(item.value); // item被收窄为TextVariant类型
} else if (item.type === "image") {
console.log(item.image.$jazz.id); // item被收窄为ImageVariant类型
}FileStream
FileStream
- Read: Use or consume chunks.
toBlob() - Write: Use or
createFromBlob(blobOrFile).start(metadata) -> push(chunk) -> end()
- 读取: 使用或逐块消费
toBlob() - 写入: 使用或按
createFromBlob(blobOrFile)流程操作start(metadata) -> push(chunk) -> end()
ImageDefinition
ImageDefinition
- Read: Use component (framework specific) or
<Image>.loadImageBySize - Write: use the function from
createImagejazz-tools/media
tsx
<Image imageId={productImage.$jazz.id} width={300} />- 读取: 使用组件(框架专属)或
<Image>loadImageBySize - 写入: 使用提供的
jazz-tools/media函数createImage
tsx
<Image imageId={productImage.$jazz.id} width={300} />Troubleshooting
故障排查
"Data not appearing" or "Value is undefined"
"数据不展示"或"值为undefined"
- Check : Ensure you are checking
$isLoadedbefore rendering.if (coValue.$isLoaded) - Deep Loading: If nested data is missing, use in your hook (e.g.
resolve).useCoState(..., { resolve: { items: true } }) - Provider Check: Ensure the component is wrapped in the appropriate .
<JazzProvider />
- 检查: 确保渲染前已判断
$isLoadedif (coValue.$isLoaded) - 深层加载: 如果嵌套数据缺失,在hook中使用配置(例如
resolve)useCoState(..., { resolve: { items: true } }) - Provider检查: 确保组件被正确包裹在对应的中
<JazzProvider />
"Infinite re-render loops"
"无限重渲染循环"
- Selector Stability: Ensure your function in
selectis stable or returns stable references.useCoState - Expensive Selectors: Move computations to instead of doing them inside the
useMemofunction.select - Equality Function: Use to prevent unnecessary updates if the selected data hasn't changed semantically.
equalityFn
- 选择器稳定性: 确保中的
useCoState函数是稳定的,或者返回稳定的引用select - 昂贵选择器: 将计算逻辑移到中,不要在
useMemo函数内部执行select - 相等性判断函数: 如果选中数据语义上没有变化,可使用避免不必要的更新
equalityFn
"Reactivity not triggering"
"响应性不触发"
- Direct Mutations: Ensure you are using or
.$jazz.set()instead of direct property assignment (e.g..$jazz.push()won't sync).obj.key = val - Deep Updates: Remember that updating a nested scalar doesn't trigger a change in the parent CoValue unless that parent property is replaced.
- 直接修改: 确保你使用的是或
.$jazz.set(),而非直接赋值属性(例如.$jazz.push()不会触发同步)obj.key = val - 深层更新: 注意更新嵌套的标量值不会触发父级CoValue的变更,除非父级属性被整体替换