Executando verificação de segurança...
2

Turbine suas páginas web com o localStorage!

O que é localStorage?

Por padrão, as páginas web não guardam dados. Se você atualizar a página enquanto escreve um texto, o texto é perdido para sempre. Essa falta de persistência pode ser muito frustrante em situações como:

  • Definir a página para o modo escuro, mas vê-la voltar para o modo claro na próxima vez que acessá-la 😑

  • Gastar tempo escolhendo produtos para um carrinho de compras, mas descobre que ela está vazia ao retornar mais tarde para finalizar a compra 😫

  • Escrever um post longo em um blog e perder o texto quando o post é enviado sem estar conectado à Internet ou o servidor retorna um erro 😫

Usando o localStorage, seus aplicativos podem salvar informações sem a necessidade de um servidor backend. Isso significa que não há necessidade de infraestrutura de armazenamento e não há custos para você, pois os dados estão sendo armazenados no computador do usuário em vez de um servidor que você gerencia.

localStorage também pode ser usado para páginas estáticas terem persistência de dados. Imagine que você criou um aplicativo simples de lista de tarefas que está hospedado no Github Pages. Ele é rápido para carregar e pode ser hospedado gratuitamente, mas é inútil, pois quando o usuário sai da página, todas as suas tarefas são perdidas 😭. O localStorage pode resolver esse problema salvando as tarefas no navegador do usuário.

Veja como usar o localStorage:

  • setItem() salva dados no navegador do usuário

  • getItem() recupera os dados salvos do navegador do usuário

  • removeItem() remove os dados salvos do navegador do usuário

Exemplo 1: Modo escuro

Suponha que eu tenha uma página da web que tenha uma opção de modo escuro e que gostaria que a página lembrasse da preferência do usuário. Observe que, ao recuperar dados do localStorage, getItem() sempre retorna os dados como uma string, portanto, você precisa converter para o tipo original de dados que você salvou originalmente usando JSON.parse() para evitar usar true como 'true', que é uma string, e geraria comportamentos muito estranhos ao fazer comparações, o que pode levar a erros no aplicativo:

// Salva a preferência do usuário
localStorage.setItem('modoEscuro', true)

// Recupera a preferência do usuário do localStorage
// getItem() sempre retorna uma string
const dadosModoEscuro = localStorage.getItem('modoEscuro') 
// retorna uma string: 'true'

// Converte a string em um valor booleano
const modoEscuro = JSON.parse(dadosModoEscuro)
// retorna um booleano: true

Exemplo 2: Uma página estática

No segundo exemplo, tenho um aplicativo de lista de tarefas e quero salvar minha lista de tarefas. Posso salvar o array no localStorage, mas ao salvar estruturas de dados complexas como objetos e arrays, preciso convertê-los em uma string usando JSON.stringify():

const listaTarefas = [
'Ir à academia',
'Preparar o jantar',
'Ir ao supermercado',
]

// Array listaTarefas é convertido em uma string
arrayComoString = JSON.stringify(listaTarefas)

// Armazena o array como valor da chave 'tarefas'
localStorage.setItem('tarefas', arrayComoString)

Por que eu preciso do JSON.stringify()?

Você pode estar pensando que se o localStorage.setItem() já salva o valor como uma string, qual a necessidade de converter antes o valor em uma string usando JSON.stringify()?
Por trás das cortinas, localStorage.setItem() usa toString(), o que resulta em alguns resultados inesperados em comparação com JSON.stringify():

/* Com booleano, inteiro ou float, o resultado é o mesmo */
const boolExemplo = true

boolExemplo.toString()
// Retorna 'true'

JSON.stringify(true)
// Retorna 'true'

// Os dois métodos retornam o mesmo resultado

/* Mas ao usar objetos, os resultados são muito diferentes */

const produto = {
tipo: 'sorvete',
preco: 1.20,
quantidade: 2
}

produto.toString()
// Retorna '[object Object]'

JSON.stringify(produto)
// Retorna '{"name":"sorvete","price":1.2,"quantity":2}'

/* Com arrays, existem diferenças inesperadas também */

