DEV Community

Em Whitney
Em Whitney

Posted on

Portals & useRef in React

During my foundational time, I'm going to write notes on what I studied and learned.

These notes were taken while watching the Front End Masters course "Complete Intro to React, v7" by Brian Holt.

What is a portal?

A portal is a mount point, separate from the actual DOM which the app is put into (root in index HTML), for the React app.

A common use case for this is a modal (a child window that pops up).

Adding the portal

First, add the modal into index.html with a separate mount point

<!-- above #root -->
<div id="modal"></div>
Enter fullscreen mode Exit fullscreen mode

Make a new file called Modal.js

import React, { useEffect, useRef } from "react";
import { createPortal } from "react-dom";

const Modal = ({ children }) => {
  const elRef = useRef(null);
  if (!elRef.current) {
    elRef.current = document.createElement("div");
  }

  useEffect(() => {
    const modalRoot = document.getElementById("modal");
    modalRoot.appendChild(elRef.current);
    return () => modalRoot.removeChild(elRef.current);
  }, []);

  return createPortal(<div>{children}</div>, elRef.current);
};

export default Modal;
Enter fullscreen mode Exit fullscreen mode

The div container is what renders inside of the Portal.

Need to render to the portal spot on the DOM.

Need to remove the div afterwards. You do this by returning a function. This function will get invoked when the Modal goes away.

What is a ref?

You use ref when you want to refer to the same thing across all things rendering.

It is essentially a pointer to an object with a current property, and when you update the ref, you update the current property.

It will never cause your component to re-render because it is completely separate from the component render cycle, unlike state variables.

Adding code for modal toggle

// at the top
import Modal from "./Modal";

// add showModal
state = { loading: true, showModal: false };

// above render
toggleModal = () => this.setState({ showModal: !this.state.showModal });

// add showModal
const { animal, breed, city, state, description, name, images, showModal } =
  this.state;

// add onClick to <button>
<button onClick={this.toggleModal} style={{ backgroundColor: theme }}>
  Adopt {name}
</button>;

// below description
{
  showModal ? (
    <Modal>
      <div>
        <h1>Would you like to adopt {name}?</h1>
        <div className="buttons">
          <a href="https://bit.ly/pet-adopt">Yes</a>
          <button onClick={this.toggleModal}>No</button>
        </div>
      </div>
    </Modal>
  ) : null;
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)