Mobx-state-tree: Cannot use destroy(self)

Created on 11 Jan 2018  Â·  3Comments  Â·  Source: mobxjs/mobx-state-tree

I'm trying to destroy a node as follows:

export default t.model('Document', {
    document_id: t.identifier(t.number),
    path: t.maybe(t.string),
})
.actions(self => ({
    delete(){
        destroy(self)
    }
}))

and then somewhere in the code:

<button onClick={document.delete} />

I get the following error:

Error: [mobx-state-tree] Cannot modify 'Document[]@/requestsStore/requests/67/documents', the object is protected and can only be modified by using an action.

Most helpful comment

Based on the current capabilities of mst, I see such a universal solution. But it seems like it would be good to have out-of-the-box.

Image = t
    .model({
        'url' : t.string
    })
    .actions(self => ({
        remove() {
            getParent(self, 2).removeChild(self)
        }
    }))

Product = t
    .model('Product', {
        images : t.array(Image),
    })
    .actions(self => ({
        removeChild(item) => destroy(item)
    }));

Gallery = t
    .model('Gallery', {
        items : t.array(Image)
    })
    .actions(self => ({
        removeChild(item) => destroy(item)
    }));

Each Node should have remove method, which is call removeChild (or destroy/destroyChild) from parent Node.

Maybe need add this to core? Then possible write less code

Image = t
    .model({
        'url' : t.string
    })

Product = t
    .model('Product', {
        images : t.array(Image),
    })

Gallery = t
    .model('Gallery', {
        items : t.array(Image)
    })

All 3 comments

That is because destroy(self) does actually modify the parent (as weird
as it might sound initially, it is a collection in the parent , that is
actually changed by this. And since actions can only modify their own
substree, the exception is actually correct and you have to delegate the
call up

Op do 11 jan. 2018 om 23:22 schreef Mohamed Shibl <[email protected]

:

I'm trying to destroy a node as follows:

export default t.model('Document', {
document_id: t.identifier(t.number),
path: t.maybe(t.string),
})
.actions(self => ({
delete(){
destroy(self)
}
}))

and then somewhere in the code:

Image = t
    .model({
        'url' : t.string
    })
    .actions(self => ({
        remove() {
            // ... ???
            //
            // destroy(self) is better then
            //
            // getParent(self, 2).removeImage(self)
            // getParent(self, 2).removeItem(self)
            // ..etc
        }
    }))

Product = t
    .model('Product', {
        images : t.array(Image),
    })
    .actions(self => ({
        removeImage(image) => destroy(image)
    }));

Gallery = t
    .model('Gallery', {
        items : t.array(Image)
    })
    .actions(self => ({
        removeItem(item) => destroy(item)
    }));

@mweststrate
How to be in such cases? Calling a parent method from a child seems to be a very implicit solution because the methods may differ from one store to another.

Based on the current capabilities of mst, I see such a universal solution. But it seems like it would be good to have out-of-the-box.

Image = t
    .model({
        'url' : t.string
    })
    .actions(self => ({
        remove() {
            getParent(self, 2).removeChild(self)
        }
    }))

Product = t
    .model('Product', {
        images : t.array(Image),
    })
    .actions(self => ({
        removeChild(item) => destroy(item)
    }));

Gallery = t
    .model('Gallery', {
        items : t.array(Image)
    })
    .actions(self => ({
        removeChild(item) => destroy(item)
    }));

Each Node should have remove method, which is call removeChild (or destroy/destroyChild) from parent Node.

Maybe need add this to core? Then possible write less code

Image = t
    .model({
        'url' : t.string
    })

Product = t
    .model('Product', {
        images : t.array(Image),
    })

Gallery = t
    .model('Gallery', {
        items : t.array(Image)
    })
Was this page helpful?
0 / 5 - 0 ratings