Check out a free preview of the full Hardcore Functional Architecture Patterns in JavaScript course
The "Using the ask Method & Lenses" Lesson is part of the full, Hardcore Functional Architecture Patterns in JavaScript course featured in this preview video. Here's what you'd learn in this lesson:
Brian continues to build the application started in the previous section so that state is merged automatically when the ask method runs, uses lenses to alter state in an elegant and immutable way, and builds reducers that compose and are unary functions.
Transcript from the "Using the ask Method & Lenses" Lesson
[00:00:00]
>> Lenses y'all, right? Let's bring those in. So bring in a lens prop, And over of n, let's also get removed for destroy because I like, I don't have to do these weird splices and whatnot. We'll come we'll get that from lamda, so now on create we can say, fact append array.
[00:00:29]
So we can do over state and we need to make a lens prop for the habits. That's what we want to change right elda habits, overhead habits. We want to sorry states the last argument. We want to append the habit. Cool, forgot a little. And let's go ahead and make our little lens namespace and we could probably just do this in mind.
[00:00:59]
Yet habits and that will be lensProp, Habit. Cool, one thing about this little autocomplete thing, it tells me I actually imported it right, so that's nice. Cool, so we all see how that works. Let's see if that goes through a, b not working at all. [LAUGH] All right, what's happening here?
[00:01:27]
So we're saying over the habits, append the habit. And do you believe that should work, so anybody see any issues?
>> Structure the habit.
>> Habits in your own lensprop.
>> Thank you that's it. Good i b, c it's so nice. All right and if I destroy let's get rid of cleared the whole thing out, I did that on purpose.
[00:01:59]
[LAUGH] All right. So let's do the same thing with lenses why not over habits remove the ID x remove one is remove is basically like splice or the state traffic. And then were run this a, b and c the actual property, cool letter b, so we're doing great, we're very happy.
[00:02:26]
We're using Montes, we got all the stuffs but one thing that kind annoying me is that each time we're having to kind of, how do I say this? We have to deal with this state and managing, like adding to it. What if instead, we actually returned, we just returned a state and it just merged it for us.
[00:02:53]
We didn't have to deal with merging this stuff, right? So this object assign for instance is saying I have a state and it's on you as a developer of our app, as we add new actions over time to always make sure you merge the state back in. What if you could just return merge and it's a monoid.
[00:03:20]
Right, monoids for the wind, so now I don't have to worry about actually object assigning my state. Let's make a monoid there. We do the same thing here, just emerge and emerge here. And so what this is gonna do is just merge, with the lenses, not such a big deal where we're just opening up the state changing something and returning a whole state back so the merge doesn't buy as much here, but down here, it does a lot like we're just turning a little bit of state.
[00:03:50]
It will merge that back into the state for us. And as we build more, we don't have to worry about always managing this whole state structure and not breaking it. We could just return the little piece that we care about everybody on board with this idea. All right, let's go ahead and make a merge.
[00:04:07]
Back to our very first thing of the day monoids. And we'll just say I will expose the X and we'll concat that by saying, get another merge. We always stay closed, object assign, make a nice copy, so we don't break anything. Maybe we can go back and try to check and make sure it's super performing and get rid of this but at the moment, we're just gonna be on the safe side and make a nice little copy.
[00:04:33]
And we'll say other .x, so we're merging our x with another x meaning plus a merge a 1, concat merge a 2, I think I want the right one to win, so that makes sense. This one's gonna overwrite this one, just how we're defining it, so work. See what happens, maybe we'll flip that, but there we go, so we get a merge.
[00:05:05]
Now I have to go update our main app loop now, right? Let's go ahead and just get rid of these curly braces killing me. [LAUGH] If you ever see me write curly braces and a function and return, I'm in a bad space mentally. [LAUGH] So, here we are, we're in this event loop and as we call these functions now the returning a submerge, right.
[00:05:32]
So what we'll have to do is get the state we wanna start with emerge of state working concat that with whatever this returns which is emerge. And then okay that concats It there's the whole thing, and we're not gonna pass a merge here. So let's just pop it out of the merge, just get it out, get it out of the type of the x after we do the operation.
[00:05:59]
Everybody see how that works? We're gonna merge the two states, so this returns a merge on each of these and then we take it out. Great, it's still working. How about that? And we click B, and it's showing B, hooray. One thing I don't like already is that I have to call merge everywhere, so let's factor that out.
[00:06:22]
Let's put that back down into our event loop will get it out of these these little functions that are just returning little bits of state now and they're all being merged, not super nice. So we'll just put this in a merge down here, cool. It's getting a little bit out of control.
[00:06:44]
Let's go ahead [LAUGH] and do that or something for the time being. All right, and we'll concat these two right here, and we'll get the x, there we go. So it's a little bit ugly, I'm not gonna lie, but that's fine. Not ugly conceptually, that's a lot of nesting.
[00:07:02]
But up here, when we're actually defining our functions, look how clean this is. I don't know if you've ever used redox, but there's the littered with switch statements and what not, okay? We know that state gets passed in each time. And we know we can flip arguments around and we can use readers to kind of factor that out.
[00:07:23]
And I noticed, I'm not using state down here, right? I'm just ignoring it, so why do I have to pass it in every time? Why do I have to deal with it? Now they just returned a little bits of state. How do I how about we only ask for it when we want to map over the state and then we'll do look how nice this worked out.
[00:07:44]
I can cancel out the state's boom, boom. So it's just a first class function that passes in the state. All right, that's neat and now this is just a function that takes a habit. Hey look, that function is like a normal function. [LAUGH] It's not a reducer anymore.
[00:08:06]
So let's go ahead and do that for these let's get rid of the state here and we'll do the exact same pattern here, we'll map over, we'll ask for the state and we'll get it back. And then down here we get rid of the state all together, we don't even have to ask for it, we're fine, okay, how do we how do we implement that, right?
[00:08:27]
Well, we have to go get asked right off the bat, so let's get a function from our lib types, and function has asked so just ask from function. Great, and then we'll use functions down here to model our stuff. Now I could wrap this in a function and all that, but I'm gonna say this is a function that returns the FN type, right?
[00:08:59]
And this one I guess I could just put that right there just for now and say, okay, well, I have a function of that. I believe we can factor this out again to get back to that or not, I'm not sure yet. We'll figure it out, so, where are we?
[00:09:19]
Instead of calling our function a state now, we're just caught with the payload, right? But then we run that thing with the state and it can choose whether or not it wants to use it. All right, compiled successfully, look at that. Going over here, a, b look how nice that is.
[00:09:40]
I could delete it, yep, I can show it, yep. Cool, all right, so now we're able to just pull state out of nowhere. [LAUGH] And, in return little bits we're gonna do here is say, all right again, the structure of this application can be different, right? We can pull this out into our app loop.
[00:10:05]
We can pull all this stuff out into our controller. We can move this into a library and so we don't have to here. And honestly, I don't care that we are, you know, hit a point where I want to move those into a controller and a little model and utility libraries and my little main function, which is the app loop.
[00:10:31]
But you typically see a lot of functional programs like this, because it just doesn't matter. And so I think it eventually matters and that's when you do it.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops