Teleport do Vue.js 3 vs Portals do ReactJS: uma análise comparativa para lidar com elementos fora do contexto do componente pai.
Tags: webdev, javascript, vue, react
Published: 2023-02-16 12:20:24

O Vue.js 3 é uma das mais populares bibliotecas de JavaScript para construção de interfaces de usuário, e sua recente atualização trouxe consigo um novo componente interessante, o **Teleport**. Neste post, vamos fazer uma introdução ao Teleport e também uma comparação com os **Portals** do ReactJS.

Antes de começarmos, é importante entendermos que ambos os recursos foram criados para resolver um problema comum em aplicações web: como lidar com elementos que precisam ser exibidos fora do contexto do seu componente pai.

Em Vue, um componente é renderizado dentro de sua própria estrutura de componentes, o que significa que todas as suas propriedades e métodos são restritos a essa estrutura. No entanto, às vezes é necessário exibir um elemento em outro local da página, fora do contexto de seu componente pai. É nesse momento que podemos utilizar o `Teleport`.

O `Teleport` permite que nosso componente seja "teletransportado" como filho de outro elemento e em qualquer outro lugar da página, sem termos que nos preocupar com renderização e interação, mantendo os dados e informações do componente mesmo após ser mudado de lugar.

Para podermos utilizar do componente `Teleport`, só precisamos envolver o elemento a ser teleportado em uma tag `<teleport> </teleport>` e especificarmos o local que o elemento deve ser renderizado, como no exemplo a baixo:

---

#### Modal.vue

```html
<template>
    <teleport to="#modal-target">
      <div v-if="show" class="modal__body">
        <h1>Modal Title</h1>
        <p>Modal Content</p>
      </div>
    </teleport>
</template>

<script lang="ts">
export default {
  props: {
    show: {
      type: Boolean,
      required: true,
    },
  },
};
</script>
```

---

#### App.vue

```html
<template>
  <div id="modal-target" class="modal__target"></div>
  <button @click="show = !show">Toggle Modal</button>
  <Modal :show="show" />
</template>
<script lang="ts">
import Modal from './components/Modal.vue';
export default {
  data() {
    return {
      show: false,
    };
  },
  components: {
    Modal,
  },
};
</script>
```

---


Com o código acima, você pode ver que o elemento modal é renderizado como filho, no local especificado pela propriedade **_"to"_** que funciona da mesma forma que um seletor CSS. Com isso podemos alterar o local de renderização do nosso componente de modal, independente da sua posição na estrutura de elementos. Obtendo o seguinte resultado: 

---


![Resultado da abordagem utilizando componente `Teleport` do vue3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2qao33e1hrlw5wpoy4s.gif)


O `Teleport` também possui uma propriedade para desabilita-lo em algum caso, podemos passar, por exemplo, para que ele seja desabilitado caso estejamos utilizando um dispositivo mobile apenas criando uma validação de tamanho de tela:

---


```js
computed: {
    isMobile() {
      return screen.width <= 760;
    },
  },
```

---

E adicionando isso na propriedade **_"disabled"_** do nosso componente `Teleport`:

```html
    <teleport :disabled="isMobile" to="#modal-target">
      <div v-if="show" class="modal__body" style="">
        <h1>Modal Title</h1>
        <p>Modal Content</p>
      </div>
    </teleport>
```

---


![Resultado da abordagem utilizando componente `Teleport` do vue3 porém com propriedade disbled](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vduyc25yn8bw4xb75d9d.gif)

---

### Um comparativo com portals do ReactJS

Agora vamos comparar o `Teleport` com os `Portals` do ReactJS. Em React, os Portais são usados para exibir elementos fora do contexto de seu componente pai. A ideia é semelhante ao `Teleport`, mas a implementação é um pouco diferente.

Em React, você precisa criar um componente Portal e usá-lo como um componente comum em sua aplicação. Aqui está um exemplo de código:

#### App.jsx

```jsx
import React, { useState } from 'react';
import { createPortal } from 'react-dom';
import './App.css';

function Modal() {
  return createPortal(
    <div>
      <h1>Modal Title</h1>
      <p>Modal Content</p>
    </div>,
    document.getElementById('modal-root')
  );
}

function App() {
  const [show, setShow] = useState(false);
  return (
    <div>
      <button onClick={() => setShow(!show)}>Toggle Modal</button>
      {show && <Modal />}
      <div id="modal-root" class="modal__root"></div>
    </div>
  );
}

export default App;

```
Assim como o `Teleport`, podemos obter um resultado parecido, nos permitindo renderizar o componente em qualquer local da página. 


![Resultado da abordagem utilizando componente `Portals` do react](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ocilun4drajd5e8gop2y.gif)



No entanto, a implementação é um pouco diferente, pois você precisa criar um componente específico e usá-lo como um componente comum.

Em resumo, o `Teleport` e os Portais são recursos semelhantes, criados para resolver o mesmo problema de exibir elementos fora do contexto de seu componente pai. O `Teleport` é uma adição interessante ao Vue.js 3 e é fácil de usar, enquanto os Portais são uma abordagem mais flexível, porém requerem uma implementação um pouco mais complexa.

A escolha entre o `Teleport` e os `Portals` depende da sua familiaridade com as ferramentas e do que você acha mais fácil de aprender. Se você já trabalha com Vue.js 3, o `Teleport` é uma opção fácil de implementar e pode ser mais adequado. Se você já está mais familiarizado com os `Portals` do ReactJS, pode ser mais fácil continuar usando essa abordagem. O importante é escolher a opção que você se sinta mais confortável em trabalhar e que seja mais fácil para você aprender.


Obrigado pela leitura!! Críticas construtivas e comentários são muito bem vindos 💚💙