Svelte 3: Guia para o Desenvolvedor (React) Impaciente
Tags: ptbr, javascript, webdev, svelte
Published: 2019-07-21 07:15:25

## Tudo o que você precisa saber para começar com o Svelte 3!

## Tabela de Conteúdo
1. O que é Svelte?
2. Para quem este guia é (requisitos)
3. O que você vai aprender e construir
4. Configurando o projeto
5. Mergulhando em Svelte
6. Buscando dados com Svelte
7. Criando listas com "each"
8. Passando "props"
9. Múltiplas "props" e "spreading"
10. Componentes filhos e "render props"
11. Manipulando eventos e modificadores de eventos
12. Uma rápida recapitulação
13. Implementando o recurso de pesquisa
14. Reatividade
15. Comparando com React
16. Como o Svelte se compara ao React e Vue?
17. Mais Recursos
18. Finalizando

# 1. O que é Svelte?

Svelte é uma biblioteca JavaScript de interface do usuário criada por Rich Harris. Rich acha que o **DOM Virtual** é apenas uma sobrecarga e apareceu com o Svelte, que agora está em sua terceira versão.

Mas por que você gostaria de aprender Svelte? React ou Vue não são o suficiente? Bem, existem alguns pontos interessantes:

- Svelte é um **compilador**, não uma dependência como React ou Vue
- O Svelte parece precisar de **menos código** para as mesmas coisas que o React, que exige 40% a mais de LOC (fonte: Rich Harris)
- O Svelte não possui **um DOM virtual**, compila um JavaScript "vanilla" mínimo e parece ter um desempenho melhor que outras bibliotecas

Eu não fiz nenhum benchmark para confirmar essas coisas, fica a sua responsabilidade de pesquisar. No tutorial a seguir, vou focar nos conceitos básicos do Svelte 3.

De qualquer forma, não pule por este artigo muito rápido. Svelte 3 é **realmente interessante**, embora tenha algumas **arestas**. Enquanto isso, você pode **mergulhar no Svelte 3 com este tutorial e formar sua própria opinião**.

Bom proveito!

# 2. Para quem este guia é (requisitos)

Você não terá problemas em seguir o tutorial se tiver uma compreensão básica de:

- HTML, CSS e JavaScript (ES6+)
- Módulos ES6, sintaxe **import/export**
- Sintaxe **async/await**
- Conceitos sobre componentes
- Sintaxe da API **fetch**

Se você está apenas começando, talvez o tutorial ainda seja demais para você. Mas não se desespere, confira os recursos a seguir e volte mais tarde.

