Nick Luger Nick Luger - 1 year ago 185
React JSX Question

Can a Mobx State Tree cause "race conditions" / works only with setTimeout?

Using mobx-state-tree. I have a

ListStore
which contains this action:

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);
}
})


Now
removeFromList
simply does:

const indexToRemove = self.list.findIndex(e => e.id === elementId);
if (indexToRemove >= 0) {
self.list.splice(indexToRemove, 1);
}


Now i have a React component that uses the list. It is injected like
@inject('ListStore')
. Then i pass it to subcomponents as props. The sub-components that use it, are all mobx-
observer
s.

I get this obscure error, which Google does know nothing about:

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


Now comes the interesting part: If i put the call of
removeFromList
into a
setTimeout(..., 1000)
, it works!

Why?

Answer Source

The error is triggered by the react developer tools.

They are holding in memory an object that died, and that's why they are throwing. In production without devtools they won't trigger that error.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download