Mobx reference type VS API data with entities relations #1926
-
Hey, I have an API that returns data where relations between my entities are already defined. My question is: How to implement Simple example (which is not my real case, taken from packages). Book entityexport const Book = types.model("Book", {
id: types.identifier,
title: types.string,
author: types.reference(User),
}) User entityexport const User = types.model("User", {
id: types.identifier,
name: types.string,
}) BookStoreexport const BookStore = types
.model("BookStore", {
books: types.optional(types.array(Book), []),
})
.actions((self) => {
getBooks : async () => {
const books = await MagicalFetchBookApi() // don't mind this, result under
self.books.replace(books)
}
}) MagicalFetchBookApi() result[
{
"id": 1,
"title": "My first book",
"author": {
"id": 1,
"name": "cavasinf"
}
},
{
"id": 2,
"title": "My second book",
"author": {
"id": 1,
"name": "cavasinf"
}
},
{
"id": 3,
"title": "Someone else book",
"author": {
"id": 2,
"name": "random guy"
}
}
] I understand that one {
"id": "1",
"title": "My first book",
"author": "1"
}, But I don't understand how to implement User (author), without pooling every users from UserStore (API) and referencing them later in my BookStore. TLDRHow to transform API response: {
"id": 1,
"title": "My first book",
"author": {
"id": 1,
"name": "cavasinf"
}
} Into two referenced entities ( |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 9 replies
-
Hi @cavasinf! You could model the users in your Example (CodeSandbox) const BookStore = types
.model("BookStore", {
users: types.optional(types.map(User), {}),
books: types.optional(types.array(Book), [])
})
.actions((self) => ({
getBooks: flow(function* () {
const books = yield MagicalFetchBookApi();
books.forEach((book) => {
const { author } = book;
self.users.set(author.id.toString(), author);
self.books.push({
...book,
author: author.id
});
});
})
})); |
Beta Was this translation helpful? Give feedback.
-
Sub question if you mind @EmilTholin. How should I type
{
"id": number,
"title": string,
"author": {
"id": number,
"name": string
}
} |
Beta Was this translation helpful? Give feedback.
-
Hello again @EmilTholin, With the same example as above (Book/Author), and the current order of use/display of my application:
When calling the getAuthorBooks() function from the store, a mobx error appears: From what I understand from the error, mobx is telling me that it has already memorised the author from my previous author list AND the author of the current pooled book. What I don't get is how Mobx as made the link between const UserStore = types
.model("UserStore", {
users: types.optional(types.array(User), [])
})
.actions((self) => ({
getUsers: flow(function* () {
const users = yield MagicalFetchUsersApi();
users.replace(users)
})
})); const BookStore = types
.model("BookStore", {
users: types.optional(types.map(User), {}),
books: types.optional(types.array(Book), [])
})
.actions((self) => ({
getUserBooks: flow(function* () {
const books = yield MagicalFetchBookApi();
books.forEach((book) => {
const { author } = book;
self.users.set(author.id.toString(), author);
self.books.push({
...book,
author: author.id
});
});
})
})); |
Beta Was this translation helpful? Give feedback.
Hi @cavasinf!
You could model the users in your
BookStore
as well, and extract them from the books in yourgetBooks
action and transform the response somewhat so that you only use theid
of theauthor
when you replace thebooks
in the store.Example (CodeSandbox)