Reatividade
Até aqui, vimos como definir propriedades e como passá-las para os componentes. Agora veremos como tornar essas propriedades reativas, ou seja, atualizar o DOM toda vez que elas mudarem.
Atribuições
Observe o código de exemplo abaixo:
<!-- App.svelte -->
<script>
let idade = 0;
let altura = 0;
function crescer() {
altura += 1;
}
</script>
<p>Minha altura é {altura} e minha idade é {idade}</p>
<button on:click={crescer}> Crescer </button>
<button> Ficar mais velho </button>
Vamos adicionar um pouco de interatividade. Criaremos a função “crescer” que aumenta o valor de “altura” em 1. Essa função ficará no App.svelte.
<script>
let idade = 0;
let altura = 0;
function crescer() {
altura + 1;
}
</script>
<p>Minha altura é {altura} e minha idade é {idade}</p>
<!-- Veremos sobre esse "on:click" mais a frente. -->
<button on:click={crescer}> Crescer </button>
<button> Ficar mais velho </button>
Quando clicamos no botão “Crescer”, olhe o que acontece:

Por que não funciona?
Simples! A reatividade no svelte acontece por atribuição de valor à uma variável. No exemplo acima, estamos dizendo que a variável altura deve adicionar + 1 ao seu valor, mas não estamos fazendo atribuição.
Uma regra prática simples: a variável atualizada deve aparecer diretamente no lado esquerdo da atribuição. Svelte tutorial
Para isso, devemos dar à variavél altura seu valor inicial + 1. Olhe abaixo:
<script>
let idade = 0;
let altura = 0;
// Observe esse trecho de código
function crescer() {
altura = altura + 1;
}
</script>
<p>Minha altura é {altura} e minha idade é {idade}</p>
<!-- Veremos sobre esse "on:click" mais a frente. -->
<button on:click={crescer}> Crescer </button>
<button> Ficar mais velho </button>
Agora, vamos testar!

Pronto, funciona!
Mas o javascript nos oferece outras maneiras de adicionar um valor a uma variável;
<script>
let idade = 0;
let altura = 0;
function crescer() {
// Operadores de atribuição
altura = altura + 1; // Modo normal
// OU
altura += 1; // Modo encurtado
// OU
// Operadores aritiméticos
altura++ // Pós incremento
}
</script>
Todos os operadores acima funcionam bem para nosso caso. Escolha 1 deles.
Declarações reativas
Vamos falar agora sobre declarações no svelte e como funcionam.
Primeiro, olhe o código!
<script>
let numero = 5;
// Isso é estranho à primeira vista, mas é javascript.
$: dobro = numero * 2
</script>
Isso se chama Label.
A sintaxe é a seguinte:
label : declaração
A “label” pode ser qualquer idenfiticador JavaScript válido que não é uma palavra reservada. Leia sobre identificador. Sendo assim, esse ”$” é válido.
Já a “declaração” pode ser uma declaração qualquer: (Exemplo: variáveis, funções, blocos if, blocos switch, console.log e outros mais )
Observação sobre a label: Eu poderia escrever assim: qualquerCoisa: dobro = numero * 2
e funcionaria normalmente. Mas por quê não faço isso e você também não deve? Porque a sintaxe padrão do svelte é com ”$” e se você alterar vai dificultar o entendimento de outras pessoas.
Observe abaixo o que podemos fazer:

O que está acontecendo aqui? A variável dobro
está sendo atualizada com base na mudança da variável numero
.
Como isso é possível? Reatividade amigos.
Podemos manter o DOM em sincronia com as variáveis e também manter as variáveis em sincronia umas com as outras.
Ok, mas eu poderia fazer isso: let dobro = numero * 2
! Será? Vejamos abaixo:

A variável dobro não é mais reativa!
Vamos entender como é o funcionamento da declaração reativa:
- Primeiro, os demais códigos de script são executados.
- Segundo, a declaração reativa é executada.
- Terceiro, o DOM é atualizado.
Observação: Poderíamos escrever {numero * 2}
no lugar de {dobro}
. Mais simples, concorda?
Mas isso é necessário quando você precisa referenciar essa declaração em vários lugares ou quando você quer alterar um valor, baseado em outro valor, ou seja, quando um depende do outro.
Outra coisa, na declaração $: dobro = numero * 2
a variável dobro
é criada automaticamente pelo svelte.
Você não precisa fazer isso aqui:
<script>
let numero = 1
// Você NÃO precisa declarar essa variável.
let dobro;
$: dobro = numero * 2
</script>
O svelte já transforma dobro
em uma let
.
Vamos fazer mais coisas!
Instruções reativas
Declarar valores reativos é legal, mas podemos fazer mais. Apresento a vocês as “instruções reativas”.
Quero fazer um console.log
toda vez que a variável number
for ímpar.

