Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A workaround to avoid cyclic references when using DeepObserve #275

Open
aabuelenin opened this issue Aug 17, 2020 · 3 comments
Open

A workaround to avoid cyclic references when using DeepObserve #275

aabuelenin opened this issue Aug 17, 2020 · 3 comments

Comments

@aabuelenin
Copy link

I've a scenario where some business objects need to keep a reference to their parent, also, their parent could change in the runtime), for example:

class Root {
    @observable
    pages: Array<Page> = [];

    constructor() {
        deepObserve(this, (change, path, root) => {
            console.log(change);
            console.log(path);
            console.log(root);
        });
    }
}

class Page {
    @observable
    nodes: Array<Node> = [];
}

class Node {
    @observable.ref
    parentPage: Page;

    @action
    setPage(page: Page): void {
        this.parentPage = page;
    }
}

In this example Node references its parent causing a cyclic reference and a runtime error
"The same observable object cannot appear twice in the same tree, trying to assign it to 'pages/0/nodes/0/parentPage', but it already exists at 'pages/0'"

I tried using observable.ref on parentPage hoping that deepObserve will treat parentPage as a reference, hence, it won't be considered a cyclic-reference, but it still failed.

Is there's a way to communicate to mobx that parentPage is just a reference and for the purposes of deepObserve, only the reference should be observed and not the page's members (the members of page would still be observable, but they won't be observed twice)?

@ToyWalrus
Copy link

I realize this is an old issue, but as it hasn't been updated or addressed in over 2 years I think leaving another comment on it may help. I would also like a workaround for this. I've tried several different methods but ultimately I keep getting the same error thrown.
In the code there's a comment saying that the check that throws this error is not actually necessary -- is there a way we could potentially disable it via an argument to the deepObserve() method?

@mweststrate @NaridaL (tagging you two b/c you have the highest contributor score in this repo, even though the repo development seems to have stagnated a little bit)

@dangoodman
Copy link

The abovementioned error also happens for duplicate array entries:

const arr = observable.array()
deepObserve(arr, /* ... */)

// error; both arr[0] and arr[1] reference the same observable
arr[0] = arr[1]

// swapping items fails with the error too
[arr[0], arr[1]] = [arr[1], arr[0]]

This case is different since it doesn't form a cycle but rather a bifurcation. A single observable has two paths.

Is the error necessary in this case?

@mweststrate
Copy link
Member

mweststrate commented May 27, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants