valtiojs / valtio-yjs

valtio-yjs makes yjs state easy
MIT License
270 stars 15 forks source link

Document empties when new user joins the room with y-websocket #35

Closed valstu closed 1 year ago

valstu commented 2 years ago

I have bumped into weird behaviour where document goes empty when new user joins the room. This happens with valtio-yjs and y-websocket. I have following state:

import { proxy } from "valtio";
import { bind } from "valtio-yjs";
import * as Y from "yjs";
import { WebsocketProvider } from "y-websocket";

export const state = proxy<{
  someArray: { id: number; value: number }[];
  counter: number;
}>({ someArray: [], counter: 1 });

const ydoc = new Y.Doc();
const provider = new WebsocketProvider(
  "wss://demos.yjs.dev",
  "cat-123",
  ydoc
);

const ymap = ydoc.getMap();

bind(state, ymap);

I also have a simple UI with single button which pushes objects to that someArray. Lets say I click three times the button and there will be three objects now on the array as expected. Now open another browser (this is critical, completely another browser). Open the same page and array content will disappear, both from new browser and old one. If it does not disappear try refreshing the new browser. Sometimes it magically starts to work and it become harder to reproduce, but if you change the room id you will be able reproduce this again.

I tried to make as simple as possible example here https://codesandbox.io/s/cranky-meadow-d0jleb

I guess this doesn't happen if I use object instead of array (someArray: [] => someObject: {})? Is ok to use arrays with nested objects inside ymap?

dai-shi commented 2 years ago

I guess this doesn't happen if I use object instead of array (someArray: [] => someObject: {})?

Then, it sounds like a bug... cc @PhilGarb

Is ok to use arrays with nested objects inside ymap?

Yeah, it should be.

valstu commented 2 years ago

Ok, It might have something to do with the way I initialize the proxy state:

export const state = proxy<{
  someArray: { id: number; value: number }[];
  counter: number;
}>({ someArray: [], counter: 1 });

If I initialize proxy state with empty object it seems to work (although I cannot be 100% sure since reproducing this is sometimes difficult)

export const state = proxy<{
  someArray: { id: number; value: number }[];
  counter: number;
} | {}>({});
dai-shi commented 2 years ago

Probably, something doesn't work well for bind() initialization.

dai-shi commented 1 year ago

Published: https://www.npmjs.com/package/valtio-yjs/v/0.4.1