Perceba que o a instrução é executada na primeira renderização, e depois executada todas as vezes que number
mudar.
É possível agrupar várias instruções.
<script>
let number = 1;
// Posso fazer isso
$: if (number % 2 !== 0) {
console.log(`O número ${number} é ímpar`)
}
// OU isso
$: {
if (number % 2 !== 0) {
console.log(`O número ${number} é ímpar`)
} else {
console.log(`O número ${number} é par`)
}
}
</script>
Podemos desestruturar objetos e arrays. Se eles mudam, os valores também mudam.
<script>
let person = {name: 'Ana', age: 20};
let numbers = [1,2,3];
// Desestruturação de objeto - Precisa colocar entre parênteses
$: ({name} = person);
// Desestruturação de array - NÃO Precisa colocar entre parênteses
$: [firstNumber] = numbers;
function changeName() {
// Vou mudar a propriedade "name" do objeto "person" e isso irá acionar a reatividade da variável
// "name"
person.name = 'Cristina'
}
function changeFirstNumber() {
// Mudar o array também aciona a reatividade. Agora o primeiro número do array será 4.
numbers = [4, ...numbers]
}
</script>
<button on:click={changeName}>Mudar nome</button>
<button on:click={changeFirstNumber}>Mudar array</button>
<p>Nome: {name} </p>
<p>Primeiro numero do array: {firstNumber} </p>
Olhe o código acima em funcionamento.

Atenção!
Apenas os valores que aparecem diretamente no $:bloco se tornarão dependências da instrução reativa. Svelte docs
Vamos entender melhor. Observe o código abaixo:
<script>
let name = 'Ana'
let lastName = 'Beatriz'
function getFullName(name) {
return `${name} ${lastName}`
}
// A única variável que aparece nesse bloco é "name", ou seja,
// esse bloco só vai ser acionado quando
// "name" mudar. Alterar "lastName" não aciona esse bloco.
$: fullName = getFullName(name)
</script>
<p>{fullName}</p>
<button on:click={() => name = 'Maria'}>
Mudar nome
</button>
<button on:click={() => lastName = 'Soares'}>
Mudar sobrenome
</button>
Esse é o resultado.

Acontece que o bloco reativo só “reage” às mudanças nas variáveis que estão dentro dele. A função getFullName
recebe a variável name
e toda vez que ela muda, o bloco reativo é acionado. Coisa que não acontece com a variável lastName
. É muito importante saber isso.
Vamos alterar o código para que o bloco reativo seja acionado na mudança das duas variáveis.
<script>
let name = 'Ana'
let lastName = 'Beatriz'
function getFullName(name, lastName) {
return `${name} ${lastName}`
}
// Agora esse bloco será acionado sempre que "name" e "lastName" mudarem.
$: fullName = getFullName(name, lastName)
</script>
<p>{fullName}</p>
<button on:click={() => name = 'Maria'}>
Mudar nome
</button>
<button on:click={() => lastName = 'Soares'}>
Mudar sobrenome
</button>

Percebeu a diferença? Se você conhece o React, sabe que isso é semelhante ao array de dependências do useEffect
.
Modificando Arrays e Objetos
Aprenderemos como acionar a reatividade do svelte alterando arrays e objetos.
Bom, vimos anteriormente que a reatividade funciona por atribuição. Mas e se alterarmos um array ou objeto usando seus métodos?
Vejamos:
<script>
let names = ['José', 'Maria', 'Antônio'];
// Método push adiciona um item ao final do array e retorna o novo tamanho do array.
function addName(name) {
names.push(name)
}
</script>
<h1>Olá {names}!</h1>
<button on:click={() => addName('Pedro')}>
Add nome
</button>

Precisamos fazer atribuição. Não se esqueça! Observe agora:
<script>
let names = ['José', 'Maria', 'Antônio'];
// Método push adiciona um item ao final do array e retorna o novo tamanho do array.
function addName(name) {
names = names.push(name) // Será que isso vai funcionar?
}
</script>
<h1>Olá {names}!</h1>
<button on:click={() => addName('Pedro')}>
Add nome
</button>

