-
Notifications
You must be signed in to change notification settings - Fork 642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactors, onInvalidation hook, types.safeReference and more #1091
Conversation
Renamed |
all done |
I think that one level won't be noticable at all, but I am not sure, need measurement.
I've just discovered, that this code was perfectly valid only up to 3.7.0 (including, https://codesandbox.io/s/vmq29xm1yl) - 3.7.1 broke it. Ability to have multiple trees is one of MST's top features. Reusing nodes from one tree in another was a bit of a pain, but it worked. Could we bring that behaviour back?
Didn't get that point. If one's reference source resides in another tree he must supply instances on create, not identifiers/snapshots. Othervise IdentifierCache should have been global and shared between all root nodes. const Source = types.model({items: types.array(MyType)})
const Refs = types.model({linkedItems: types.array(types.reference(MyType))})
const source1 = Source.create({items: [{id: 1}, {id: 2}, {id: 3}]})
const source2 = Source.create({items: [{id: 1}, {id: 4}, {id: 5}]})
// at this point we could not supply ids, because id=1 lives in both source1 and source2
const refs = Refs.create({linkedItems: source1.items}) |
Fair enough :)
I didn't even know that was supposed to be possible. I guess that's something for @mweststrate to decide?
Well, my answer was assuming that references and referenced nodes had to share a common root. Of course if they don't there's no way check if references are valid at creation time. Just wondering, if refs can be assigned to referenced nodes in other stores, what's an id assignation default behaviour? taking your example code, what should this do?
Also, if you restore a snapshot, how will the reference know into which store it should hook to find the node? |
Hmm the docs say https://github.com/mobxjs/mobx-state-tree#references
|
Throw )) |
Wouldn't this be confusing with the |
The idea I had was that standard types.reference(User, {
// given an identifier, find the user
get(identifier) {
return resolveIdentifier(someOtherStore /* this is another tree, accessed from closure, import, env or whatever */ , User /* type (living in the other tree) */, identifier)
},
// given a user, produce the identifier that should be stored
set(value /* User */) {
return value.name
}
}) |
@xaviergonz didn't review the code yet, since not all conceptual questions are answered :-). But this PR looks like a great improvement! |
@mweststrate Thanks for the feedback :)
Didn't even know that existed. I'll switch it back to safeReference then
Ah, so it is supposed to be ok for custom refs. Thanks! |
Ok, I was able to keep the invalidSnapshotIdentifier even for custom identifiers in another stores (basically in this case upon creation of the safe reference, it will try to access the node, thus trigger the getter, and if that getter does not return a node then the reference will trigger the invalidSnapshotIdentifier cause) Also I wrote a unit test to make sure that custom identifiers can use nodes from external trees (it seems it keeps working) |
Also renamed it back to safeReference |
@k-g-a added a unit test for that, but using custom references (it works) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work!
Thanks! last thing, renamed |
@xaviergonz, thanks for great work! Could you estimate how soon will it land? :) |
I'll make a new release this afternoon |
@k-g-a 3.9.0 released |
@xaviergonz, refactored our production code from volatile state to safeReferences: it works great and reduces boilerplate. Thanks for contribution! |
@k-g-a my pleasure :D |
Closes #1088 #1086 #1081
addHook(model/array/map/scalar/whateverType, 'afterCreation'..., (self) => {...})
in the future if desiredReference validation:
isValidReference
,tryReference
,onInvalidate
hook andtypes.safeReference
Accessing an invalid reference (a reference to a dead/detached node) triggers an exception.
In order to check if a reference is valid, MST offers the
isValidReference(() => ref): boolean
function:Also, if you are unsure if a reference is valid or not you can use the
tryReference(() => ref): ref | undefined
function:The options parameter for references also accepts an optional
onInvalidated
hook, which will be called when the reference target node that the reference is pointing to is about to be detached/destroyed. It has the following signature:Note that invalidation will only trigger while the reference is attached to a parent (be it a model, an array, a map, etc.).
A default implementation of such
onInvalidated
hook is provided by thetypes.safeReference
type. It is like a standard reference, except that once the target node becomes invalidated it will:undefined
Strictly speaking it is implemented as