const usuarios = ['Paulo', 'Maria', 'Ken']

usuarios.toString()
// Retorna 'Paulo,Maria,Ken'

JSON.stringify(usuarios)
// Retorna '["Paulo","Maria","Ken"]'

JSON.stringify() converte objetos e arrays em strings de uma maneira que é possível convertê-los facilmente de volta aos seus formatos originais. Por outro lado, toString() remove informação sobre a estrutura de dados, tornando difícil ou impossível convertê-los de volta à sua forma original.

Exemplo 3: Um carrinho de compras

const itemsCarrinho = [
{
    produto: 'sorvete',
    sabor: 'baunilha',
    quantidade: 1
},
{
    produto: 'hambúrguer',
    toppings: ['picles', 'queijo'],
    quantidade: 2
}
]

// Da mesma forma que antes, convertemos o array de objetos em uma string
arrayComoString = JSON.stringify(itemsCarrinho)

// Armazenamos o array de objetos convertido em string
localStorage.setItem('carrinho', arrayComoString)

// É possível deletar o carrinho
localStorage.removeItem('carrinho')

Conclusão

localStorage é uma ótima maneira de armazenar dados sem a necessidade de configurar e manter um bancos de dados. Você está transferindo a responsabilidade de armazenar dados de seus servidores para seus usuários, então é possível dar mais poder aos seus sites estáticos ou expandir as capacidades de sua página sem sobrecarregar seu banco de dados.

Os dados armazenados no localStorage não expiram e permanecerão enquanto o usuário não limpar o cache do navegador. Dependendo do navegador, ele pode armazenar até 5MB de dados ou uma quantidade ilimitada.

Mas atenção:
⚠️⚠️
Você nunca deve usar localStorage para armazenar dados sensíveis, como senhas, dados de login ou informações de cartão de crédito, porque os dados armazenados em localStorage não são criptografados e podem ser acessados por um hacker mal-intencionado ou até mesmo alguém que tenha acesso ao navegador pode ver o que está armazenado usando o developer tools.
⚠️⚠️

Por hoje é só e espero que tenham gostado! 😃
Fiquem à vontade para fazer perguntas e comentários! 😉

Carregando publicação patrocinada...
2

Não se limite ao localStorage

O localStorage é um recurso que acredito que todo desenvolvedor web deveria conhecer e que a maioria dos aplicativos deveria usar. No entanto, ele não é a única solução para armazenar dados no navegador e também não é a melhor solução para todos os casos.

Cookies

Os cookies são uma ótima solução para armazenar dados com mais segurança, quando nem o usuário nem algum script mal intencionado deve ser capaz de acessar a informação, e para quando o dado também deve estar disponível no servidor.
Um dos problemas da sua solução para dark theme é que, quando o aplicativo inicia, ele não sabe qual é a preferência de tema escuro do usuário até ler o localStorage. Isso pode causar o problema de muitos aplicativos piscando com um tema diferente quando iniciam e, em seguida, trocando rapidamente.
Os cookies são enviados em todas as requisições feitas para o seu site, inclusive na primeira, então seu aplicativo pode ser enviado para o cliente já com a opção de tema escolhida da última vez.

IndexedDB

IndexedDB é uma solução de armazenamento assíncrono do tipo chave-valor, onde o valor pode ser qualquer coisa compatível com um valor em um JSON, ou seja, sem a necessidade de stringify ou parse. Além disso, o tamanho disponível costuma ser muito maior do que o do localStorage (o limite do localStorage costuma ser de 5MB, enquanto o do indexedDB costuma ser de 20% a 80% do espaço livre em disco).
Um dos problemas do seu exemplo do carrinho de compras é que, como o localStorage é síncrono, dependendo do tamanho da lista e das informações nela contidas, a thread principal pode acabar sendo bloqueada por mais tempo do que o desejado, principalmente porque JSON.stringify e JSON.parse são operações razoavelmente custosas.

1

produto.toString() // Retorna '[object Object]'

Cara, isso explica um bug que eu tive em um projeto antigo.
Talvez algum dia eu vá consertar...

1