Current section: Control Props 30 exercises
solution

Control Props

Loading solution

Transcript

00:00 Super. So let's dive into our toggle component now. We are accepting the on and on change, but we are aliasing on to controlled on because our toggle component actually destructures on from useToggle. So this is the actual state,

00:16 and here is the controlled state right here. So we want to forward that on, lot of ons here, but we're going to forward this to useToggle. Now, diving into useToggle, we need to accept that as props or properties or options,

00:35 I suppose, and they're going to have the same types as this. So I'm going to actually just grab these and go up here and stick those right there. Now, I can add on, which again, we have on defined right down here. So I'm going to alias that to controlled on and on change.

00:54 Then we need to determine whether we are in a controlled state. So you'll notice that over here, there is no on prop, and so on could be undefined. If it is undefined, then we are not in a controlled state. If it is defined, then we are in a controlled state. So what we can do here is say,

01:12 const on is controlled based on whether we've been given a value for controlled on. So if we've gotten an on prop, then we are controlled. So with that now, we can determine where does our on state come from.

01:29 So our on comes from state.on, but only if we are not being controlled. If we are being controlled, then it should come externally. So if we're in a controlled state, then we're going to use the state that we got from our parents. Otherwise, we'll use the state that we manage ourselves.

01:47 Actually, we can stop right now and do a quick check. We could initialize both on to be true. Now we're passing on as true, and these should initialize to true. So we are referencing the parent state, and interestingly, I can't check this off anymore because we haven't implemented the on change yet.

02:06 But yeah, so we're in a good place currently for our exercise. Let's continue from here. So there's this giant block of text. I'll try to help you understand what is going on here. But what we need to do is when we say dispatch, if we're uncontrolled, like in this case,

02:27 then updating our internal state works great. If we are controlled though, updating our internal state doesn't do anything for us. We need to tell our parent, hey, I'm supposed to change. So like, or at least if I was in charge, I would change, but you do whatever you want to with this information. And so we're going to make a new function

02:46 called dispatch with on change, which is going to take an action, which is our toggle action. And then it's going to manage all the, determining whether we should call on change and whether we should update or dispatch. So I'm going to update both of these to call this instead,

03:04 and it can return dispatch action. So that's just a refactor. We didn't actually change any behavior there, but now we need to determine, do we even bother calling dispatch? So if on is controlled, or rather, if it's not controlled, then we are going to call dispatch, okay?

03:23 We are managing it internally. We got to update our internal state. So I can save that and our uncontrolled should still work. So we're in a good place there. Now we just need to let our parent know, hey, if I was in charge, then this is what change I would make. So we need to determine what is the change I would make. And the interesting thing about reducers

03:43 is that you don't have to call dispatch for the reducer to be called. You can actually call the reducer yourself. So here's the new state, would be a reducer with the state in action. That's interesting. And so I know what the suggested changes are, almost, because this state is not necessarily correct.

04:03 This is my internally managed state, but I have some state that could be externally managed as well. So we're going to merge our current state with the externally managed state. And now based on, if my state was this, and I dispatched this action, then this is the state that I would have.

04:21 That is our suggested changes right there. If I was in charge, this is how the state would change, but you do whatever you want to do. And so now if an on change function is available, then we're going to call it with that new state, our suggested changes, and the reason for those changes.

04:39 And that is the control props pattern. Boink, boink, boink, boink, boink, boink. And that totally works. We reset, we can do this one, we can do that one, that one, and back and forth, and reset, and then our uncontrolled still works. And that is the idea. All of this text trying to explain that relatively simple function.

04:58 So instead of dispatching our internal state, we only do that when we are not in a controlled situation. And in any case, we're going to let the external world know what state change is going to occur, and why it occurred, so that they can do their logs or whatever they're going to do.

05:18 And then when we are in a controlled situation, we reference the controlled value rather than our own value for state. Those are probably the two most important aspects. First, that you reference the external value, the value that's coming in, rather than your internally managed one.

05:35 And then second, that you let the external world know when state changes happen, and what state change would happen if you were in charge, and why they are happening. And that is the control prop pattern. This does get a little bit more complicated when you add a bunch more elements of state, but I think that you can derive

05:54 how that would change things yourself. So there you go. That is the control props pattern. I hope you had a good time with that.