React - Persistindo dados na URL 💾
Compartilhar conteúdo é o que há de mais comum na internet e em aplicativos. Compartilhamos fotos, mensagens e tudo mais que podemos. Dentre o que mais compartilhamos estão as URLs.
Abaixo, vou mostrar como podemos guardar e recuperar informações via URL em aplicações React. Dessa maneira usuários podem compartilhar a URL mantendo o mesmo estado da página compartilhada.
Uma lista com filtros
Uma implementação bem comum quando desenvolvendo um aplicativo, é aplicar filtros em uma lista de dados. Por exemplo, uma tabela com dados pessoais e filtros por coluna ou, uma página de produtos de um E-commerce que contém filtros para cada atributo de seus items. Ser capaz de compartilhar a página em questão com todos os filtros aplicados é fundamental.
Vamos ao código:
Abaixo tenho a minha aplicação: Uma lista com dados de pessoas como nome, sobrenome, idade e profissão. A aplicação tem 2 componentes importantes:
- App (Principal)
- List (Componente genérico de lista)
O componente App
importa os dados da lista - que no caso abaixo é apenas um arquivo com dados aleatórios contendo nome, idade e cidade. Poderia também ser dados de uma API qualquer.
import List from './List';
import { LIST_HEADERS, PERSONAL_DATA_LIST } from './data';
function App() {
return (
<div className="App">
<List headers={LIST_HEADERS} data={PERSONAL_DATA_LIST} />
</div>
);
}
export default App;
O component List
recebe os dados da lista, bem como o cabeçalho a ser mostrado. Baseado nestas duas informações a tabela é montada.
const List = ({ headers = [], data = [] }) => {
return (
<table>
<thead>
<tr>
{headers.map((header) => (
<th key={header}>{header.toUpperCase()}</th>
))}
</tr>
</thead>
<tbody>
{data.map((item) => (
<tr key={item.id}>
{headers.map((header) => (
<td key={header}>{item[header]}</td>
))}
</tr>
))}
</tbody>
</table>
);
};
export default List;
O resultado é:
O meu próximo passo é fazer com que a usuário consiga ordenar a tabela simplesmente clicando em um dos items do cabeçalho. Ou seja, ordenar a tabela por uma de suas colunas.
Para chegar lá vou separar o cabeçalho da minha tabela em um componente próprio e fazer com que cada item seja clicável. Vou criar o componente Headers
:
const Headers = ({ headers = [] }) => {
const headerClick = (header) => {
console.log(header);
};
return (
<thead>
<tr>
{headers.map((header) => (
<th onClick={() => headerClick(header)} key={header}>{header.toUpperCase()}</th>
))}
</tr>
</thead>
);
}
export default Headers;
E então, atualizar o componente List
para importar o novo componente Headers
import Headers from "./Headers";
const List = ({ headers = [], data = [] }) => {
return (
<table>
{<Headers headers={headers} />}
<tbody>
{data.map((item) => (
<tr key={item.id}>
{headers.map((header) => (
<td key={header}>{item[header]}</td>
))}
</tr>
))}
</tbody>
</table>
);
};
export default List;
Ao clicar em algum dos items do cabeçalho, imprimo um log com o respectivo header
clicado:
Manipulando a URL
Agora vou atualizar o método headerClick
para guardar na URL qual o último cabeçalho foi clicado. Para isso vamos utilizar o construtor URLSearchParams. Veja como ficou:
const headerClick = (header) => {
const urlParams = new URLSearchParams(window.location.search);
urlParams.set('sort', header);
window.location.search = urlParams;
};
Na primeira linha recupero todas a variáveis de URL disponíveis, ou seja, tudo do tipo: ?variavel=1
.
Na segunda linha definimos o parâmetro sort
com o valor do cabeçalho clicado. Ex: ?sort=name
.
E por fim, na terceira linha, escrevo minha alteração na URL.
A partir deste momento, qualquer clique em um dos items do cabeçalho vai resultar na alteração da URL, com o parâmetro sort
sendo atualizado de acordo.
Lendo os parâmetros da URL
Meu último passo é ler o parâmetro sort
da URL e então ordenar a minha lista de acordo com este parâmetro. Para isso vou utilizar o mesmo construtor utilizado anteriormente, com a diferença do método get
ao invés do método set
. Veja como ficaram as alterações no component List
:
import Headers from './Headers';
const List = ({ headers = [], data = [] }) => {
const urlParams = new URLSearchParams(window.location.search);
const sort = urlParams.get('sort');
...
Agora que sei exatamente qual item foi clicado, posso ordenar a lista de acordo:
const urlParams = new URLSearchParams(window.location.search);
const sort = urlParams.get('sort');
const dataSorted = data.sort((a, b) => {
if (a[sort] < b[sort]) {
return -1;
}
if (a[sort] > b[sort]) {
return 1;
}
return 0;
});
Fiz uso do método sort
para ordenar a lista. No método em questão, eu comparo os valores da lista para a propriedade selecionada e retorno um número positivo ou negativo, baseado no resultado desta comparação.
Por exemplo, se minha variável sort
tem como valor name
, vou então comparar apenas os items da propriedade name
(a[sort]
). Vejo então que João vem antes (é menor) que Maria e portanto, deve aparecer primeiro na lista.
Este é o resultado após clicar no cabeçalho name
:
Ir além
Guardar dados na URL é extremamente efetivo quando sabemos que o usuário deseja compartilhar a página em questão da maneira como ele vê. E não se limita apenas a listas. É possível utilizar esta técnica de inúmeras maneiras diferentes.
Por exemplo, quando utilizamos a ferramenta Jira, é possível compartilhar uma URL com um parâmetro para que o modal do ticket esteja aberto. Desta maneira, o usuário que receber a URL compartilhada saberá exatamente o que o outro usuário está compartilhando.
Aproveite então desta técnica, utilize a sua criatividade e faça páginas com melhor usabilidade.
Veja o código deste post aqui
Compartilhe este artigo no Twitter.