Context through the tree hierarchy #2162
-
Hi, new to TS/RN/mobx/MST so this will be a noob question. As I understand it MST gives me a tree-like hierarchy of models. I wonder if it's possible to set a context for a portion of this tree. For example if I had an application with several accounts - could I contextually apply the account ID to all sub-models of that account? for the purpose of API calls? Here's an example from the MOBX documentation: https://mobx-keystone.js.org/contexts/ const usernameCtx = createContext<string>()
@model("MyApp/SomeParent")
class SomeParent extends Model({
username: prop<string>(),
// ...
}) {
onInit() {
usernameCtx.setComputed(this, () => this.username)
}
}
@model("MyApp/SomeDeepChild")
class SomeDeepChild extends Model({...}) {
@modelAction
someActionThatRequiresUsername() {
const username = usernameCtx.get(this)
// ...
}
@computed
get someComputedThatRequiresUsername() {
return usernameCtx.get(this) + " is awesome!"
}
}```
What would be the equivalent in MST using the React ContextAPI? I tried to use the above but I don't seem to be able to import `createContext` from mobx - is it a deprecated function? (I understand the context API in react is newish so some libraries might have come up with their own context stuff first)
I've struggled to search for answers to this question, as every mention of 'context' + 'MST' shows me examples with React components using contexts to access MST models and using context provider tags inside those component trees.
Is the correct thing to do here to hold this contextual relationship on my react tree? My understanding of the philosophy of MST is that we have a *separate* model tree to the components tree? |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 8 replies
-
Just a follow up that I found this example: Is it expected to use 'getParent' for this sort of thing? I presumed that would break encapsulation? |
Beta Was this translation helpful? Give feedback.
-
Also as a heads up, the example you gave is from MobX-Keystone, which is a different take on MobX-State-Tree. The two libraries are pretty incompatible, but they share many similarities since Keystone was an attempt to build a similar system to MST. I know it's confusing, especially since the docs site kind of looks like ours. Sorry for the mix up there. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the replies! Maybe I'm misunderstanding the 'tree' part of 'mobx
state tree'. I assumed I would in some way be able to apply something to a
subtree or navigate the tree as I can with react providers and contexts
…On Sat, 9 Mar 2024, 17:57 Tyler Scott Williams, ***@***.***> wrote:
Also as a heads up, the example you gave is from MobX-Keystone, which is a
different take on MobX-State-Tree. The two libraries are pretty
incompatible, but they share many similarities since Keystone was an
attempt to build a similar system to MST. I know it's confusing, especially
since the docs site kind of looks like ours. Sorry for the mix up there.
—
Reply to this email directly, view it on GitHub
<#2162 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAJWOW34TMQ2KYXOW46DOXLYXNERRAVCNFSM6AAAAABEOEEVEGVHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM4DOMZQHE2TC>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
get parent presumably doesn't work for anything deeply nested as in the
example from mobx keystone?
…On Sat, 9 Mar 2024, 19:03 Sam Duke, ***@***.***> wrote:
Thanks for the replies! Maybe I'm misunderstanding the 'tree' part of
'mobx state tree'. I assumed I would in some way be able to apply something
to a subtree or navigate the tree as I can with react providers and contexts
On Sat, 9 Mar 2024, 17:57 Tyler Scott Williams, ***@***.***>
wrote:
> Also as a heads up, the example you gave is from MobX-Keystone, which is
> a different take on MobX-State-Tree. The two libraries are pretty
> incompatible, but they share many similarities since Keystone was an
> attempt to build a similar system to MST. I know it's confusing, especially
> since the docs site kind of looks like ours. Sorry for the mix up there.
>
> —
> Reply to this email directly, view it on GitHub
> <#2162 (comment)>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAJWOW34TMQ2KYXOW46DOXLYXNERRAVCNFSM6AAAAABEOEEVEGVHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM4DOMZQHE2TC>
> .
> You are receiving this because you were mentioned.Message ID:
> ***@***.***
> com>
>
|
Beta Was this translation helpful? Give feedback.
-
I'm a little new with mst, and you probably moved on or solved this by now, but depending on how you add data, you might be able to use references: import { types, Instance } from 'mobx-state-tree';
const ParentType = types
.model({
parentId: types.identifier,
name: types.string,
})
.volatile((self) => ({
someValue: 'string',
someNumberValue: 3,
}));
const ChildType = types
.model({
childId: types.identifier,
name: types.string,
parent: types.reference(ParentType),
})
.actions((s) => ({
getParentName() {
return s.parent.name;
},
}));
const Store = types
.model({
parentStore: types.map(ParentType),
childStore: types.array(ChildType),
})
.actions((s) => ({
addParent(parent: ParentType) {
s.parentStore.put(parent);
},
}))
.views((s) => ({
getChildren(parentId: string) {
return s.childStore.filter((child) => child.parent.parentId === parentId);
},
}));
type ParentType = Instance<typeof ParentType>;
type ChildType = Instance<typeof ChildType>;
const store = Store.create({
parentStore: {
'1': {
parentId: '1',
name: 'parent1',
},
'2': {
parentId: '2',
name: 'parent2',
},
'3': {
parentId: '3',
name: 'parent3',
},
},
childStore: [
{
childId: '1',
name: 'child1',
parent: '1',
},
{
childId: '2',
name: 'child2',
parent: '1',
},
{
childId: '3',
name: 'child3',
parent: '3',
},
],
});
const parentName = store.childStore[0].parent.name;
const parentNameOtherWay = store.childStore[0]?.getParentName();
const parentVolatile = store.parentStore.get('1')?.someValue;
const parentVolatileNumber = store.parentStore.get('1')?.someNumberValue;
const childrenOf = store.getChildren('1');
console.log(
parentName,
parentNameOtherWay,
parentVolatile,
parentVolatileNumber,
childrenOf.map((c) => c.name)
); I just threw this together quickly, but for recursive types you could use the Identifiers and references are pretty cool. Keep in mind that the identifier does not have to match anything in your persisted data(it can). It's simply a way to relate one node to another within the same store. When you access the properties of the child node you get all of the actions, views, properties of the reference. There are a ton of ways to structure your data here and I'm not even close to being able to recommend any best or even good practices. So far I have tried to keep it simple and not nest things too deeply and it's worked out for me. hth! |
Beta Was this translation helpful? Give feedback.
Yes, you are correct that the environment is global. I don't think we have an equivalent.
If anyone wants to see the code in action, this does not work: