PROG_WAY_BLOG Telegram 338
Порталы в React

Сталкивались когда-нибудь с проблемой, когда нужно рендерить элемент за пределами текущей DOM-иерархии?

Например, модальные окна, которые не должны быть вложены в основное дерево из-за проблем с позиционированием или всплывающие подсказки, которые всегда должны быть на переднем плане


Для таких задач React предлагает решение — порталы

В документации реакта приведён такой код:
import { createPortal } from 'react-dom';

<div>
<p>Текст расположен в родительском диве</p>
{createPortal(
<p>Текст расположен в document.body </p>,
document.body
)}
</div>


Работает этот код проще простого: элемент, переданный в функцию createPortal, будет маунтиться реактом не в родительский див, а в document.body. Работать это будет с деревом любой вложенности

Такой код будет работать, но он не очень удобен, поэтому многие компонентные библиотеки максимально упрощают порталы для разработчиков и делают подобные компоненты — они есть в Chakra UI, Material UI, Semantic UI и других либах

Но, на самом деле, там нет ничего сложного


Если максимально упростить, то можно прийти к такому варианту:
const Portal = ({ children }: PropsWithChildren) => {
const [container] = useState(() => document.createElement('div'));

useLayoutEffect(() => {
document.body.appendChild(container);
return () => {
document.body.removeChild(container);
};
}, [container]);

return createPortal(children, container);
}

// ...

<Portal>
<p>Текст внутри портала</p>
</Portal>

Тут стоит уточнить две детали:

1. Мы создаём новый div внутри useState, чтобы проще было контролировать портал
Если мы будем рендерить контент сразу в document.body, то можно словить много проблем со стилями и отслеживанием самого портала

Используем мы именно useState, чтобы создавать элемент единожды и гарантировано на первый рендер компонента. Элемент создается внутри колбека инициализации состояния — он всегда вызывается единожды на маунт компонента

Как альтернатива, можно обойтись и рефом


2. В useLayoutEffect мы привязываем жизненный цикл тега-обёртки к циклу компонента портала
Тоже полезно, чтобы лишний раз не задумываться о том, как живёт портал и не создавать ненужных элементов в вёрстке

useLayoutEffect используется вместо useEffect, чтобы обрабатывать портал без лишних мерцаний и более плавно

Вообще, тема разных эффектов и где какой использовать — это отдельная крупная тема, возможно сделаю об этом пост в будущем


Да и всё. Тут компонент на 10 строчек буквально, ничего сверхъестественного. Если вам нужны порталы, то задумайтесь — скорее всего вам хватит такой простой реализации

Спасибо за прочтение, это важно для меня ❤️

@prog_way_blogчат — #web #javascript #theory #code
21👍11🐳3🔥1👏1



tgoop.com/prog_way_blog/338
Create:
Last Update:

Порталы в React

Сталкивались когда-нибудь с проблемой, когда нужно рендерить элемент за пределами текущей DOM-иерархии?

Например, модальные окна, которые не должны быть вложены в основное дерево из-за проблем с позиционированием или всплывающие подсказки, которые всегда должны быть на переднем плане


Для таких задач React предлагает решение — порталы

В документации реакта приведён такой код:
import { createPortal } from 'react-dom';

<div>
<p>Текст расположен в родительском диве</p>
{createPortal(
<p>Текст расположен в document.body </p>,
document.body
)}
</div>


Работает этот код проще простого: элемент, переданный в функцию createPortal, будет маунтиться реактом не в родительский див, а в document.body. Работать это будет с деревом любой вложенности

Такой код будет работать, но он не очень удобен, поэтому многие компонентные библиотеки максимально упрощают порталы для разработчиков и делают подобные компоненты — они есть в Chakra UI, Material UI, Semantic UI и других либах

Но, на самом деле, там нет ничего сложного


Если максимально упростить, то можно прийти к такому варианту:
const Portal = ({ children }: PropsWithChildren) => {
const [container] = useState(() => document.createElement('div'));

useLayoutEffect(() => {
document.body.appendChild(container);
return () => {
document.body.removeChild(container);
};
}, [container]);

return createPortal(children, container);
}

// ...

<Portal>
<p>Текст внутри портала</p>
</Portal>

Тут стоит уточнить две детали:

1. Мы создаём новый div внутри useState, чтобы проще было контролировать портал
Если мы будем рендерить контент сразу в document.body, то можно словить много проблем со стилями и отслеживанием самого портала

Используем мы именно useState, чтобы создавать элемент единожды и гарантировано на первый рендер компонента. Элемент создается внутри колбека инициализации состояния — он всегда вызывается единожды на маунт компонента

Как альтернатива, можно обойтись и рефом


2. В useLayoutEffect мы привязываем жизненный цикл тега-обёртки к циклу компонента портала
Тоже полезно, чтобы лишний раз не задумываться о том, как живёт портал и не создавать ненужных элементов в вёрстке

useLayoutEffect используется вместо useEffect, чтобы обрабатывать портал без лишних мерцаний и более плавно

Вообще, тема разных эффектов и где какой использовать — это отдельная крупная тема, возможно сделаю об этом пост в будущем


Да и всё. Тут компонент на 10 строчек буквально, ничего сверхъестественного. Если вам нужны порталы, то задумайтесь — скорее всего вам хватит такой простой реализации

Спасибо за прочтение, это важно для меня ❤️

@prog_way_blogчат — #web #javascript #theory #code

BY progway — программирование, IT


Share with your friend now:
tgoop.com/prog_way_blog/338

View MORE
Open in Telegram


Telegram News

Date: |

The group’s featured image is of a Pepe frog yelling, often referred to as the “REEEEEEE” meme. Pepe the Frog was created back in 2005 by Matt Furie and has since become an internet symbol for meme culture and “degen” culture. Healing through screaming therapy Administrators Choose quality over quantity. Remember that one high-quality post is better than five short publications of questionable value. Matt Hussey, editorial director of NEAR Protocol (and former editor-in-chief of Decrypt) responded to the news of the Telegram group with “#meIRL.”
from us


Telegram progway — программирование, IT
FROM American