How to Use Mixin to Create Reusable Multi Selection Logic
We use lists everywhere, & sometimes we need to perform single or multiple selections on those lists. In this blog, we are going to learn how to use mixins to create reusable multiple selection logic.
Many developers have heard of mixins, but they are not sure how they work or where to use them. If you have come across this question, don't worry, you are not alone. I faced a similar issue until one of my colleagues taught me how to use them.
We use lists everywhere, and sometimes we need to perform single or multiple selections on those lists.
In this blog, we are going to learn how to use mixins to create reusable multiple selection logic that can be used on any StatefulWidget.
Common Approach
If you are like me, you might have implemented multiple selection on the list like this:
Usually, we create a state variable inside a StatefulWidget that holds the value of the selected items. In the above example, we used _selectedItem variable to hold that selection state.
Although this approach works fine if you have this logic on 2-3 screens, what if you have multiple screens with the same feature and logic? Then you would want to extract that into a common, reusable class.
Now the question is: what kind of class should you extract this logic into? Should we create a class to extend it or create a class as a mixin?
Since we are mixing a logic of multiple selection in a StatefulWidget, we will use a mixin here.
Create a Mixin
We use the mixin keyword and the on keyword to apply these mixins to the given class. Check the mixin document for more details on syntax.
Every time the selection is changed, we want to update the UI using setState({}). Therefore, we need access to the setState({}) method, which we can only obtain from the State<W> class. As a result, we create a mixin on top of State<W> class:
SelectableState consists of two components:
String: represents the data to be stored upon selection.
W extends StatefulWidget: W in State<W> requires a StatefulWidget class, which can be of any type. Hence, we use W extends StatefulWidget in SelectableState.
Now, we need to store the selection state somewhere. A mixin is a class, so we can create a Set<String> variable inside it.
I've used Set<String> to avoid selecting duplicate strings. You can use any data structure you prefer based on your project's needs.
Since our goal is to make the mixin a truly reusable component, we will replace the string with a generic type T
.
Add Selection Logic to Mixin
We need to add all the common methods required to handle multiple selection logic:
💡 If your app only uses strings, keep it as a string until you need a different type. If you use T, make sure the equals and hashCode methods are properly overridden. Maybe in the future, we can implement this using a dart record. If you want to learn about use cases for records, let me know in the comments.
Using Mixin
To use a mixin in our existing HomePage, we use them with a keyword followed by SelectableState where String is the data type for the state and HomePage is the type of StatefulWidget:
Now we can access all the methods we created in SelectableState and use all those methods directly inside _HomePageState :
Conclusion
It seems overwhelming to simply extract the selection logic for 1-2 screens. But if things scale, this would be really helpful. If there is a new screen with the same logic, you just need to add this mixin using with keyword.
These also allow you to add additional methods to the SelectableState class as UI requirements change. For example, if you want to enable/disable a button based on some selection, you can create an isEnabled method inside SelectableState mixin.
That’s it for now.
You can check the example on DartPad with and without a mixin.
https://dartpad.dev/?id=fba4016af91790f123dd894197da0a74
If you want to learn more about mixins, then check out this great blog by Quickbird Studios.
If you enjoyed this post then would you be able to do me a quick favor and share my latest blog post with your friends and colleagues? I'd really appreciate it and I think it could be valuable to them.
Thank you so much!