API Usage

Mistakes when calling Yjs methods.

Mutating Objects After Insertion

// WRONG
const config = { theme: 'light' }
yMap.set('config', config)
config.theme = 'dark'  // NOT synced!

Yjs snapshots on set(). Later mutations don’t propagate.

Fix: Create new objects, or use nested Y.Map for granular updates:

yMap.set('config', { ...yMap.get('config'), theme: 'dark' })

Moving Shared Types Between Parents

// WRONG
const items = folder1.get('items')  // Y.Array
folder2.set('items', items)  // Error!

Shared types can only have one parent.

Fix: Copy data to new shared type, delete old.

Creating New Instances Instead of Accessing

// WRONG
function addItem(item) {
  const items = new Y.Map()  // Disconnected!
  items.set(item.id, item)
}

new Y.Map() is unattached. Use yDoc.getMap().

Not Using Transactions

// WRONG: 2N syncs, 2N observer events
for (const item of items) {
  content.set(item.id, item)
  order.push([item.id])
}

Fix: Wrap in transact():

yDoc.transact(() => {
  for (const item of items) {
    content.set(item.id, item)
    order.push([item.id])
  }
})

Forgetting trackedOrigins

// WRONG: captures remote changes too
const undoManager = new UndoManager([content])

Without trackedOrigins, undo captures collaborators’ changes.

Fix:

const undoManager = new UndoManager([content], {
  trackedOrigins: new Set(['user-action'])
})
yDoc.transact(() => { ... }, 'user-action')

Checklist

  • Never mutate after set()
  • Don’t move shared types between parents
  • Use yDoc.getMap(), not new Y.Map()
  • Wrap related changes in transact()
  • Configure UndoManager with trackedOrigins

See Also