React Portals & Refs

React Portals & Refs (For Advanced DOM Manipulation)

React provides Portals and Refs for advanced DOM manipulation. Portals allow rendering components outside the main React tree while preserving state and event behavior. Refs provide direct access to DOM elements or React components, enabling precise control over UI interactions.

React Portals

What Are React Portals?

Portals allow rendering a component outside its parent DOM hierarchy while still maintaining React’s state and event system.

When to Use Portals?

✅ Modals & Dialogs – Prevents CSS issues like overflow: hidden.
✅ Tooltips & Popups – Ensures correct positioning.
✅ Dropdown Menus – Keeps UI elements separate from the main document flow.
✅ Global UI Elements – Helps maintain an organized structure.

Creating a React Portal for a Modal

👉 Step 1: Add a Target
in index.html

Ensure that public/index.html has a portal root where the modal will be injected:

<body>
<div id=”root”></div>
<div id=”portal-root”></div> <!– Target for portal –>
</body>

👉 Step 2: Create the Modal Component Using ReactDOM.createPortal

This component will render inside #portal-root, outside the main app DOM:

import React from ‘react’;
import ReactDOM from ‘react-dom’;

// Modal Component
function Modal({ children, onClose }) {
return ReactDOM.createPortal(
<div className=”modal-overlay” onClick={onClose}>
<div className=”modal-content” onClick={(e) => e.stopPropagation()}>
{children}
<button onClick={onClose} className=”close-btn”>Close</button>
</div>
</div>,
document.getElementById(‘portal-root’) // Mounts modal here
);
}

export default Modal;

👉 Step 3: Use the Modal Component in App.js

Now, use the Modal inside the App component:

import React, { useState } from ‘react’;
import Modal from ‘./Modal’;

function App() {
const [showModal, setShowModal] = useState(false);

return (
<div>
<h1>React Portal Modal Example</h1>
<button onClick={() => setShowModal(true)}>Open Modal</button>

{showModal && (
<Modal onClose={() => setShowModal(false)}>
<h2>Portal Modal</h2>
<p>This modal is rendered using a portal!</p>
</Modal>
)}
</div>
);
}

export default App;

👉 Step 4: Add Modal Styles (Optional, but Recommended)

For a better UI, add these styles in App.css or a separate CSS file:

.modal-overlay {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}

.modal-content {
background: white;
padding: 20px;
border-radius: 8px;
min-width: 300px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}

.close-btn {
margin-top: 10px;
padding: 8px 12px;
background: red;
color: white;
border: none;
cursor: pointer;
}

📝 Short Explanation:

1️⃣ Add a Target <div> in index.html
✔️Create a <div id=”portal-root”></div> inside public/index.html to serve as the modal container outside the main React app.
2️⃣ Create the Modal Component
✔️ Use ReactDOM.createPortal to render the modal inside #portal-root, keeping it separate from the main app DOM.
✔️ Prevent background clicks from closing the modal by using e.stopPropagation().
3️⃣ Use the Modal in App.js
✔️ Manage the modal’s visibility using useState.
✔️ Conditionally render <Modal> when showModal is true.
✔️ Pass onClose to close the modal when clicking the close button.
4️⃣ Style the Modal (Optional but Recommended)
✔️ Add CSS for overlay, modal content, and a close button to improve the UI.

🎯 Benefits of Using Portals

✔ Prevents z-index and styling conflicts.
✔ Ensures UI elements remain accessible in the DOM hierarchy.
✔ Enhances usability for modals, tooltips, and floating UI components.

React Refs

What Are Refs?

Refs provide a way to directly interact with DOM elements or React components without triggering re-renders.

When to Use Refs?

✅ Managing Focus – Automatically focus an input field.
✅ Controlling Animations – Trigger or pause animations dynamically.
✅ Interacting with Third-Party Libraries – Use external libraries that require direct DOM manipulation.
✅ Measuring Elements – Get dimensions or positions of elements.

1️⃣ Creating a Ref with useRef (Focus Input Field)

Using useRef to access the input field and programmatically focus it when the button is clicked.

import React, { useRef } from ‘react’;

function InputFocus() {
const inputRef = useRef(null);

const focusInput = () => {
if (inputRef.current) {
inputRef.current.focus(); // Focus the input field
}
};

return (
<div>
<input ref={inputRef} type=”text” placeholder=”Type here…” />
<button onClick={focusInput}>Focus Input</button>
</div>
);
}

