Updating State After a Transition
We want the loading spinner to persist until the modal completely disappears.
In order to achieve this, we will use the
afterLeave lifecycle event prop for Headless UI's
afterLeave prop is a perfect fit for our use case, as it allows running code at the end of the l
0:00 This next one is not a challenge but rather a show and tell, as this is very Headless UI-specific knowledge. We want to persist the loading spinner all the way until the modal has completely disappeared, which is not the case right now.
0:12 Our Modal component is using Headless UI's transition component, and you can see different props like enter, enterFrom, enterTo, etc., but the Transition component also has lifecycle event hooks, which allow us to fire some logic before or after a transition in or out.
0:28 One of these props, let's go in the Root component here, is called afterLeave. This will allow you to run some code at the end of the leave transition, so when the modal is completely disappeared. This seems like a perfect time for us to set the IsLoading property back to .
0:44 You might think you'd want to do something like setIsLoading here, but remember, the Modal component itself should not be responsible to handle any of the logic of whether the modal should be loading or not. It receives the isLoading prop, and that's it.
0:59 In other words, instead of directly trying to change the isLoading value here, we want to emit a signal back to the parent components that consume this modal to say, "Hey, right now would be a good time to do your thing and setIsLoading back to ."
1:13 Check this out. Our modal is already receiving these sort of event props like onClose. What I'm thinking here is just like we have this onClose event, we could have a sister event called onCloseComplete, which would also be a function. Let's make it optional.
1:30 Down where we receive our props, let's receive onCloseComplete. Let's make it default so it just doesn't do anything if it's not passed. Now here we can use this onCloseComplete as our event emission to the parent, so afterLeave, we can just fire the onCloseComplete function that can be set in the parent component.
1:51 Now, once again, we're not handling any of the isLoading logic. We just give a chance to the consumer of the Modal component to execute some code after the leave transition has completed. Now we can go back to our index file here and get rid of the setIsLoading inside the handleConfirm function. Instead, we can pass a new onCloseComplete function.
2:14 This is where we're going to setIsLoading to . With a bit of luck, when we click the button, it's going to set the loading to true. Then after two seconds, close the modal. When the close transition is complete, this is where it's going to setIsLoading back to . Let's take a look.
2:34 We open the modal, pay very close attention to the loading spinner, and see if you see it disappear or not. Hopefully it will stay until the end. When we reopen the modal, it's not there. Very nice. Let's check a second time. Spin, spin, spin, spin, spin, spin, spin all the way, and then it's set to behind the scenes. This is starting to look pretty nice.