Testing and Modular Front-End

Managing State and Refactoring Code

James Halliday

James Halliday

Substack
Testing and Modular Front-End

Check out a free preview of the full Testing and Modular Front-End course

The "Managing State and Refactoring Code" Lesson is part of the full, Testing and Modular Front-End course featured in this preview video. Here's what you'd learn in this lesson:

To help handle scaling in web development, James refactors code to show how to deal with state management.

Preview
Close

Transcript from the "Managing State and Refactoring Code" Lesson

[00:00:00]
>> One thing that you might have noticed already is that this approach isn't necessarily gonna scale super well itself. We've just got all of these variables floating around. How is this gonna look when we have 20 variables all in the same scope? Not super well, it's gonna be hard to split things up into separate files.

[00:00:18]
So one thing that we can do right away that's very simple is we can just collect these properties into a variable, like an object. They call it state because it's a useful technique for kind of keeping track of every piece of information that you're going to need to render the code on the screen.

[00:00:44]
So now we just need to update every time we do n we need to do state.n. Every time we reference x, we need to do state.x. But this is generally a better way to do things than before, so it still works, it's good. One really nice thing about doing this too is if you need to log the values for all of these different kinds of variables in your program, you can do that with just a console log and you can poke around.

[00:01:16]
You could also implement some of these fancy techniques, one's called time travel. That's where you save out the states. So you could just call JSON.strigify in your state object, dump them out, and you could write a little program that maybe when you hit the left and right arrow keys will kind of step through the history.

[00:01:35]
So one of those would be pretty easy to wire up now that you've got everything that the rendering logic needs in one place. Another piece to note about how we've been wiring things up is that, generally speaking, doing things, like modifying the state inside of your event listeners, doesn't tend to scale very well either.

[00:01:56]
Because maybe you're gonna have multiple buttons that each do basically the same thing. Maybe it starts out incrementing a variable, but then you need to add more custom domain logic. So a good way of doing that is to use an event emitter. And then so the first thing you can do is require the EventEmitter library like this.

[00:02:22]
And then you can make a new EventEmitter object. I like to call it bus when I do it when I do it this way. So now instead of modifying the state in these events, we can emit an event that's like a increment dash n. So I can do bus.emit('increment-n'), and we can move these operations that actually are going to modify the state someplace else.

[00:02:57]
So what I can do is now bus.on('increment-n'). I can call the update function and I can call this state.n++. Another thing that we can do while we're sort of doing a little bit of refactoring work to make this more scalable for a bigger project is, instead of calling update directly from here, it's gonna scale better across multiple files if we use an event for that as well.

[00:03:25]
So I'm gonna bus.emit('update') or we could call it render or we could call it something like that. And then I'm gonna just listen for the update event and call update when it happens. This is gonna be nicer so that we don't have to pass in the update function if we want to factor out all of these events into their own file.

[00:03:52]
So the final thing that we need to do is now, instead of updating the state in here, we'll also commit an increment-x event, and I can move this code up here to do pretty much the same thing as we were doing with increment-n. Although, maybe x works a different way, maybe it wraps around.

[00:04:12]
And so having this logic all in one place let's us kind of put the sort of policies about how the business logic gotta work in a single place. So let's go ahead and do that. So (state.x + 1) mod 4. So I think that ought to work if I update the file.

[00:04:33]
Yep, so now when I click, once I go past three it pops back around to four. Another common thing that I would do at this point is we kind of are starting to see a separation in what this chunk of code does versus what the other chunk of code does.

[00:04:52]
So this is a good time to kind of start moving some of these pieces out into their own files. So I can call this file, I call it reduce.js. This is sort of a term of the art in these kinds of applications. You have the idea of a reducer, and the reducer operates, it sort of listens for different kinds of state transitions.

[00:05:17]
And it will modify the state and also emit additional state events that it needs to. So just save it there. Now we can pass some things in as arguments. So maybe we get the event emitter as an argument and we also get the state as an argument. So now we can move all of that code into just doing this or, We can clean up the code a little bit.

[00:05:50]
Another important thing is you might also want to do something like instead of even having the event emitter exist at all, to completely remove that temptation you might just have an admit function that's gonna live in the same scope as your rendering logic. That way you can't be tempted to emit events or do things like listen on events or that kinda stuff.

[00:06:15]
Because this kind of architecture, which is more or less the redux architecture, where you have a single state object and you have a separate sort of reducer that's gonna listen for events. And then in your rendering logic, the only thing that you're gonna do is kind of emit additional events.

[00:06:38]
Maybe do a little bit of massaging the data, like dealing with things like formatting maybe different form elements into an object that you're gonna emit to make those events be relatively clean. But this is a good way of kind of separating out different pieces of logic that you might have in your application.

[00:06:59]
So just to make sure that this still runs. Yep, it's all running as before. So I got a request to add a new kind of feature, and I think this would be pretty fun. So we can modify this example now, and I'm gonna commit that in case I mess it up, refactor.

[00:07:23]
We also need to add the reduce function. So we refactored with a separate reducer.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now