Ошибка: [mobx-state-tree] Не удалось разрешить ссылку XXX для типа "Пользователь"
контекст
У меня есть приложение React, которое поддерживается mobx-state-tree (MST). Одна из страниц делает два параллельных вызова API для получения списка Projects
и список системы Users
,
Ответы этих двух API-интерфейсов затем применяются в качестве моментальных снимков к двум узлам одного и того же дерева. Поле владельца модели проекта относится к модели пользователя.
Моя проблема в том, что вызов API проекта GET часто завершается раньше, чем вызов API пользователя GET. Классическое "гоночное состояние". Итак, когда MST пытается разыменовать значение владельца, пользователь с таким идентификатором недоступен в дереве, и я получаю ошибку времени выполнения, подобную этой:
Ошибка: [mobx-state-tree] Не удалось разрешить ссылку 'dtGNbVdNOQIAX0OMGaH2r2oSEf2cMSk9AJzPAf4n7kA' для типа 'Пользователь' (с узла: /projectListStore/projects/0/owner)
Вопрос
Как мне обойти ошибку?
Обратите внимание, что выполнение вызовов API зависит друг от друга (await
или же users.load().then(users => { projects.load(); }
) не вариант для нашего проекта.
MST Models
export const ProjectModel = types
.model('Project', {
projectId: types.optional(types.identifierNumber, 0),
title: '',
descriptionStatus: '',
projectStatus: '',
startDate: CustomDate,
endDate: CustomDate,
owner: types.maybeNull(types.reference(User)), // -----
}) \
// ... |
|
export const User = types |
.model('User', { /
userId: types.identifier, // <<<--
userName: '',
firstName: '',
lastName: '',
email: '',
lastVisited: CustomDate,
})
// ...
Пример API
GET
https://service.com/api/users
[
{
"userId": "g-gqpB1EbTi9XGZOf3IkBpxSjpAHM8fpkeL4YZslEL8",
"userName": "john.doe@service.com",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@service.com",
"lastVisited": "2018-01-18T17:32:48.947"
},
{
...
},
...
]
GET
https://service.com/api/workmanagement/projects?minStartDate=&maxStartDate=2018-11-24&status=Active
[
{
"projectId": 1,
"title": "Project Title",
"description": "Praesent luctus vitae nunc sed condimentum. Duis maximus arcu tortor, vitae placerat enim ultrices sed. Etiam scelerisque gravida justo, vitae venenatis dui pellentesque eu.",
"projectStatus": "active",
"startDate": "2018-08-20T00:00:00",
"endDate": "2019-07-01T00:00:00",
"owner": "g-gqpB1EbTi9XGZOf3IkBpxSjpAHM8fpkeL4YZslEL8",
},
{
// ...
},
...
]
0 ответов
Одно из решений, которое вы можете применить, находится в ProjectModel
модель для определения владельца в виде строки
owner: types.maybeNull(types.string),
Затем определите вычисляемое свойство модели, которое будет извлекать владельца как объект.
export const ProjectModel = types
.model('Project', {
projectId: types.optional(types.identifierNumber, 0),
title: '',
descriptionStatus: '',
projectStatus: '',
startDate: CustomDate,
endDate: CustomDate,
owner: types.maybeNull(types.reference(User)), // -----
}).views(self => ({
get ownerObject(): undefined | Instance<typeof User> {
// get the user manually from the tree
const root = getRoot(self)
return resolveIdentifier(User.Type, root, self.owner)
}
}))
Вы можете использовать это так project1.ownerObject ? project1.ownerObject.firstName : ''
Обратной стороной является то, что вам всегда нужно будет проверять ownerObject
существует всякий раз, когда вы его используете.
Похоже, вы потенциально загружаете пользовательские данные после создания модели проекта. Это может быть так же просто, как использование поздней ссылки. Это предназначено для любых типов, которые могут быть созданы после создания этой модели.
вместо этогоowner: types.maybeNull(types.reference(User))
попробуй этоowner: types.maybeNull(types.late(() => types.reference(User)))