Se você precisar de uma atualização nos módulos do ES6, consulte a documentação do [**import**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) e [**export**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) em JavaScript. Há também o excelente artigo [**ES6 Modules in Depth**](https://ponyfoo.com/articles/es6-modules-in-depth).

E para saber mais sobre a API fetch, confira [Fetch API](https://davidwalsh.name/fetch).

(Sim, é um monte de coisas para um novato saber. Não me culpe!).

Além disso, certifique-se de ter uma versão mais recente do Node.js instalada em seu sistema.

# 3. O que você vai aprender e construir

Nós não vamos construir uma aplicação "fullstack" neste tutorial. Ao invés disso, vou guiá-lo através dos conceitos básicos do Svelte 3, construindo algumas pequenas partes da interface do usuário. No final, você deve poder começar a construir com o Svelte, tendo visto como criar componentes, como manipular eventos e assim por diante.

E agora... vamos aprender Svelte!

# 4. Configurando o projeto

Como acontece com qualquer projeto JavaScript moderno, precisamos fazer tocar as músicas e dançar no ritmo: configurar o projeto! Se você quiser criar um repositório Git para o projeto, vá em frente e, em seguida, clone o repositório em sua máquina local.

Uma vez clonado, você está pronto para criar um novo projeto Svelte com **degit** . Não se preocupe, não é outra ferramenta para aprender! **degit** apenas faz cópias dos repositórios do Git e, no nosso caso, vamos clonar o modelo Svelte em uma nova pasta (ou no repositório que criamos).

Então, para recapitular, crie um novo repositório Git se você quiser e depois clone-o em sua máquina local.

Em seguida, crie um novo projeto Svelte com **degit** na sua nova pasta. Se a pasta não estiver vazia, **degit** irá te avisar e você precisará passar a opção de força:

```bash
npx degit sveltejs/template svelte-tutorial --force
```

Em seguida, vá para o novo projeto e instale as dependências:

```bash
cd svelte-tutorial && npm i
```

E agora você está pronto para ir!

# 5. Mergulhando em Svelte

Com a pasta criada, vamos dar uma olhada no que foi gerado. Abra o projeto com o seu editor de texto. Você verá vários arquivos:

- **App.svelte** - o componente raiz do aplicativo
- **‌rollup.config.js** - uma configuração para o Rollup, o empacotador que o Svelte usa

Agora abra **App.svelte** e dê uma olhada:

```vue
<script>
    export let name;
</script>

<style>
    h1 {
        color: purple;
    }
</style>

<h1>Hello {name}!</h1>
```

Isso é um **componente Svelte**! Mesmo. Tudo o que precisa é de uma tag de script, uma tag de estilo e um pouco de HTML. **name** é uma variável que é usada dentro do HTML, **interpolada entre chaves**. Não se preocupe muito com a declaração de exportação por enquanto. Vamos ver o que acontece depois.

# 6. Buscando dados com Svelte

Para começar a explorar o Svelte, começaremos imediatamente com a artilharia: vamos buscar alguns dados de uma API.

Por esse motivo, o Svelte não é tão diferente do React: ele usa um método chamado **onMount**. É uma **função do ciclo de vida**. É fácil adivinhar onde Svelte tomou emprestada a ideia: dos **métodos de ciclo de vida React**.

Agora vamos criar um novo componente Svelte chamado **Fetch.svelte** dentro da pasta **src**. Nosso componente importa o onMount do Svelte e faz uma solicitação de busca para uma API. **onMount** recebe uma função de callback e, dentro desse callback, fazemos a solicitação. Os dados são salvos em uma variável chamada **data**, acima de onMount:

```vue
<script>
  import { onMount } from "svelte";

  let data = [];

  onMount(async function() {
    const response = await fetch("https://academy.valentinog.com/api/link/");
    const json = await response.json();
    data = json;
  });
</script>
```

Agora abra **App.svelte** e importe o componente recém-criado (você pode se livrar de tudo, exceto da tag de script):

```vue
<script>
  import Fetch from "./Fetch.svelte";
</script>

<Fetch />
```

Como você pode ver, a sintaxe para usar componentes lembra o JSX do React. Como esse componente faz apenas uma chamada de API, mas ainda não exibe nada, vamos adicionar mais coisas à mistura.

# 7. Criando listas com "each"

Em React estamos acostumados com a função de mapa para [criar listas de elementos](https://reactjs.org/docs/lists-and-keys.html). Em Svelte existe um bloco chamado "each". Vamos usá-lo para criar uma lista de links. A API retorna uma matriz de objetos e cada objeto possui um título e uma URL. Vamos adicionar um bloco "each" agora:

```vue
<script>
  import { onMount } from "svelte";

  let data = [];

  onMount(async function() {
    const response = await fetch("https://academy.valentinog.com/api/link/");
    const json = await response.json();
    data = json;
  });
</script>

{#each data as link}
// faz algo //
{/each}
```

Observe como "each" **produz os dados variáveis** de onde eu extraio cada elemento como **"link"**. Com o bloco no lugar agora é hora de gerar uma lista de elementos, verifique colocar um elemento **ul** em torno do bloco "each":

```vue
<script>
  import { onMount } from "svelte";
  
  let data = [];
  
  onMount(async function() {
    const response = await fetch("https://academy.valentinog.com/api/link/");
    const json = await response.json();
    data = json;
  });
</script>

<ul>
  {#each data as link}
    <li>
      <a href={link.url}>{link.title}</a>
    </li>
  {/each}
</ul>
```

Agora, no seu terminal, entre na pasta do seu projeto e execute:

```bash
npm run dev
```

Visite **http://localhost:5000/** e você verá uma lista de links:

![](https://www.valentinog.com/blog/wp-content/uploads/2019/06/svelte-list-of-elements-each.png)

Bom trabalho! Você aprendeu como gerar listas de elementos no Svelte. Mas agora vamos tornar **nosso componente mais reutilizável**.

# 8. Passando "props"

A **capacidade de reutilizar componentes na interface do usuário** é a "razão principal" de bibliotecas JavaScript modernas. Em React, por exemplo, há o conceito de **props**, atributos personalizados (e até mesmo função ou outros componentes) que podemos passar para os nossos componentes para torná-los mais flexíveis.

No momento, o **Fetch.svelte** não é tão reutilizável, a URL é única. Mas não se preocupe, os componentes da Svelte também podem receber **props** do lado de fora. Vamos começar fazendo a url uma variável (mostrarei apenas a parte relevante do componente):

```vue
<script>
  import { onMount } from "svelte";

  let url = "https://academy.valentinog.com/api/link/";
  let data = [];

  onMount(async function() {
    const response = await fetch(url);
    const json = await response.json();
    data = json;
  });
</script>
```

Certo, agora há um truque para tornar a **url** uma prop: basta prefixar a variável com **export**.

```vue
<script>
  import { onMount } from "svelte";

  // exporta a variável para transforma-la em uma prop
  export let url = "https://academy.valentinog.com/api/link/";
  let data = [];

  onMount(async function() {
    const response = await fetch(url);
    const json = await response.json();
    data = json;
  });
</script>
```

Agora abra **App.svelte** e atualize o componente Fetch passando uma prop de url:

```vue
<script>
  import Fetch from "./Fetch.svelte";
</script>

<Fetch url="https://jsonplaceholder.typicode.com/todos" />
```

Agora seu componente chama o novo endpoint ao invés da URL padrão. Outra coisa interessante é que as variáveis ​​marcadas como props podem ter um valor padrão. Em nosso exemplo, "https://academy.valentinog.com/api/link/" **é o valor padrão** que funciona como um substituto para quando nenhuma prop é passada.

Agora vamos ver o que acontece quando precisamos de mais uma prop.

# 9. Múltiplas "props" e "spreading"

Componentes Svelte podem ter múltiplas props, é claro. Vamos adicionar outro título chamado **title** ao nosso componente:

```vue
<script>
  import { onMount } from "svelte";

  export let url = "https://academy.valentinog.com/api/link/";
  export let title = "A list of links";
  let data = [];

  onMount(async function() {
    const response = await fetch(url);
    const json = await response.json();
    data = json;
  });
</script>

<h1>{title}</h1>
<ul>
  {#each data as link}
    <li>
      <a href={link.url}>{link.title}</a>
    </li>
  {/each}
</ul>
```

E novamente do **App.svelte** passamos a nova prop:

```vue
<script>
  import Fetch from "./Fetch.svelte";
</script>

<Fetch
  url="https://jsonplaceholder.typicode.com/todos"
  title="A list of todos" />
```

Você pode achar a abordagem acima impraticável quando as props começarem a crescer em quantidade. Felizmente há uma maneira de espalhar todas as props de uma vez. Declare as props como um objeto e espalhe-os (**spread**) sobre o componente:

```vue
<script>
  import Fetch from "./Fetch.svelte";
  const props = {
    url: "https://jsonplaceholder.typicode.com/todos",
    title: "A list of todos"
  };
</script>

<Fetch {...props} />
```

Legal, não é? Mas ainda não estou satisfeito. Eu quero tornar o componente Fetch **ainda mais reutilizável**. Como?

# 10. Componentes filhos e "render props"

"Fetch" não é um nome ruim para um componente, mas se eu olhar para ele, ele retorna uma lista HTML. Existe uma maneira de passar essa lista para o lado de fora, **como uma prop children em React**? Sim, é possível! No Svelte nós nos referimos aos componentes filhos como **slot**.

Como primeiro passo, removerei toda a marcação de **Fetch.svelte** e substituí-la por um **slot**. Vamos remover a prop **title** também:

```vue
<script>
  import { onMount } from "svelte";

  export let url = "https://academy.valentinog.com/api/link/";
  let data = [];

  onMount(async function() {
    const response = await fetch(url);
    const json = await response.json();
    data = json;
  });
</script>

<slot />
```

Em seguida eu posso passar elementos filhos para **Fetch** a partir do elemento pai, isso acontece em **App.svelte**:

```vue
<script>
  import Fetch from "./Fetch.svelte";
  const props = {
    url: "https://jsonplaceholder.typicode.com/todos"
  };
</script>

<Fetch {...props}>
  <h1>A list of todos</h1>
  <ul>
    <li>now what?</li>
  </ul>
</Fetch>
```

Mas agora nós temos um problema. Preciso dos dados que estão dentro do **Fetch.svelte** pois não quero criar a lista manualmente.

Em React você teria utilizado uma **HOC, render props ou [hooks](https://www.valentinog.com/blog/hooks)**. Em outras palavras, quero renderizar um componente filho, mas o filho deve obter dados do componente pai.

No Svelte você pode obter o mesmo resultado passando valores de volta ao componente pai. Primeiro **passe dados como uma prop para o seu slot**:

```vue
<script>
  import { onMount } from "svelte";

  export let url = "https://academy.valentinog.com/api/link/";
  export let title = "A list of links";
  let data = [];

  onMount(async function() {
    const response = await fetch(url);
    const json = await response.json();
    data = json;
  });
</script>

<!-- {data} é um atalho para data={data} -->
<slot {data} />
```

E do lado de fora, você pode acessar **data** usando a notação **"let: data = {data}"**, aqui encurtado para **"let: data"**:

```vue
<script>
  import Fetch from "./Fetch.svelte";
  const props = {
    url: "https://jsonplaceholder.typicode.com/todos"
  };
</script>

<!-- "let:data" é como encaminhar os dados internos de um componente um nível para cima. -->
<Fetch {...props} let:data>
  <h1>A list of todos</h1>
  <ul>
    {#each data as link}
      <li>{link.title}</li>
    {/each}
  </ul>
</Fetch>
```

Agora posso usar **data** do componente **Fetch** e eles estarão disponíveis para cada bloco. É como encaminhar os dados internos de um componente um nível para cima.

Parece uma abordagem legal, embora possa ser contra-intuitivo no começo. O que você acha? Na próxima seção, veremos o tratamento de eventos no Svelte.

# 11. Manipulando eventos e modificadores de eventos

Vamos construir um componente de formulário para ilustrar como a Svelte lida com eventos. Crie um novo arquivo chamado **Form.svelte**. Por enquanto, ele conterá uma entrada para pesquisa e um botão do tipo submit:

```vue
<script>

</ script>

<form>
  <label for = "search"> Pesquisa: </ label>
  <input type = "search" id = "search" obrigatório />
  <button type = "submit"> Pesquisar </ button>
</ form>
```

(Como exercício, você pode extrair todos os elementos em seu próprio componente).

Em seguida, inclua o novo componente dentro de **App.svelte**:

```vue
<script>
  import Form from "./Form.svelte";
</script>

<Form />
```

Agora o aplicativo deve renderizar seu formulário no navegador. Nesse ponto, se você tentar enviar o formulário, o comportamento padrão será executado: o navegador irá atualizar a página.

Para assumir o controle do formulário em JavaScript "vanilla", eu registraria um ouvinte de evento para o evento submit. Então, dentro do manipulador eu evitaria o padrão com **event.preventDefault()**:

```js
// vanilla JS example
var form = document.getElementsByTagName('form')[0]

form.addEventListener('submit', function(event){
    event.preventDefault();
});
```

As coisas são um pouco diferentes dentro de um componente Svelte: **os manipuladores de eventos são registrados com "on:"** seguidos respectivamente pelo nome do evento / função do manipulador:

```vue
<script>
  function handleSubmit(event) {
    // faz algo
  }
</script>

<form on:submit={handleSubmit}>
  <label for="search">Search:</label>
  <input type="search" id="search" required />
  <button type="submit">Search</button>
</form>
```

Além disso, no Svelte **existem modificadores de eventos**. Os mais importantes são:

- **preventDefault**
- **stopPropagation**
- **once**

Para **interromper o efeito padrão** em nosso formulário, podemos usar o modificador **preventDefault**, após o nome do evento:

```vue
<script>
  function handleSubmit(event) {
    // faz algo
  }
</script>

<form on:submit|preventDefault={handleSubmit}>
  <label for="search">Search:</label>
  <input type="search" id="search" required />
  <button type="submit">Search</button>
</form>
```

Você também pode passar o **handleSubmit** como um suporte para tornar o componente mais flexível. Aqui está um exemplo, com um prop padrão:

```vue
<script>
  export let handleSubmit = function(event) {
    // faz algo
  };
</script>

<form on:submit|preventDefault={handleSubmit}>
  <label for="search">Search:</label>
  <input type="search" id="search" required />
  <button type="submit">Search</button>
</form>
```

É isso aí. Agora vamos levar este simples aplicativo um passo adiante: **Eu quero filtrar a lista de links**. O formulário já está em vigor, mas precisamos conectar **Fetch.svelte** com **Form.svelte**. Vamos fazer isso!

# 12. Uma rápida recapitulação

Vamos recapitular o que fizemos até agora. Nós temos dois componentes, **Fetch.svelte**:

```vue
<script>
  import { onMount } from "svelte";

  export let url = "https://academy.valentinog.com/api/link/";

  let data = [];

  onMount(async function() {
    const response = await fetch(url);
    const json = await response.json();
    data = json;
  });
</script>

<slot {data} />
```

e **Form.svelte**:

```vue
<script>
  export let handleSubmit = function(event) {
    // valor padrão da prop
  };
</script>

<form on:submit|preventDefault={handleSubmit}>
  <label for="search">Search:</label>
  <input type="search" id="search" required />
  <button type="submit">Search</button>
</form>
```

Em seguida, há **App.svelte**, que é o componente raiz. Por conveniência, vamos renderizar o formulário e buscar dentro do aplicativo:

```vue
<script>
  import Fetch from "./Fetch.svelte";
  import Form from "./Form.svelte";
</script>

<Form />
<Fetch let:data>
  <h1>A list of links</h1>
  <ul>
    {#each data as link}
      <li>
        <a href={link.url}>{link.title}</a>
      </li>
    {/each}
  </ul>
</Fetch>
```

**Fetch.svelte** pega os dados de uma API e envia os dados um nível á cima. Então, ao usar cada bloco como um slot, posso passar dados para seus filhos.

Agora quero que o usuário filtre os dados, dependendo do termo de pesquisa que ela insere no formulário. Parece que **Form** e **Fetch** precisam se comunicar. Vamos ver como podemos implementar isso.

# 13. Implementando o recurso de pesquisa

A maneira como vejo esse recurso é que precisamos de um termo de pesquisa para filtrar o array de dados. O termo de pesquisa pode ser uma prop passada para **Fetch.svelte** a partir do componente pai. Abra o **Fetch.svelte** e adicione a nova prop **searchTerm**:

```vue
<script>
  import { onMount } from "svelte";

  export let url = "https://academy.valentinog.com/api/link/";

  // nova prop
  export let searchTerm = undefined;

  let data = [];

  onMount(async function() {
    const response = await fetch(url);
    const json = await response.json();
    data = json;
  });
</script>

<slot {data} />
```

(**searchTerm** é atribuído **undefined** para evitar que Svelte alerte no console "Fetch foi criado sem a prop searchTerm esperada").

Em seguida, precisamos de uma nova variável para manter a resposta em json, pois filtraremos essa resposta dependendo do searchTerm. Adicione uma nova variável chamada **jsonResponse** e, ao invés de salvar no json, use **jsonResponse** para armazenar a resposta da API:

```vue
<script>
  import { onMount } from "svelte";

  export let url = "https://academy.valentinog.com/api/link/";

  // nova prop
  export let searchTerm;

  // nova variável
  let jsonResponse = [];

  let data = [];

  onMount(async function() {
    const response = await fetch(url);
    const json = await response.json();
    
    // salva a resposta na nova variável
    jsonResponse = json;
  });
</script>

<slot {data} />
```

Neste ponto, **data** terá:

- o jsonResponse original se nenhum searchTerm for fornecido
- um array filtrado se o searchTerm não estiver vazio

Para filtrar o elemento do array, podemos utilizar [.match](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match) com a propriedade **title** baseada em um [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp). (A API retorna um array de objetos. Cada objeto tem **title** e **url**). Uma primeira implementação poderia ser:

```js
const regex = new RegExp(searchTerm, "gi");

const data = searchTerm
    ? jsonResponse.filter(element => element.title.match(regex))
    : jsonResponse;
```

Faz sentido! Vamos ver o componente completo:

```vue
<script>
  import { onMount } from "svelte";

  export let url = "https://academy.valentinog.com/api/link/";

  // nova prop
  export let searchTerm = undefined;

  // nova variável
  let jsonResponse = [];

  const regex = new RegExp(searchTerm, "gi");

  const data = searchTerm
    ? jsonResponse.filter(element => element.title.match(regex))
    : jsonResponse;

  onMount(async function() {
    const response = await fetch(url);
    const json = await response.json();

    // salva a resposta na nova variável
    jsonResponse = json;
  });
</script>

<slot {data} />
```

Neste ponto, precisamos de alguns ajustes no **App.svelte**. searchTerm deve ser uma prop dinâmica sendo enviada pelo componente pai. Em seguida, interceptamos o valor da entrada quando um usuário envia o formulário. Abra o **App.svelte** e passe o searchTerm como prop para Fetch:

```vue
<script>
  import Fetch from "./Fetch.svelte";
  import Form from "./Form.svelte";

  let searchTerm;
</script>

<Form />
<Fetch {searchTerm} let:data>
  <h1>A list of links</h1>
  <ul>
    {#each data as link}
      <li>
        <a href={link.url}>{link.title}</a>
      </li>
    {/each}
  </ul>
</Fetch>
```

Em seguida, criamos e passamos o handleSubmit como prop para o Form e, dentro do App.svelte, salvamos o termo de pesquisa inserido pelo usuário dentro da variável searchTerm:

```vue
<script>
  import Fetch from "./Fetch.svelte";
  import Form from "./Form.svelte";

  let searchTerm;

  function handleSubmit() {
    const { value } = this.elements.search;
    searchTerm = value;
  }
</script>

<Form {handleSubmit} />
<Fetch {searchTerm} let:data>
  <h1>A list of links</h1>
  <ul>
    {#each data as link}
      <li>
        <a href={link.url}>{link.title}</a>
      </li>
    {/each}
  </ul>
</Fetch>
```

Quase pronto. Salve todos os arquivos e execute o servidor de desenvolvimento. Você vai ver... uma página em branco!

![](https://www.valentinog.com/blog/wp-content/uploads/2019/06/svelte-3-tutorial-reactivity.png)

O que está acontecendo? Segure firme e vá para a próxima seção!

# 14. Reatividade

A maneira como a Svelte lida com **valores calculados** pode não parecer intuitiva no começo. Nosso problema está em **Fetch.svelte** e vem das seguintes linhas:

```js
const regex = new RegExp(searchTerm, "gi");

const data = searchTerm
    ? jsonResponse.filter(element => element.title.match(regex))
    : jsonResponse;
```

Se você pensar sobre isso, temos dois valores calculados. RegExp depende do searchTerm e queremos recalcular o primeiro toda vez que o último for alterado.

Então nós temos a variável **data**: ele deve recalcular também toda vez que searchTerm e RegExp mudarem. É como uma planilha: os valores podem depender de outros valores.

Svelte se inspira em "programação reativa" e usa uma sintaxe estranha para os chamados valores computados. Esses valores são chamados de **"declarações reativas"** no Svelte 3. Veja como você deve ajustar o código acima:

```js
$: regex = new RegExp(searchTerm, "gi");

$: data = searchTerm
    ? jsonResponse.filter(element => element.title.match(regex))
    : jsonResponse;
```

**$:** não é uma língua alienígena. É simplesmente JavaScript, e é chamado de [Instrução Rotulada](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label).

Aqui está o **Fetch.svelte** completo novamente:

```vue
<script>
  import { onMount } from "svelte";

  export let url = "https://academy.valentinog.com/api/link/";
  export let searchTerm = undefined;
  let jsonResponse = [];

  $: regex = new RegExp(searchTerm, "gi");

  $: data = searchTerm
    ? jsonResponse.filter(element => element.title.match(regex))
    : jsonResponse;

  onMount(async function() {
    const response = await fetch(url);
    const json = await response.json();
    jsonResponse = json;
  });
</script>

<slot {data} />
```

Agora, o recurso de pesquisa funcionará como esperado:

![](https://www.valentinog.com/blog/wp-content/uploads/2019/06/svelte-3-search-form.png)

(Filtragem de Links no nível da API teriam sido uma abordagem melhor do que buscar todos os links todas as vezes).

Agora confira a próxima seção se você está curioso para ver como o mesmo "aplicativo" é implementado com o React.

# 15. Comparando com React

Como que o mesmo aplicativo ficaria em React? Aqui está o **App.js**, que é o equivalente do **App.svelte**:

```jsx
import React, { useState } from "react";
import Fetch from "./Fetch";
import Form from "./Form";

function App() {
  const [searchTerm, setSearchTerm] = useState("");

  const fetchProps = {
    url: "https://academy.valentinog.com/api/link/",
    searchTerm
  };

  function handleSubmit(event) {
    event.preventDefault();
    const { value } = event.target.elements.search;
    setSearchTerm(value);
  }

  return (
    <>
      <Form handleSubmit={handleSubmit} />
      <Fetch
        {...fetchProps}
        render={links => {
          return (
            <>
              <h1>A list of links</h1>
              <ul>
                {links.map(link => (
                  <li key={link.url}>
                    <a href={link.url}>{link.title}</a>
                  </li>
                ))}
              </ul>
            </>
          );
        }}
      />
    </>
  );
}

export default App;
```

Aqui estou usando o componente Fetch com uma prop de renderização. Eu poderia usar um hook, mas eu queria mostrar a você como o mesmo conceito se aplica tanto ao Svelte quanto ao React.

Em outras palavras:

- Para acessar o estado de um componente pai a partir de um componente filho no React, você pode usar props de renderização (ou um hook personalizado para compartilhamento da busca de dados)
- para acessar o estado de um componente pai de um slot Svelte, você pode encaminhar os dados para cima a partir do pai

Se você comparar **App.js** com a versão Svelte ([clique aqui](https://github.com/valentinogagliardi/svelte-tutorial/blob/master/src/App.svelte)), poderá ver que um típico componente Svelte é menos detalhado que um equivalente em React.

Facilmente explicado pelo fato de que **no Svelte 3 não há necessidade de chamar explicitamente setSomeState ou funções similares. O Svelte "reage" apenas atribuindo valores às variáveis.**

Em seguida, **Form.js**, um espelho React do **Form.svelte**:

```jsx
import React from "react";

function Form(props) {
  return (
    <form onSubmit={props.handleSubmit}>
      <label htmlFor="search">Search:</label>
      <input type="search" id="search" required={true} />
      <button type="submit">Search</button>
    </form>
  );
}

export default Form;
```

Nada muito diferente, apenas uma função recebendo algumas props.

Finalmente, há o **Fetch.js**, espelhando o **Fetch.svelte**:

```jsx
import { useState, useEffect } from "react";

function Fetch(props) {
  const { url, searchTerm } = props;
  const [links, setLinks] = useState([]);
  const regex = new RegExp(searchTerm, "gi");
  const data = searchTerm
    ? links.filter(link => link.title.match(regex))
    : links;

  useEffect(() => {
    fetch(url)
      .then(response => response.json())
      .then(json => setLinks(json));
  }, [url]);

  return props.render(data);
}

Fetch.defaultProps = {
  url: "https://academy.valentinog.com/api/link/"
};

export default Fetch;
```

O componente acima usa hooks e render props: novamente, isso é desnecessário porque você pode extrair tudo em um hook personalizado. E aqui está **Fetch.svelte**:

```vue
<script>
  import { onMount } from "svelte";

  export let url = "fillThis";
  export let searchTerm = undefined;
  let jsonResponse = [];

  $: regex = new RegExp(searchTerm, "gi");

  $: data = searchTerm
    ? jsonResponse.filter(element => element.title.match(regex))
    : jsonResponse;

  onMount(async function() {
    const response = await fetch(url);
    const json = await response.json();
    jsonResponse = json;
  });
</script>

<slot {data} />
```

Para mim, eles são muito parecidos! No entanto, esses exemplos não estão nem perto de um aplicativo grande e sua milhagem pode variar.

# 16. Como o Svelte se compara ao React e Vue?

Já me perguntaram o que acho de Svelte comparado a React e Vue. Eu não posso falar por Vue porque eu não tenho muita experiência com isso, mas eu posso ver como Svelte toma algumas coisas emprestado.

Falando de React, Svelte raciocina bem para mim e parece mais intuitivo do que o seu equivalente. Num piscar de olhos, o Svelte 3 parece apenas mais uma maneira de fazer as coisas, talvez mais esperto do que o React. Mas a base dele é sólida.

O que é realmente interessante em Svelte é que não há DOM Virtual, diferente de React e Vue. Em outras palavras, não há abstração entre a biblioteca e o [Modelo de Objeto de Documento](https://www.valentinog.com/blog/dom/) real: o Svelte 3 compila o JavaScript "vanilla" mínimo possível. Isso é útil se você estiver executando seu aplicativo em ambientes restritos.

Para recapitular, o Svelte é uma biblioteca bastante interessante, mas darei mais tempo, pelo menos, até que a documentação, o ecossistema e as ferramentas fiquem maduras.

# 17. Mais Recursos

Para aprender mais sobre o Svelte, não posso recomendar o suficiente a [documentação oficial](https://svelte.dev/docs) e os [exemplos](https://svelte.dev/examples).

[O código fonte deste tutorial está disponível aqui](https://github.com/valentinogagliardi/svelte-tutorial).

Também recomendo assistir a essa apresentação do criador do Svelte:

https://www.youtube.com/watch?v=AdNJ3fydeao

# 18. Finalizando

Para onde ir a partir daqui? Há muito mais para aprender sobre o Svelte 3 se você quiser. E há muitas novidades prontas para uso:

- Estilos com escopo (*scoped styles*)
- data-binding de duas vias (*two way data-binding*)
- Gestão de estados (*state management*)
- Animações incorporadas (*built-in animations*)

E antes de dizer adeus, algumas palavras finais:

JavaScript é brutal. Bibliotecas vêm e vão e há sempre algo novo para aprender. Ao longo dos anos, aprendi a não ficar muito amarrado a nenhuma biblioteca JavaScript em particular, mas com toda a honestidade, eu realmente gosto de React e Redux.

React trouxe "componentes" para as massas, por outro lado, a própria biblioteca requer alta especialização para ser dominada. Vue, ao contrário, é mais amigável para iniciantes, mas infelizmente não é percebido como “moderno” como React (o que quer que isso signifique).

O Svelte 3 tem o melhor dos dois mundos: os componentes Svelte se parecem com os do Vue e alguns dos conceitos do React se aplicam também.

O Svelte é mais intuitivo que o React , especialmente se pensarmos em um iniciante que se aproxima do React na era do Hooks. Porém, React não está indo embora tão cedo, mas estou ansioso para ver onde Svelte está indo.

E para você, meu amigo, sempre há meu antigo conselho: sempre continue aprendendo a plataforma web e você será capaz de dominar qualquer biblioteca JavaScript que vier em seguida.

Obrigado por ler e fique ligado neste blog!

# Créditos ⭐️

- [Svelte 3 Tutorial for The Impatient (React) Developer
](https://www.valentinog.com/blog/svelte/), originalmente escrito por [Valentino Gagliardi](https://twitter.com/gagliardi_vale)