- Overview
- Transcript
2.2 Making our Filter Declarative
In this lesson, we'll apply the declarative style to our filtering events, creating functions to do our filtering for us.
1.Introduction3 lessons, 14:53
1.1Introduction01:13
1.2A Refresher on Functions08:57
1.3Project Walkthrough04:43
2.Some Basic Improvements5 lessons, 36:51
2.1Getting Declarative09:20
2.2Making our Filter Declarative08:21
2.3Becoming Familiar With Higher-Order Functions05:22
2.4Callbacks, the Other Higher-Order Function06:15
2.5A Look at Pure Functions07:33
3.Building a Functional Utility Library4 lessons, 29:00
3.1Functional Filter02:52
3.2Understanding Map and Reduce10:41
3.3Reorganizing Our Collection With GroupBy08:13
3.4Getting Creative With Pluck and Mean07:14
4.Some Existing Tools2 lessons, 14:47
4.1Underscore and Lodash07:55
4.2Native JavaScript Functions in ES506:52
5.Conclusion1 lesson, 02:36
5.1Conclusion02:36
2.2 Making our Filter Declarative
So, we've just gotten started doing a little bit of converting here from what started as more imperative style, and changing it over to be a more functional style. We did that with these two functions over here, loadBeers and setActiveFilter, and now we're gonna take it a step further and transfer or convert the filtering that's done down here. So, let's take a look at how we're doing it now in the, in imperative style. We're repeating the same for loop, so if you remember, wherever we're repeating code, it's a really good candidate for replacing with a function. So, you can see we're doing the same for loop over the beers list, and then, we're checking to see in each case if a certain key on each beer object matches a certain value. So, this should be o, a place where we can write a function to do this filtering for us. So, let's go back up here, where we're defining our functions at the top, and we'll do filterBeers. And, we're going to take the property and the value. Let's just go ahead and copy the domestic case. I'll actually cut that out of there. And we'll just swap out a few things. Okay? So, we can go ahead and just use the global beers cuz we're getting it up here now. Okay? So, we have access to it in the scope. We'll talk later about whether or not that's a good idea, but for now, we're just gonna leave that alone. And, so, we're looping over that and here we're hard coding the check against this locale property. And, so, instead we're gonna use bracket notation to swap in whatever the value of property is. And, then, we don't wanna check it against a hard coded string. I'm going to actually check it against the passed in value. And, so, we need to actually create our filtered beers array and pass it back. We'll push onto it if it matches the criteria. And then we'll return. So, now, we have a working filteredBeers function. Let's just try it with domestic. So, filteredBeers, now, now, in this scope, cuz we can run inside of this function here, synonymous function. So, we have this empty array filteredBeers, and we're gonna set it to be the result of our filter beers function that we just created. [SOUND] The property is locale and the value we care about here is domestic and let's refresh the page and we'll get all of our beers back and clicking on Domestic still does the filtering that we want. We haven't broken anything else. So, if we start to replace this, all right. So here's Imports. That works, so, here, we wanna know if type equals ipa or if type equals ale. So, our function doesn't handle this case yet. So, we need to do a little bit of modification to make sure our filter can adapt to whatever we want here. Let's take a look. My first thought is to just check right here and see if this is an array. So, we can use Array.isArray, [SOUND] and that will tell us if value is an array. But what if it is? Well, now, we actually have to do another for loop and then, do an if statement inside that. This function is getting to be pretty crazy and complicated. So, using this declared of style, I'm thinking maybe what we need to do is instead of this kind of hard coded property check. What if we created another function that did the comparison for us? Instead of doing this check we'll just do if compareValues. We'll pass it the beers, beer that were on the current object and the property and the value. [SOUND] And, that should take this information and convert it into a true or false to see if the criteria match the way we want them to. So, down here, we can create a new function, compareValues, which takes a beer or, in this case, we can even make it a little more generic and say, an item, a property [SOUND] and a value. [SOUND] And, if it's not an array, then, we can just return, does the item property equal the value? And that's our old case. So, everything up to now should work and then, what we have to do is now solve for the case where it is an array. So, otherwise, since we've already returned here, we don't have to do an else. We can just say otherwise will loop over, the value is an array there. Even though, it's still called value. And, now, for each of these, we'll check item property against value, but now, instead of the array itself, we'll actually get the, the item that we're on. So, if there's an array of values there, we wanna check each individual one, and if any of them are true, we will return true. And, otherwise, the end here, we can return false. So, if three returns, we return a check against the property and the value directly, if it's not an array. Otherwise, we have to check one. So, if at any point we find a match, we'll return true, and if it falls all the way through here because it never found a match, then we wanna return false. You should notice here that this means that this compare values function can only do or comparisons. So, if you give it, so, let's go ahead and look at what we're going to do, we're going to give it an ipa string and an ale string. Now, in our case, this is okay because it can never be both. But if you wanted to do a more complicated comparison, you wouldn't be able to, right? You couldn't even say, you couldn't do two properties. You couldn't say, can, if type is ipa and locale is domestic, like, there's no way to do that kind of mix and match on the filter. So, the filter is still pretty narrow. But, it's gonna address all the use cases that we have currently. So, we're gonna go with it for now. So, that means for here, filteredBeers, now equals filterBeers again, the same function. And, we'll do type, but Instead of just a string, we'll do an array where either ipa or ale. And, that's definitely nicer than this for loop for sure, cuz now, we can just look at this and say all right, we're filtering the beers on type, and we wanna know if anything is either an ipa or an ale. And, we'll just quickly add these other two for lager and stout, and now our switch statement is way more readable, right. You can look at this and say, it's still a little bit repetitive in places, maybe we could clean that up. But, from where we came from, this is a huge improvement, because now we can say, in the domestic case, we wanna filter the locale for domestic, and so on and so forth. And, this code just reads, it kind of self documents, and tells us what's going on inside of the code. So, let's save this and just make absolutely sure that it works. I'm gonna verify that for us. Domestic, Imports, Ales, Lager, Stouts, oh, we messed up the stout one. Oh, filteredBers isn't going to work. So, I'll just save that again, refresh, and we'll click on stats and we're back to everything working the way we want. [SOUND] So, this is a really good improvement like I said, but it also is fragile because the function that we just wrote is very specific. It does some comparisons in here that are specific to what we need right now, but if we were to need something more complicated at any point, we'd have to re-write these functions, and that's just not a great foundation to build on. If we want to give ourselves more power, to actually be flexible with this kind of filtering, we're gonna need to take advantage of something called higher-order functions, which is a huge, huge part of what makes something functional. And, so, we're gonna take a look at that in the next video.