Apr 09, 2021

Como criar um hook customizado(usePersistState) para persistir dados no localStorage, com React e Typescript

2 minutos de leitura

Nesse artigo lhe mostrarei como criar um customHook para persistir estados do React usando o localStorage da api nativa do Browser e Typescript.

Tá, mas o que são os Hooks?

Os Hooks foram adicionado no React 16.8. Eles permitem que você use o state e outros recursos do React sem escrever classes, tudo com componentes funcionais.

CustomHooks é uma forma de você poder criar seus próprios hooks permitindo que você extraia toda a lógica de um componente em funções reutilizáveis.

Tá então vamos lá!

  1. Primeiro vamos criar uma pasta chamada hooks e um dentro dele um arquivo com o nome do seu hook, nesse caso usePersistState.tsx
  2. Em seguida vamos criar uma função passando um generic pra ela com o nome de <S> Esse generic faz com que todas as vezes que chamarmos nossa função poderemos dar um tipo para ela, facilitando na tipagem quando formos usar, desse jeito:
// key: é o nome da chave que passaremos para o localStorage.
// initialValue: Será o valor inicial do tipo do nosso generic.
export function usePersistState<S>(key: string, initialValue: S) {
  //...
}
  1. Agora criaremos um estado que terá o tipo do nosso generic, no valor inicial iremos passar uma função que retornará o valor armazenado no localStorage com essa key que estamos passando, se não houver nada, retornará nosso initialValue, ficando desse jeito:
export function usePersistState<S>(key: string, initialValue: S) {
  const [state, setState] = useState<S>(() => {
    const storageValue = localStorage.getItem(key);
 
    if (storageValue) return JSON.parse(storageValue);
 
    return initialValue;
  });
}
  1. Agora precisamos verificar todas as vezes que esse estado mudar, para podermos sempre atualizar o nosso dado armazenado no localStorage, e para isso precisamos usar o useEffect, um hook do React que lida com efeitos.

Caso não entenda como funciona o useEffect, você pode ler mais sobre na documentação do React, vou deixar o link no final desse artigo;

  1. Para finalizar vamos tipar o retorno da nossa função, retornando nosso state do tipo <S> e setState com o tipo: React.Dispatch<S>, Ficando assim o nosso código final.
export function usePersistState<S>(
  key: string,
  initialValue: S
): [state: S, setState: React.Dispatch<S>] {
  const [state, setState] = useState<S>(() => {
    const storageValue = localStorage.getItem(key);
 
    if (storageValue) return JSON.parse(storageValue);
 
    return initialValue;
  });
 
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(state));
  }, [state, key]);
 
  return [state, setState];
}

E para usar é simples você pode usar como se estivesse usando o useState do React;

type UserProps = {
  name: string;
  mail: string;
  avatar: string;
};
 
function App() {
  // Aquele <S> que definimos no nosso Hook passamos como generic aqui
  const [user, setUser] = usePersistState<UserProps>("sua_key", {});
 
  return null;
}