Não funcionou né? Mas por quê? Bom, olhe o que eu escrevi no comentário do código. “Método push adiciona um item ao final do array e retorna o novo tamanho do array.”
A variável names
está recebendo como valor o tamanho do array e não é isso que queremos.
Vamos consertar!
<script>
let names = ['José', 'Maria', 'Antônio'];
// Método push adiciona um item ao final do array e retorna o novo tamanho do array.
function addName(name) {
names.push(name)
// Basta fazer a atribuição.
// A variável "names" recebe a mesma variável, porém com o array alterado.
names = names
}
</script>
<h1>Olá {names}!</h1>
<button on:click={() => addName('Pedro')}>
Add nome
</button>
Ou de maneira mais direta.
<script>
let names = ['José', 'Maria', 'Antônio'];
// Aqui usamos o "spread operator" para colocar dentro do novo array tudo que ele tinha + name
function addName(name) {
names = [...names, name]
}
</script>
Vejamos em ação!

É assim que se modifica um array no svelte. Sempre por atribuição.
E com objetos? A mesma coisa.
<script>
let person = {name: 'Ana', age: 1}
// Alterar alguma propriedade do objeto "person" aciona a reatividade.
function changeAge(age) {
person.age = age
}
</script>
<h1>{person.name} tem {person.age} {person.age > 1 ? 'anos' : 'ano'}!</h1>
<button on:click={() => changeAge(19)}>
Mudar idade
</button>

Agora, tem algo que não funciona! É quando fazemos atribuições a referências de objetos.
Observe abaixo:
<script>
let person = {name: 'Ana', age: 1}
// Aqui estamos recebendo um obj por parâmetro e fazendo a atribuição.
// Deveria funcionar como no exemplo anterior. Mas não!
function changeAge(obj) {
obj.age = 19
}
</script>
<h1>{person.name} tem {person.age} {person.age > 1 ? 'anos' : 'ano'}!</h1>
<!-- Aqui passamos o obj "person" para a função -->
<button on:click={() => changeAge(person)}>
Mudar idade
</button>

Fique atento a isso. Passar um objeto por referência e alterar seu valor não ativa a reatividade!
Mas… Podemos fazer o exemplo acima funcionar! Como? Atribuição. Já falei essa palavra várias vezes e isso é pra você saber que é assim que a reatividade do svelte funciona. Atribuição!
Olhe o exemplo:
<script>
let person = {name: 'Ana', age: 1}
function changeAge(obj) {
obj.age = 19
// Basta atribuir "person" ao objeto modificado.
person = obj
}
</script>
<h1>{person.name} tem {person.age} {person.age > 1 ? 'anos' : 'ano'}!</h1>
<button on:click={() => changeAge(person)}>
Mudar idade
</button>
Ou
<script>
let person = {name: 'Ana', age: 1}
// "Spread operator" em ação, agora com objetos.
function changeAge(obj) {
person = {...obj, age: 19}
}
</script>
<h1>{person.name} tem {person.age} {person.age > 1 ? 'anos' : 'ano'}!</h1>
<button on:click={() => changeAge(person)}>
Mudar idade
</button>

Vamos utilizar a declaração reativa? Só pra relembrar!
<script>
let person = {name: 'Ana', age: 1}
function changeAge(obj) {
person = {...obj, age: 19}
}
// Com a declaração reativa, podemos melhorar nosso código. Se precisarmos
// usar esse código em outro lugar, basta usar a variável "pluralOrSingular".
$: pluralOrSingular = person.age > 1 ? 'anos' : 'ano'
</script>
<h1>{person.name} tem {person.age} {pluralOrSingular}!</h1>
<button on:click={() => changeAge(person)}>
Mudar idade
</button>
Bom, a variável pluralOrSingular
só serve pra “anos”! Podemos modificar essa declaração para ser mais genérica.
Mas atenção! Você já pode ir para a próxima página. Aqui só vamos treinar um pouco.
Vamos nessa!
Olha o que eu fiz:
<script>
let person = {name: 'Ana', age: 1}
function changeAge(obj) {
person = {...obj, age: 19}
}
// Função bem simples. "textToModify" é o texto que quero transformar em plural ou não.
// "property" é a propriedade do objeto que eu quero usar de comparação.
// pra ver se vai ser plural ou não.
function getPluralOrSingular(textToModify, property) {
return property > 1 ? textToModify + 's' : textToModify
}
$: pluralOrSingular = getPluralOrSingular('ano', person.age)
</script>
<h1>{person.name} tem {person.age} {pluralOrSingular}!</h1>
<button on:click={() => changeAge(person)}>
Mudar idade
</button>
Vocẽ se lembra o que eu disse sobre a declaração reativa?
Eu disse que ela só aciona a retividade dos valores que aparecem nela. Foi por isso que chamei a função getPluralOrSingular
passando person.age
por parâmetro. É pra que seja reativa toda vez que person.age
mudar.
E continua funcionando, só que agora está mais genérica. Olhe só:

Da pra fazer muito mais coisas. Foquei apenas no necessário relacionado ao svelte. O restante é javascript puro. Modifique o código à vontade.