export default InputFocus;

📝 Explanation

✔️ Use useRef to Create a Reference: useRef(null) initializes a reference (inputRef) to store a reference to the input field.
✔️ Attach ref to the Input Field: <input ref={inputRef} /> assigns the reference to the input field, allowing direct access to it.
✔️ Focus Input on Button Click: The focusInput function calls inputRef.current.focus(), setting focus to the input field when the button is clicked.

🎯 Why use useRef here?

✔️ Avoids re-rendering the component when focusing the input.
✔️ Directly manipulates the DOM element (imperative approach).

2️⃣ Storing Previous State Using useRef

Here, we persist the previous state value across renders without causing re-renders.

import React, { useState, useEffect, useRef } from ‘react’;

function Counter() {
const [count, setCount] = useState(0);
const prevCountRef = useRef(); // Stores previous value

useEffect(() => {
prevCountRef.current = count; // Update previous count after render
}, [count]);

return (
<div>
<h1>Current: {count}</h1>
<h2>Previous: {prevCountRef.current ?? “N/A”}</h2>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}

export default Counter;

📝 Explanation

✔️ Use useRef to Store the Previous State: prevCountRef = useRef(); holds the previous value without triggering re-renders.
✔️ Update prevCountRef in useEffect :
  useEffect(() => { prevCountRef.current = count; }, [count]);
•  Runs after each render, storing the latest count as prevCountRef.current.
✔️ Display Current and Previous Values: The previous count is shown using {prevCountRef.current ?? “N/A”} (displays “N/A” initially).

🎯 Why use useRef for previous state?

✔️ Unlike useState, useRef does not trigger re-renders.
✔️ It allows tracking previous values across renders.

3️⃣ Forwarding Refs to Child Components (forwardRef)

By default, refs cannot be passed to child components. React.forwardRef enables passing refs down the component tree.

👉 Example: Forwarding Refs to a Button Component

import React, { useRef, forwardRef } from ‘react’;

const CustomButton = forwardRef((props, ref) => (
<button ref={ref} {…props}>Click Me</button>
));

function App() {
const buttonRef = useRef();

return (
<div>
<CustomButton ref={buttonRef} onClick={() => alert(“Button clicked!”)} />
</div>
);
}

export default App;

Explanation:

✔️ Use forwardRef to Pass the ref: forwardRef allows CustomButton to accept a ref and forward it to the <button> element.
✔️ Attach the ref in the Parent Component:
useRef() is used in App to create buttonRef.
CustomButton ref={buttonRef} passes the reference to the button.
✔️ Handle Click Event: Clicking the button triggers an alert (onClick={() => alert(“Button clicked!”)}).

🎯 Why use forwardRef?

✔️ Allows parent components to directly access a child’s DOM element.

✔️ Useful for custom UI components (e.g., reusable buttons, inputs).

Benefits of Using Refs

✔ Directly manipulate the DOM.
✔ Store mutable values without causing re-renders.
✔ Maintain focus, animations, or track previous values.

Comparing Portals & Refs

Feature React Portals React Refs
Purpose Render components outside normal DOM hierarchy Directly access/manipulate DOM elements
Use Cases Modals, tooltips, floating UI elements Focusing inputs, animations, measuring elements
Maintains React State ✅ Yes ❌ No
Requires External Container ✅ Yes (Needs div in index.html) ❌ No
Complexity 🔹 Moderate 🔹 Moderate

Best Practices for Using Portals & Refs

✅ Use Portals for UI elements that should be outside of the main DOM structure.
✅ Use Refs only when necessary—avoid excessive direct DOM manipulation.
✅ Avoid Overusing Refs – Prefer React state where possible.
✅ Combine Portals & Refs for better UI interactions (e.g., closing modals when clicking outside).
✅ Use forwardRef when passing refs to child components for better encapsulation.

Conclusion

React Portals and Refs provide powerful tools for advanced UI manipulation. Portals allow rendering elements outside the React tree while keeping event handling intact. Refs enable direct interaction with the DOM, making them useful for focus management, animations, and measuring elements. By mastering these tools, you can build highly interactive and dynamic React applications.

Course Video in English