State management in ClojureDart
Introduction
Today we will focus on state management in CLJD. In the past article, we made a quick application with a global state with defonce
function. But we can make things better thanks to re-dash a package for CLJD to make state management clearer and more efficient.
Re-Dash an introduction
Re-dash is based on re-frame state management for ClojureScript. It is developed by Werner Kok.
It will allow us to make some handling events and react in the view with subscribe.
If you want to know more about what I'm talking about re-frame has nice documentation about the concept: data loop.
Local vs Global state
Re-dash can be compared to Riverpod in Flutter. Because it allows us to create some global state and manage it. For all local states as we do in Flutter with flutter_hook for example prefer use atom
.
But how can we use it for CLJD? Let's take a look at some code.
The model
Before using re-dash you will need to import it in the deps like so:
Now let's make a file named albums_model.cljd
in a models folder, it will contain all the business logic of the app, paste this code into the file:
As we can see we first make a function named register!
we will use it later. But the important part here is that we use a function named rd/reg-event-fx
, rd/reg-fx
, rd/reg-event-db
, and rd/reg-sub
. Let's take a look at each function.
rd/reg-event-fx
& rd/reg-event-db
: this is the act of registering an event handler that can be dispatched from.
rd/reg-fx
: this is the act of registering an effect handler, here to handle the side effect of an HTTP call.
rd/reg-sub
: this is the act of registering a subscription function that can be subscribed to by any widget to query the derived state value (when it actually changes)
::refresh-albums
: this function has the purpose to call the fetch-albums. It's well useful when we need to refresh the list.
::fetch-albums
: will fetch from the API function the albums list. And dispatch (call another function in re-dash), ::populate-albums
and past some result of the call.
::populate-albums
: this function will change the state db
by using the albums param. And thanks to the assoc
function we can add a key/value to db
, (assoc db :albums albums)
.
::get-albums
: with two params we can see the first param is db
it's our state. It contains all the states we have made like the :albums
ones we have made with the ::populate-albums
.
If you want to know more about each re-dash capability take a look at this documentation.
Now we have our model in place we can use it in the view.
The view
Let's change the main to be more concise:
The important part here is the (albums-model/register!)
function, we need to put this before the run function. To be sure the model will be instantiated only one time.
And create a new file named albums_list.cljd
:
First, we dispatch (rd/dispatch [::albums-model/refresh-albums])
to fetch the list when the view is rendered for the first time, then we can watch
a re-dash function we have made like so:
:watch [albums (rd/subscribe [::albums-model/get-albums])]
This function will refresh the tree when the albums
in db change.
When we pull to refresh the list, we call it with an anonymous function the dispatch event from re-dash #(rd/dispatch [::albums-model/refresh-albums])
This will call the refresh-albums
in the model and fetch the list again.
Conclusion
And it's done, we have separated the business logic to our view thanks to re-dash package! Enjoy coding! I would like to thank Werner Kok, for this amazing state management package, and the review of this article!
Like always feel free to fork/clone/reuse the code I use for this article: