Giter Club home page Giter Club logo

Comments (10)

enk0de avatar enk0de commented on June 3, 2024
image

from liveblocks.

nvie avatar nvie commented on June 3, 2024

Hi @enk0de – thanks for taking the time to write up this issue report. I've got a few follow-up questions to help investigate this issue.

  • From your dependency list, it looks like you're using the @liveblocks/react package to interact with Storage primarily, can you confirm this?
  • What does the (relevant) shape of your Storage tree look like? (Could you for example share the Storage type definition from your liveblocks.config.ts file if you have any?)
  • Can you share the relevant mutations you are performing in your mouse drag event? How exactly are you mutating storage?
  • Can you share the relevant room subscriptions you have set up that may trigger re-rendering?
  • Which React version are you on?

Thank you!

from liveblocks.

enk0de avatar enk0de commented on June 3, 2024
  1. Yes, we are using @liveblocks/react to use createRoomContext, shallow!
  2. As security issue, we cannot reveal exact interface. but i can share simillar structure.
interface Storage {
  tree: LiveObject<{
    rootNodeID: string; // Tree entry
    nodes: LiveMap<string, LiveObject<{ id: string, x: string, y: string, parentNodeID?: string, children?: LiveList<string> }>>;
  }>;
};
  1. Yes, sure.
  • when you drag the BlockNode, Node's x, y position is updated
  • when you drag the BlockNode to ContainerNode(which can take other Node in children), instantly below operations occurs.
    • remove BlockNode's id item from original parent's children LiveList.
    • replace BlockNode's parentNodeID value(original parent node id) with new parent(ContainerNode)'s id.
    • insert BlockNode's id item into new parent(ContainerNode)'s children LiveList.
  1. Yes, sure
    useStorage((root) => root.tree.nodes, shallow);
  2. We are using [email protected]

from liveblocks.

nvie avatar nvie commented on June 3, 2024

Amazing, thanks @enk0de! I assume you're making these three writes in a single batch(), so they're always sent over the wire as an atomic batch of ops? If you're using useMutation, that's already the case.

Could you maybe share what happens in one of your observed error states?

For example, do only 2 of the three updates take place? Or more than those 3? Or is there a duplicate entry somewhere? Basically: what does your erroreneous state look like in the situation like your recorded video?

from liveblocks.

enk0de avatar enk0de commented on June 3, 2024

I assume you're making these three writes in a single batch()

Yes, We are doing those operations in one batch callback!
Sometimes the execution of a batch() occurs in another batch(), or after a history.pause().

Could you maybe share what happens in one of your observed error states?

In recorded video, There are two spaces there. One is inside the white box shown in the video, and the other is outside the white box. The blue rectangle in the recorded video can be dragged to become a child in either of those two spaces.

Therefore, the blue square should only exist in one of the two spaces.

At the beginning of the video, you can see that moving the blue rectangle slowly works fine, but when you move it very quickly, it suddenly crashes.

an error situation occurs where the blue square exists in both spaces. This is not a React rendering issue, there are actually two of them in the data from Liveblocks.

from liveblocks.

enk0de avatar enk0de commented on June 3, 2024

hi, @nvie. I found a solution to resolve the issue.
the issue occurs when remove dragging node ID from original parent's children LiveList.

here is my original code

  private deleteNodeFromParent(id: string) {
    const parentNode = this.getParentNode(id);
    if (parentNode === undefined) {
      return;
    }

    const children = this.getLiveNode(parentNode.id)?.get('children');
    if (children === undefined) {
      throw new Error('Node children not exists');
    }

    const index = children.indexOf(id);
    children.delete(index);
}

The code below fixes the problem.

  private deleteNodeFromParent(id: string) {
    const parentNode = this.getParentNode(id);
    if (parentNode === undefined) {
      return;
    }

    const parentLiveNode = this.getLiveNode(parentNode.id);
    const originalChildren = parentLiveNode?.get('children');

    if (parentLiveNode === undefined) {
      throw new Error('Node not exists');
    }

    if (originalChildren === undefined) {
      throw new Error('Node children not exists');
    }

    parentLiveNode.set(
      'children',
      new LiveList(originalChildren.filter((childID) => childID !== id))
    );
  }

i just re-create children LiveList and replace it with originalChildren LiveList.
could you find and let me know why this problem happens? Thanks!

from liveblocks.

nvie avatar nvie commented on June 3, 2024

Ah, I see! Thanks for sharing that code example, @enk0de. This makes the problem a bit clearer to understand.

To summarize, the issue you were facing before is that under some conditions the children.delete(index) call sometimes does not remove the node from the LiveList, and as a result you are seeing the drag node end up in more than one children lists at the same time, causing an invalid state?

If the above is correct, I have an idea of what might explain this issue.

from liveblocks.

enk0de avatar enk0de commented on June 3, 2024

To be more precise, the node is not deleted when you do children.delete(index), but rather the nodeID is deleted in children LiveList and then immediately restored to the list.

from liveblocks.

nvie avatar nvie commented on June 3, 2024

Thanks for sharing that extra info @enk0de. Can you maybe also share if it's only the client that's affected, or does the same bug happen in a different client/window as well when it happens? Trying to bisect if this bug is scoped to the client or to the server. Thanks!

from liveblocks.

enk0de avatar enk0de commented on June 3, 2024

Hi. nvie. I am still suffering the problem. have you found out why this occurs?

from liveblocks.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.