Check out a free preview of the full Complete Intro to React, v9 course
The "Portals" Lesson is part of the full, Complete Intro to React, v9 course featured in this preview video. Here's what you'd learn in this lesson:
Brian introduces portals that allow a React application to render content outside the application's root. The purpose of this portal will be to display a modal.
Transcript from the "Portals" Lesson
[00:00:00]
>> Brian Holt: Let's talk about Advanced React, these were things that you don't really need to use these so much, maybe uncontrolled forms you, you'll use these quite a bit, but error boundaries and portals. Much more niche in their use cases, but still felt useful enough that I wanted you to have them in your tool bag even if you don't pull them out very much, right?
[00:00:20]
So let's talk about portals, this is just the markup for the page, right? We have root right here, and that's the only thing that our app can render into, let's say we had ten different divs here, our app currently is only constrained to its root, which is this root right here.
[00:00:46]
Let's say that you dislike your users and you want to show them modals, I think modals are a terrible thing, I think whoever invented them should be ashamed of themselves. And now I'm going to show you how to do them [LAUGH], this used to be a huge problem trying to render modals with React, because it's really hard to get something in front of other stuff.
[00:01:10]
You either have to do unholy things with Z-Index, or you have to find some way to render something first in your app, and it becomes really hard to do, right? We could probably mess around and figure out how to do it somewhat with context, right? But I'm gonna show you something way easier that they introduced to make this a much easier thing, a much more common, I'll say more common, but less user antagonistic.
[00:01:38]
Way of using portals is, let's say you had a side nav that contextually rendered stuff based on what was on the page, and so they're two separate things. You can use a portal to say like, all right, render this into the side nav if you're on this page, right, that's actually a very cool use case for this.
[00:01:59]
>> Brian Holt: Yeah, a good example of this, if you just wanna visualize what I'm talking about is the Azure Docs, so JavaScript Azure Functions, let's just see if I can show you what I'm talking about. So let's say on this page, you have the nav here, and then this is your React app here in the middle, you have these like additional resources here that you're training.
[00:02:18]
And like these change depend on what page you're on, you could use a portal to, say, render into the additional resources these things when you're on this page, it allows you to render outside of your app, right? So that's kind of the use case we're getting at here, so we're gonna head into our index.html, and above root, we're going to put a modal.
[00:02:46]
>> Brian Holt: This time we're not gonna put anything inside of modal because we don't want it to show anything unless there's something rendered into it, right? Okay, I want you to make a new file here, I just call it modal.jsx, you ever watch the good place that TV show.
[00:03:02]
I feel like when I get up to the pearly gates, one of my crimes against humanity is showing so many people how to make modals.
>> Brian Holt: All right, import, use effect, and use ref, so we'll talk about ref as well, that'll be kind of exciting from React.
>> Brian Holt: Import create portal
>> Brian Holt: From react-dom, I'm just gonna say this code is 90% directly from the React docs, so you credit work is due.
[00:03:44]
>> Brian Holt: So maybe I can pass my sins on to them, modal equals, we're talking about children as well, there's lots of fun tidbits in here about React of some more advanced use cases.
>> Brian Holt: All right, so this is kind of a weird one but what we have one div that represents the root of our portal, which is gonna be that modal that we're gonna grab, right?
[00:04:09]
We need to reference the same div between renders, right, because this modal is gonna keep rendering cuz it's React, right? That's how React works, so how do we make sure that we're always referring to the exact same div, we don't wanna create a new div every single render, we wanna refer to the same div between renders, how do we do that?
[00:04:29]
We don't want to do a document.getElementID directly in the render, that's a slow API, right, anytime that you have to interact with a div direct or the DOM directly, you end up in this kind of slow code path and you don't want that. Enter refs, that's what we're gonna do here, so we're gonna say const elRef, el being element, use ref and we're gonna have it start as null.
[00:05:00]
This is the default value the first time, and then we're gonna say if no elRef.current, then elRef.current =document.createElement div. So, a ref is a frozen object, we don't really use freeze too much, it's usually a library thing, but it only has one thing that you can modify on it, which is current, why is it this way?
[00:05:39]
Because the ref is an object, we can modify the values on it, and it's always going to refer to the same thing, right, it's the pointer points at the same thing.
>> Brian Holt: So this current is going to be the same div, so we're only gonna create one div, and we're going to reference the same div every single render, little strange, I know.
[00:06:02]
But stick with me, and it'll make maybe a bit more sense here, just keep in mind, this elRef contains a div, and it's the same div no matter how many times I run the render, now, our old friend, useEffect.
>> Brian Holt: Const modal root = document.getElementById, modal, so that's gonna be our modal root, modal root.appendChild, elRef.current, so now, our created div is inserted into the DOM, that's cool.
[00:06:49]
And hold on, we'll come back and do the return here in a second cuz I wanna explain that more in depth, how many times are we gonna insert our div? Once, empty array, right, you got it, and then down here at the bottom we're going to return create portal of div.
[00:07:18]
>> Brian Holt: And we're going to render out children.
>> Brian Holt: And then we're going to do that with our elRef.current.
>> Brian Holt: And then export default modal, so create portal, what's cool about this is, now, we can render this anywhere inside of our app and it'll be like, you don't want this actually directly here, you're trying to stick this over there, right?
[00:07:49]
So it's not gonna render whatever you render as children there, it's going to stick it whatever you put in the portal, let's talk about children for just a second. So if I have a div here and I have my h1 that's like right there, right, what is the children of this div, it's whatever is inside of it, right?
[00:08:14]
So it's the same thing with modal, what is the children of modal, it's whatever's inside of it, right? Whatever you put inside of it, most of the stuff that we've been doing has been self closing, right, where it's pizza, because it doesn't make any we're not trying to put anything inside of pizza, right?
[00:08:32]
So that's why all these have been the self closing, but modal, we actually do wanna have arbitrary stuff inside of it, so that's what children is, and children comes in via props. It's a specifically named props, we destructured here, but this is normally called props, right, if you did it that way, you would just say props.children, right?
[00:08:55]
But instead we did destructuring cuz I don't know, but I typically destructure cuz I like the shorter names, but that's up to you. Cool, we used an effect here because we want this to happen once, we want it to be scheduled for after the initial render, that makes sense, okay.
[00:09:13]
That's probably a hint of what I'm about to talk to, this has a memory leak.
>> Brian Holt: Why?
>> Brian Holt: Let's say I render and unrender this modal a thousand times.
>> Brian Holt: How many divs is modal root gonna have inside of it, 1,000? Nothing goes back and removes elRref.current from this modal root, so it's just gonna keep leaving behind divs, right, so we have to go clean up after ourselves, right?
[00:10:04]
So this is one of the weirdest APIs for React in my opinion, but you return a function here, and you do all your cleanup here, so modalroot.removechild.
>> Brian Holt: elRef.current, that's our cleanup function, so whatever function you run or you return from your effect will be run once after it gets unmounted, and this will solve our memory leak.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops