Globalizing Curried Selectors
Several weeks ago, I wrote about Globalizing Redux Selectors. At the end of the post, I showed an implementation using Ramda that works for selectors taking any number of arguments. I later discovered that the solution doesn’t allow globalized selectors to be called as curried functions. Let’s fix that.
Refresher
If you have no idea what I’m talking about, I recommend reading the original post and the one it refers to.
As a quick refresher, we’re assuming a Redux application that uses a modular structure. In some contexts, we want to have selectors that work on a local slice of the state tree (localized selectors). In others, we want those same selectors to work on the entire state tree (globalized selectors).
The solution we came up with is to export the localized selectors by name, and then default export an object containing the globalized selectors.
At the end of the previous post, we came up with the following code for creating globalized selectors from local ones:
What’s the Problem?
Since I writing that post, I ran into a case where one of my selectors was curried, and I wanted to call the globalized version of the selector in a curried fashion. It didn’t work.
If you’re not familiar with Ramda’s curry
function, see Thinking in Ramda: Partial Application.
Here’s a simple test case that I wrote to illustrate the problem:
The first test (calling the selector normally) passed, but the second one failed.
Looking at our original code, it’s easy to see why: we’re not currying the globalized selectors. Let’s take care of that:
Hmmm, that didn’t work either. You can’t curry a function that takes a variable number of arguments; in that situation, curry
assumes that the arguments you’ve given it are all there are going to be.
What we need is a way to tell curry
how many arguments to expect.
Fortunately, Ramda also has curryN
that is like curry
, but also takes the number of arguments to expect. Perfect!
But how can we know how many arguments to expect? This is a general utility function that is supposed to work with selectors that take any number of arguments. We can’t just hard-code an arbitrary number.
We have the original selector, and it knows how many arguments it needs. We can use Ramda’s length
function for that.
That should be everything we need.
That works!
This version of globalizeSelectors
has handled everything I’ve thrown at it so far. Crisis averted!