Closed frontend-sensei closed 1 year ago
We are encountering the same issue.
We have a React application which used SyncedStore with 2 properties in it: article, en metadata. Article is an object which is constructed of primitive values and 1 units property, which is an array of objects.
The syncedStore gets its data through YJS, where the logic of handling the YJS docs is built upon a centralised server.
The current situation is that, when a backend call tells this server to fetch the most recent 'article' and replace the existing one, the updated value of units is a boxed array. How can we prevent this from happening?
this.logger.info("[${this.name}] Reloading article content")
const garbageCollection = true
const articleMap = this.getMap(ARTICLE_MAP_NAME)
logger.info("[${this.name}] Reloading WSSharedDoc from our ACL endpoint")
const updatedSharedDoc = await getWSSharedDoc(this.name, garbageCollection)
const updatedArticleContent = updatedSharedDoc.getMap(ARTICLE_MAP_NAME).toJSON()
const updatedArticleContentFields = Object.keys(updatedArticleContent)
updatedArticleContentFields.forEach((updatedArticleContentField) => {
articleMap.set(updatedArticleContentField, updatedArticleContent[updatedArticleContentField])
})
Hi! When you use yjs methods, such as doc.getArray("todos").push(...)
(@frontend-sensei) or Y.Map.set() (@nvanhoeck-dpgmedia ), then you'll directly add the object your pushing / setting as "one value". In syncedstore we call this "boxed".
A "boxed" value means that the entire object is the granularity of syncing. If you use SyncedStore style methods (e.g.: store.todos.push({...}) ), the values won't be boxed, and you syncing happens all the way through the property level.
To understand what's going on beneath. When you use Y.Array push
, this entire object ({ id: 1, completed: false, title: 'one' }
) in the first example will be seen as one "opaque" object.
When you use SyncedStore todos.push(...)
, it internally get's translated to something like (pseudo code): Y.Array push(new Y.Map({id: 1, completed: false, title: 'one' })
TLDR: make sure you either use the syncedstore methods that simplify this, or create a Y.Map to represent your object
@YousefED thanks for the clarification. So if I get this correct, if we want to push changes from a YJS server to all clients, we need to map our data to a Y.Map structure and push the changes in this Y.Array. If we talk about a nested data structure, we'll have to do this for every array in the nested data structure?
Hey, @YousefED! This library looks cool. Im trying figure out it deeper.
What I am going to do
Get initial data using REST and fill it to YDoc which I got from
getYjsDoc(store)
. When I check store values, I found that added values wrapped as a Boxed values.Example of my code:
What I see in the console: