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á!
- Primeiro vamos criar uma pasta chamada
hooks
e um dentro dele um arquivo com o nome do seu hook, nesse casousePersistState.tsx
- 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){
...
};
- 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 essakey
que estamos passando, se não houver nada, retornará nossoinitialValue
, 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;
});
}
- 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;
- 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;
}