-
Notifications
You must be signed in to change notification settings - Fork 10
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
Lifecycles #23
Comments
Yeah this is one I find I'm always explaining because it is non-obvious until it is. If you picture your app basically a bunch of nested Now if you are wondering about Components, it's the realization that if there is nothing conditional in selecting their rendering then they will live the whole life of the app. So they are tied to the topmost autorun. However, if there are conditions, then that will be it's own nested In so the best pattern for global state is Context like React since the Provider puts creation under the reactive tree.. MobX-JSX has context unlike React has no tie to the render mechanism in itself so there is no performance hit etc.. See it here: https://codesandbox.io/s/mobx-counter-context-wlu1x So the mentality here is Components are ephemeral. They serve as factory functions that maintain state by the closures created in MobX's reactive computations. So lifecycles don't make sense. In the purest sense all bindings are side effects of these computations. Those side effects consist also of nested computations which are all managed as part of each computations own lifecycle. There are no lifecycles outside of that. But since it isn't tied to a components the reactive primitives are fluid between global and local state. It's just the same pattern all the way down. Does that help? |
Thanks for so detailed explanation. I sort of understand the concepts you're talking about but Im having a very hard time to put them in practice. I understand a components render function sort of becomes "many independent computations that will react to change on their closures" like some sort of virtual subcomponents. Taking the repo examples as a use case, I make an App that has Counter1 and Counter2, Counter2 is removed from the tree after some seconds but the setTimeout on Counter2 keeps running https://codesandbox.io/s/mobx-counterclasses-2tfn8 and I cant figure out a way to remove it. Do you mean I need all the Context/Store boilerplate to get the disposal working? Thanks again |
Yeah something is broken here. |
Ok Fixed in v0.11.10. Ended up being just poorly written code which was sharing a reference. Sorry about the confusion, I probably broke that beginning of June and didn't notice until now. |
Thanks a lot! I have updated the example and wrote a class that implements componentDidMount and componentWillUnmount import { render, cleanup, Component } from 'mobx-jsx'
class Component2 extends Component {
constructor(props) {
super(props)
if (this.componentDidMount) {
console.log('adding componentDidMount')
Promise.resolve().then(() => this.componentDidMount())
}
if (this.componentWillUnmount) {
console.log('adding componentWillUnmount')
cleanup(() => this.componentWillUnmount())
}
}
}
class App extends Component2 { componentDidMount(){ } componentWillUnmount(){ } } |
Yeah I think that is right. The microtask resolution will be after mount. And the cleanup runs at the beginning of re-evaluation so the elements aren't removed until the replacement elements are inserted so they are still attached to the DOM at that point. The only place this falls apart is if something upstream decides not to insert its children after deciding to create them. For the most part I think even |
I thought I'd update this to tell you where I took this with Solid. I added features like Suspense and concurrent mode and it was problematic that we'd never know when things are mounted. My old set timeout falls apart hard. So I did figure out how to do this in an interesting way that is DOM oblivious but understands when reactive contexts have settled for the first time. The challenge is it puts me a crossroads because if I'm using hook like primitives I'd need to introduce things beyond current MobX API to represent them. It basically becomes a framework on its own.. like if I made an If I wanted to bring them up to parity I'd just be aping Solid's APIs and they'd stop being what they are more or less which is basically the end of this experiment. I could look at making Solid's reactive core itself pluggable but I don't have full control over every reactive system to work the way I want. It would be cool cause you could use existing MobX stuff and it would be seamless but I'd almost be better to provide a light wrapper over Solid with MobX's API if people wanted to port the code.. People have done that with Vue and it would work pretty well for the 90% case. It's not unlike what you have been doing to port lifecycles over to MobX JSX> I suppose I could even have MST work with Solid MobX facade. I don't really want to do that necessarily as I have great love for MobX and all other reactive libraries. But at a certain point the reactivity has to be customized to fit the problem space. There are certain things I can just do with my own reactive library I can't with others due to how they work. Or maybe I could if I could export some internals etc.. But it's considerable effort. |
Hey many thanks for the time on the detailed follow up and your considerations. The following is just me on my own context. I opened this issue originally because I needed a way to turn off "events handlers" (sockets/canvas/dom). The cleanup approach works ok and I translated it to a componentWillUnmount method just because I use classes in most situations. Nonetheless, I grew up tired of all the confusing and closely related lifecycles provided by React, it led me from time to time to some bugs that were just annoying. I do not feel the need for other lifecycles than mount and unmount, I think everything else could be handled by just leveraging a state, in any case mobx already provides ways to intercept and observe. In a closely related note I do not see the point for things like Suspend, Portals and friends, again you can handle these sorts of things leveraging a state and knowing what you are doing. If you have a bug near these sorts of utility Components you will not only have to understand your own code but you will also have to think of the internals of how suspend and friends works, so I avoid them. I understand is fascinating to provide solutions for UI architecture, I feel like most solutions are overdoing and handling edge cases. This obviously may be good for companies but for mere mortals like me I end with an incredible amount of websites all of them using slightly different versions and concepts of closely related technologies, its overwhelming. I love mobx because I do not have to think how stuff works, I can concentrate into what Im actually building, I can just do That being said I understand the need for detailed and extended solutions, solids.js looks great, I just feel I dont need the features. I tried to look at it but the syntax handling observables turned me off, if solid had provided the syntax I snipped on this post and classes I probably had been using solid by now, because everything is handled on the same library and because seems to be your main area of focus . Unless Im missing something my problem space is covered by what already is provided, split in two libraries but such is life, the simplicity seduces me. I wished mobx provided a renderer but it seems that them are also shifting paradigms and introducing more and more concepts, there must be reasons of course. Im done, Im just very thankful for what you are providing. |
That's great. And I think that's sufficient then. I love reactive primitives because I can model almost anything but some problems are difficult even for me so it's nice sometimes to give a syntax to make it just automatically handle it for you. But I'm also very particular about my approach with Solid otherwise I might just be using MobX in my core so I understand why it doesn't align. I've put more time into Solid specifically to worry about more complicated things like lifecycle (which a reactive library doesn't really have) and trying to tell a consistent story but it does complicate everything (in theory to allow certain things to be easier). I'm definitely not primarily focused on the localized problem (like looking at the component file in front of me) when working through my decisions. You can tell a library like Svelte is but it has limits elsewgere. MobX JSX keeps things simple enough with enough room to branch out that I'm glad it exists. At one point this was really all my ambition for Solid really. It's just growing beyond that. |
I was looking at the project I need to modify to use
mobx-jsx
and of around 300 classes the only thing I can see could complicate me is the lifecycle componentWillUnmount which seems to me I cant avoid it. I will give you examples:A component that sets a MutationObserver to redraw a canvas when something is resized to then turn off the observer on componentWillUnmount
A component that use sockets, like in
socket.on(......)
and on componentWillUnmountsocket.off(...)
There's seem to be a concept of cleanup via mobx, but I dont see how that will work per component, on the counter++ example I added two counters and removed one later on, the setTimeout kept running on the unmounted component. Also with mobx you can create a global state that isn't attached to any component which is very handy. On Solid you do something similar to cleanup but I guess is tuned to the component? Maybe is per file? I would prefer a componentWillUnmount lifecycle as in some situations I have many components on the same file and the intention will look more clear. Thanks in advance!
For completeness, I read on #11 that componentDidMount could be simulated by using
Promise.resolve().then(() => /*... */);
on the constructor or render function(maybe better on the render function).The text was updated successfully, but these errors were encountered: