automatic / computed references between dependent entities #1972
-
| Is there a way to keep references up to date between two entities. Here, I have a simple model with  const Row = t.model("row", {
  id: t.refinement(t.identifier, id => isUUID(id)),
  order: t.string,
  table: t.reference(t.late((): IAnyModelType => Table)),
})
const Table = t
  .model("table", {
    id: t.refinement(t.identifier, id => isUUID(id)),
    rows: t.map(t.reference(t.late((): IAnyModelType => Row))),
  })
  .actions(self => ({
    addRow: (row) => void (self.rows.set(row.id, Row.create(row))),
  }))
const State = t.model("state", {
  tables: t.map(Tables),
  rows: t.map(Row),
})My newbie intuition is to use listeners such as  A simpler problem with one entity is automatic managing parent-children dependencies. If a child node is added or deleted, is there a way to update the children map of its parent? Is there a way to delete all children recursively if a parent is deleted? const Node = t.model("node", {
  id: t.refinement(t.identifier, id => isUUID(id)),
  children: t.map(t.reference(t.late((): IAnyModelType => Node))),
  parent: t.reference(t.late((): IAnyModelType => Node))
})(Sorry if the question is too basic; new to mobx and mst, and don't know how to model and update entities compared to Postgres 😅 ). | 
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 6 replies
-
| I have found a naive solution using  // Equivalent of a cascading deletion when foreign key is deleted.
export const deleteSelf = ({ cause, parent }) => void (cause == "destroy" && remove(getParent(parent), parent.id));
const Row = t
  .model("row", {
    id: t.refinement(t.identifier, id => isUUID(id)),
    order: t.string,
    table: t.reference(t.late((): IAnyModelType => Table), { onInvalidated: deleteSelf }),
  });
const Table = t
  .model("table", {
    id: t.refinement(t.identifier, id => isUUID(id)),
  })
  .views(self => ({
    get rows() {
      return values(getRoot(self).rows).filter(row => row.table.id == self.id);
    }
  }))
  .actions(self => ({
    addRow: (row) => {
      const root = getRoot(self);
      unprotect(root); // mst doesn't like when subtrees modify their parents
      set(root.rows, row.id, {...row, table: self.id});
      protect(root);
    }
  }))
const State = t
  .model("state", {
    tables: t.map(Tables),
    rows: t.map(Row),
  }) | 
Beta Was this translation helpful? Give feedback.
-
| This is a clear indication that your action needs to live higher in the tree. Also, any specific reason to keep your references in a map? A simple list would work better since the snapshot would be just a list of strings. | 
Beta Was this translation helpful? Give feedback.
-
| Marking @antondomratchev's answer as correct here based on the discussion. Thanks, y'all! | 
Beta Was this translation helpful? Give feedback.
My apologies I was looking at the first example of the code you provided. Where Table model was defining rows as a property.
You can use something like
getRoot(self).addRow(self.id, row)this code assumes that current model is attached to the root node and the root node has aaddRowaction. I tend to sprinkle arootview across my child models because i often dive to the root of the tree and traverse…