Mobx 状态树能否导致 "race conditions" / 仅适用于 setTimeout?
Can a Mobx State Tree cause "race conditions" / works only with setTimeout?
使用mobx-state-tree。我有一个包含此操作的 ListStore
:
remove: process(function* remove(id) {
try {
self.markBeingRemoved(id); // set flag in store
const element = yield getEnv(self).resource.remove(id); // async call
self.removeFromList(element.id); // see below
showSuccessNotification(); // some jQuery based notification library
} catch (err) {
showServerError();
} finally {
self.markBeingRemoved(null);
}
})
现在 removeFromList
只需:
const indexToRemove = self.list.findIndex(e => e.id === elementId);
if (indexToRemove >= 0) {
self.list.splice(indexToRemove, 1);
}
现在我有一个使用列表的 React 组件。它像 @inject('ListStore')
一样被注入。然后我将它作为道具传递给子组件。使用它的子组件,都是mobx-observer
s.
我收到这个晦涩的错误,Google 对此一无所知:
mobx-state-tree.module.js?9486:50 Uncaught Error: [mobx-state-tree]
This object has died and is no longer part of a state tree.
It cannot be used anymore.
The object (of type 'Template') used to live at '/list/1'. It is
possible to access the last snapshot of this object using
'getSnapshot', or to create a fresh copy using 'clone'. If you want to
remove an object from the tree without killing it, use 'detach'
instead.
at fail (webpack-internal:///467:92:11)
at Object.get (webpack-internal:///467:1409:17)
at Object.get [as id] (webpack-internal:///33:1682:28)
at dehydrate
at dehydrate (chrome-
extension://fmkadmapgofadopljbjfkapdkoienihi/build/backend.js:8154:24)
at dehydrate (chrome-
extension://fmkadmapgofadopljbjfkapdkoienihi/build/backend.js:8154:24)
at chrome-
extension://fmkadmapgofadopljbjfkapdkoienihi/build/backend.js:7285:20
at Array.map (native)
at Bridge.flushBufferSlice (chrome-
extension://fmkadmapgofadopljbjfkapdkoienihi/build/backend.js:7280:33)
at Bridge.flushBufferWhileIdle (chrome-
extension://fmkadmapgofadopljbjfkapdkoienihi/build/backend.js:7268:15)
fail @ mobx-state-tree.module.js?9486:50
get @ mobx-state-tree.module.js?9486:1367
get @ mobx.module.js?cbdf:1638
dehydrate @ backend.js:8154
dehydrate @ backend.js:8154
dehydrate @ backend.js:8154
(anonymous) @ backend.js:72
flushBufferSlice @ backend.js:7280
flushBufferWhileIdle @ backend.js:726
有趣的部分来了:如果我将 removeFromList
的调用放入 setTimeout(..., 1000)
, 有效!
为什么?
该错误是由react开发者工具触发的
他们在内存中保存了一个已死亡的对象,这就是他们投掷的原因。在没有 devtools 的生产中,它们不会触发该错误。
使用mobx-state-tree。我有一个包含此操作的 ListStore
:
remove: process(function* remove(id) {
try {
self.markBeingRemoved(id); // set flag in store
const element = yield getEnv(self).resource.remove(id); // async call
self.removeFromList(element.id); // see below
showSuccessNotification(); // some jQuery based notification library
} catch (err) {
showServerError();
} finally {
self.markBeingRemoved(null);
}
})
现在 removeFromList
只需:
const indexToRemove = self.list.findIndex(e => e.id === elementId);
if (indexToRemove >= 0) {
self.list.splice(indexToRemove, 1);
}
现在我有一个使用列表的 React 组件。它像 @inject('ListStore')
一样被注入。然后我将它作为道具传递给子组件。使用它的子组件,都是mobx-observer
s.
我收到这个晦涩的错误,Google 对此一无所知:
mobx-state-tree.module.js?9486:50 Uncaught Error: [mobx-state-tree]
This object has died and is no longer part of a state tree.
It cannot be used anymore.
The object (of type 'Template') used to live at '/list/1'. It is
possible to access the last snapshot of this object using
'getSnapshot', or to create a fresh copy using 'clone'. If you want to
remove an object from the tree without killing it, use 'detach'
instead.
at fail (webpack-internal:///467:92:11)
at Object.get (webpack-internal:///467:1409:17)
at Object.get [as id] (webpack-internal:///33:1682:28)
at dehydrate
at dehydrate (chrome-
extension://fmkadmapgofadopljbjfkapdkoienihi/build/backend.js:8154:24)
at dehydrate (chrome-
extension://fmkadmapgofadopljbjfkapdkoienihi/build/backend.js:8154:24)
at chrome-
extension://fmkadmapgofadopljbjfkapdkoienihi/build/backend.js:7285:20
at Array.map (native)
at Bridge.flushBufferSlice (chrome-
extension://fmkadmapgofadopljbjfkapdkoienihi/build/backend.js:7280:33)
at Bridge.flushBufferWhileIdle (chrome-
extension://fmkadmapgofadopljbjfkapdkoienihi/build/backend.js:7268:15)
fail @ mobx-state-tree.module.js?9486:50
get @ mobx-state-tree.module.js?9486:1367
get @ mobx.module.js?cbdf:1638
dehydrate @ backend.js:8154
dehydrate @ backend.js:8154
dehydrate @ backend.js:8154
(anonymous) @ backend.js:72
flushBufferSlice @ backend.js:7280
flushBufferWhileIdle @ backend.js:726
有趣的部分来了:如果我将 removeFromList
的调用放入 setTimeout(..., 1000)
, 有效!
为什么?
该错误是由react开发者工具触发的
他们在内存中保存了一个已死亡的对象,这就是他们投掷的原因。在没有 devtools 的生产中,它们不会触发该错误。