Transcript from the "State Mutations" Lesson
>> Lukas Ruebbelke: I'm gonna show you a pro technique real quick, and then we're gonna do the challenge.
>> Lukas Ruebbelke: And so this is
>> Lukas Ruebbelke: Kind of important.
>> Lukas Ruebbelke: Let's talk about data mutations.
>> Lukas Ruebbelke: So,
>> Lukas Ruebbelke: So ideally, when you're creating an application that you want to one, minimize state but you want your state to be immutable.
>> Lukas Ruebbelke: The issue is, when you have an application, if everything is immutable, how do you do anything? Every application, the user has to interact in a meaningful way. And so, invariably, you are going to have to have state mutations. Now to be clear, mutable state in itself is not a bad thing.
[00:01:16] Shared mutable state, on the other hand, is the devil's handiwork. Because when you have two things that have a reference to a property or an object of some sort or state that is shared between them and either one of them can mutate it. Now, essentially they are holding each other hostage.
[00:01:42] Because let's say component A can do some nefarious thing to the shared object that has an adverse effect on Item B. Does that make sense? So essentially, if you have two things that can actually mutate a shared object, well, and you have no control over what the other thing does, you're kind of at the mercy.
[00:02:06] That is a recipe for unpredictability. And so this is one of the reasons why even I think inheritance is really dangerous. Because now you have this implicit trust that, hey, everything is gonna work out. You're gonna do everything in my best interest, and that's not always the case.
[00:02:23] So, mutable state is not a bad thing. Shared mutable state is where things go wonky.
>> Lukas Ruebbelke: So in the case of a form, what do you do? Well the answer is [SOUND]. You isolate that state or that state mutation to that component. And so let me show you how to do this.
[00:02:51] And actually I'm super stoked cuz I actually forgot these was on the docket.
>> Lukas Ruebbelke: So we have in our form, let's go to items.
>> Lukas Ruebbelke: A form to see and edit the item details. Now the question is, if I were just passing this in and I started to actually mutate this.
>> Lukas Ruebbelke: The minute I changed it here, it would actually change it up here. And so let me actually see if I can illustrate this.
>> Lukas Ruebbelke: So this is the solution by the way to how to get around this but,
>> Lukas Ruebbelke: Input
>> Lukas Ruebbelke: Item.
>> Lukas Ruebbelke: I think I broke something, hang on.
>> Lukas Ruebbelke: Item detail, cannot read property of id line to find.
>> Lukas Ruebbelke: Hold on, I just need to update this template real quick.
>> Lukas Ruebbelke: And then I will illustrate exactly, let's just replace this with this.
>> Lukas Ruebbelke: Still no good? ItemDetailComponent. Let's see if this shows what else is going on.
[00:04:51] Not helpful.
>> Lukas Ruebbelke: Keep going down.
>> Lukas Ruebbelke: So this is interesting we're talking about debugging. On one hand I got that super helpful error of hey, use this and here's some suggested code. And then over here it's like do whatever you want cuz, I don't know what's going on here.
>> Lukas Ruebbelke: So let's see here, ID, ID, ID, somewhere in here.
>> Speaker 2: Is the item there in line two?
>> Speaker 2: I don't know maybe.
>> Lukas Ruebbelke: Let's see what happens if we do this. So I'm completely free styling here but I really would love for this to work.
>> Lukas Ruebbelke: Refresh.
>> Lukas Ruebbelke: Name of undefined.
>> Speaker 3: It's often I get that name, yeah.
>> Lukas Ruebbelke: There we go. So we're making progress. So right now you can see I'm binding to something that doesn't exist.
>> Lukas Ruebbelke: Okay, let's change this up. Just a second.
>> Lukas Ruebbelke: I'm gonna make this work, or else.
>> Lukas Ruebbelke: Did I forget a description? ID of undefined. What the?
>> Lukas Ruebbelke: Wait.
>> Lukas Ruebbelke: All right.
>> Lukas Ruebbelke: All of that to get to here. So just refresh the page. Now, here's the issue.
>> Lukas Ruebbelke: I'm sending in an item,
>> Lukas Ruebbelke: Now it's into the form. The minute that I touch this and start to mutate it,
>> Lukas Ruebbelke: Look what has happened. Because I'm passing by reference, that when I edit this here in the form, notice that it is updating over in the list.
>> Lukas Ruebbelke: So how would I back out of this? I've already mutated the object. How do I essentially keep this? We're really backed out of this operation.
[00:08:18] What if you start to type and you're like, I didn't really want to do anything. I want to basically abort this. How do you do that? Unfortunately, you've already performed a mutation. That's a problem. And so, again, I've done this to illustrate that shared mutable state, you can edit it or mutate it to one place, and it's somewhere else.
[00:08:45] That cold have adverse effects. So, let me just back out of this and
>> Lukas Ruebbelke: And by the way to make that work what I had to was actually, basically use an initial default value in the parent component to initially, essentially seed or populate that property binding that I had.
[00:09:15] Let's go back here and we'll delete this.
>> Lukas Ruebbelke: And we're gonna go here and back into my item detail component.
>> Lukas Ruebbelke: And let's talk about how to isolate state mutations to a single component. What we're doing here, is,
>> Lukas Ruebbelke: Using a setter method, on the input. So essentially, instead of setting the property directly, when somebody goes to set the property, it actually calls the setter method.
[00:10:01] And so what we're saying, is when item gets set from the parent, we actually want to intercept that with a method. And then using object.assign, we actually wanna create a copy of this object. And in this case it's value. We essentially want to create a local copy of item and assigned it to selected item.
[00:10:31] Now what I'm also doing up here is I'm setting original names. So this is purely a thing and I'm just keeping track of the original name. So that I can go over here and,
>> Lukas Ruebbelke: When we go to items, I still have kind of track of like you're editing this.
[00:10:53] So I'm just preserving the original name. But, because I'm creating a copy using object auto sign in here, in my template
>> Lukas Ruebbelke: When I edit my item, I'm actually editing selected item. Then when I'm ready to save it and I'm like, hey this is good, then we go, click, Save.
[00:11:26] And we're not omitting the original item. We're omitting the new item to be passed to be to the parent to then be passed to the service. And so again, state comes down, events flow up with essentially instructions or new state to be applied further up the chain. And so, what I just really wanna call out here, is using the setter method.
[00:11:51] When we set item, I'm just trading a local copy so that we can mutate that all day long. And if we wanna throw it away, well that's totally fine. Because we haven't changed anything anywhere else. But when we're ready to commit it, then we just service it to the parent component.
[00:12:09] And so this is actually a pretty fundamental component or technique for isolating state change when you have a component with a form. Is pass in the data model via input, use object.assign to create a copy of it, mutate the local copy. And when you're ready, then you can send it back up, or you can throw it away.
>> Lukas Ruebbelke: Does that make sense? Yes?
>> Speaker 2: This is where we might get into a problem that has nothing to do with the channel. But assign doesn't do a deep clone.
>> Lukas Ruebbelke: Right.
>> Speaker 2: Right. So when you got a object that has multiple levels and things like that.
>> Lukas Ruebbelke: Right, so if you have an object that has other objects.
[00:12:52] So just actually thank you for pointing it out. Object.assign does not do a deep clone so depending on what you're sending in this may not be sufficient. In most cases when dealing with simple objects, it's totally fine but just be cognizant. It is a shallow copy and if you need a deep copy, there are thousands of ways to do that.
[00:13:17] I mean, there's just libraries. I mean, there's plenty of utilities to help you essentially accomplish your deep clone dreams. I think underscore, I think every one of them has a, you know it's a pretty standard utility function.
>> Lukas Ruebbelke: Make sense? So this is actually a really important concept that once I realized, this was kind of as I'm going into this reactive stake down, event up, redux.
[00:13:46] That was one of the big questions I have is look if we're moving to an immutable world, what do you do about forms? You have to change stuff. And so I went and talked to actually well, Bob Brumworld really actually helped me out quite a bit. But Paul Taylor who works in RSJS, in a couple of different lines.
[00:14:04] Really the consensus is like look, mutable state is not bad as long as you do not share it. What you need to do is isolate it, and this is really kind of the best way to do that. Is now creating a local copy to mutate and we're not touching essentially the shared object that we're parsing in.