nank1ro / solidart

Signals in Dart and Flutter, inspired by SolidJS
https://docs.page/nank1ro/solidart
MIT License
163 stars 7 forks source link

Some clarification #13

Closed sanihaq closed 1 year ago

sanihaq commented 1 year ago

HI, thanks for this amazing package. I have some question regarding disposing of a signal.

When using this way -

Solid(
      providers: [
        SolidProvider<FilesController>(
          create: () => FilesController(),
          dispose: (controller) => controller.dispose(), // does dispose gets automatically called, I dont have to dispose else where?
        ),
      ],
...
}

or

Solid(
      signals: {MySignals.someSignal: () => createSignal<bool>(false)}, // I have to dispose, when I dont need it any more?
...
)

Hope I manage to explain it properly. Thanks.

nank1ro commented 1 year ago

Hi, thank you for choosing solidart πŸ’ͺ

When using the Solid widget, the life cycle of signals and providers is automatically managed by Solid. This means that when the Solid widget is removed from the tree, all associated signals and providers are automatically disposed. You don't have to dispose them yourself, Solid knows the exact moment when you no longer need signals and providers.

For providers, there is the dispose method to be added manually as you decide what to do, since I do not know the shape of the class. In other words, I do not know whether your class contains a method called dispose. This means that you can also call a method called controller.cleanup() or whatever you need.

sanihaq commented 1 year ago

@nank1ro so I don't have to think about cleanup at all. Except when I'm creating my own provider, in that case I have to create a β€œdispose” (or any name) method and handle all the signal inside that provider and pass that to the initial Solid widget. Is that it?

p.s. I love the documents for how simple and straight forward it is. The examples are great too. But I think it can be a little more fleshed out. And example with testing would be great too.

nank1ro commented 1 year ago

Yes, to recap:

Solid(
      signals: {MySignals.someSignal: () => createSignal<bool>(false)},
...
)

☝🏼 signals created inside the Solid widget automatically dispose

SolidProvider<FilesController>(
          create: () => FilesController(),
          dispose: (controller) => controller.dispose(),
        ),

☝🏼 providers created inside the Solid widget will call the dispose method you provide In your FilesController dispose method you have to dispose all the signals or resources you have created inside.

Thank you for your suggestions! I'm surely going to add a testing chapter to the documentation. What else do you think needs to be explained more in details?

sanihaq commented 1 year ago

@nank1ro ok, got it. πŸ’‘πŸ‘Œ As I said, simplicity is really a plus point for this package. There are a lot of simple to get state management available out there (e.g. riverpod). But are not seems so easy at first glance (and that's a pretty negative point from my point of view). So, keep the simplicity (in the docs and in the package). That being said, I wouldn't mind further resource to get more performance out of this package. Like, do I have to use a stateful widget everywhere to get a provider. As a general rule, we should have less not more stateful widget.

Thank you. I hope this get much more wide adoption in the future. Good luck.🀞

nank1ro commented 1 year ago

One of the mission of solidart is to be simple to use and understand. This is never going to change. So thank you again for choosing it and I hope to improve it always better πŸ˜‰

I don't understand why you have to use a StatefulWidget to get a provider. It's not a performance issue to get it from the build method.

To explain this please let me first tell that StatelessWidgets and StatefulWidgets are the same about performance. If you are using a StatefulWidget you aren't losing performance. The performance consideration is simply how often the build method is called.

Using solidart you never call setState() because you handle the state with a signal. You have fine grained reactivity out of the box.

Providers are not state. They contain state. This means that when you get a Provider you are not reacting to its state.

You can get a provider in the initState, in the build method or even in a callback, like onPressed. You're not going to experience any performance issue.

Every Widget has an internal Map called _inheritedWidgets where all the InheritedWidget ancestors are stored. When you call context.get you're just getting a value from this Map. You're not traversing the tree every time. This operation is performed automatically by Flutter when it creates the Widget for the first time.

sanihaq commented 1 year ago

@nank1ro yes it makes sense of what you said, perhaps I came to the wrong conclusion seeing it in some example and not thinking of other possibilities. My bad. As for StatefulWidget I still think we should avoid it if it's not necessary. Because it might confuse later. StatefulWidget comes with extra complexity (not to mention looks busy, unclean). So, generally StatelessWidget should be encouraged where's possible.