Documentação completa da Biblioteca:

SWR: React Hooks for Data Fetching

Stay While Revalidation

Isso quer dizer que ele vai mostrar os dados do cache enquanto você não conseguir buscar os novos dados, Ele vai buscar as informações do cache e mostrar, mesmo assim ele vai fazer uma nova requisição, então, se tiver uma nova informação, ele vai mostrar.

Revalidate on Focus

Quando o usuario deixar o site aberto por um tempo, quando o usuario voltar e clicar na janela, o SWR por debaixo dos panos ele vai recarregar(Sem f5), e mostrar as informações mais recentes.

$ yarn add swr
// > hooks > useFetch.ts
import useSWR from 'swr';

// "url" e a url da requisição que eu quero fazer.
export function useFetch(url: string) {
  /*
    Como primeiro parametro colocamos a url, e o segundo 
    parametro colocamos oque nos ultilizamos para obter os dados 
    da nossa requisição, se caso foi o fetch
  */
  const { data, error } = useSWR(url, async url => {
    /*
      Aqui vamos retornar os dados, e caso tenha ocorrido algum 
      error, vamos retornar esse error.
    */

    const response = await fetch(url);
    const data = await response.json();

    return data;
  });
// > UserList.tsx
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { useFetch } from '../hooks/useFetch';

interface User {
  id: number;
  name: string;
}

const UserList: React.FC = () => {
  const { data } = useFetch<User[]>('<http://localhost:3333/users>');
	/* Temos passar a interface User como um generic.
		Ele ainda vai esta reclamando, porque o nosso hook não está preparado
		para receber esse Generic.
	*/

  return (
    <ul>
      {data.map(user => {
        return (
          <li key={user.id}>
            <Link to={`/users/${user.id}`}>
              {user.name}
            </Link>
          </li>
        );
      })}
    </ul>
  );
};
// ------------------------------------------------------------------

// > hooks > useFetch.ts
import useSWR from 'swr';

/* Data = any ele vai receber o formato do data, e caso o data não seja
 informado ele vai ser "qualquer tipo" */
export function useFetch<Data = any, Error = any>(url: string) {
  const { data, error } = useSWR<Data, Error>(url, async url => {
		// O useSWR recebe o Data como generic.
    const response = await fetch(url);
    const data = await response.json();

    return data;
  });

  return { data, error };
};
const UserList: React.FC = () => {
  const { data } = useFetch<User[]>('<http://localhost:3333/users>');

  /* Os dados vai demorar para chegar, então no primeiro momento ele vai 
		estar vazio(underfined), por isso estou fazendo esse if, se não tiver
		alguma estrategia assim, o typescript vai 
    ficar reclamando la no {data.map(user => {... falando que o "data" e 
		underfined.
  */
  if (!data) {
    return <p>Carregando...</p>
  }

  return (
    <ul>
      {data.map(user => {
        return (
          <li key={user.id}>
            <Link to={`/users/${user.id}`}>
              {user.name}
            </Link>
          </li>
        );
      })}
    </ul>
  );
};

/*Ou podemos colocar um ponto de interrogação, indicando pro typescript
	que e só para mostrar essa informação quando estiver carregado. 
	(Não vamos precisar usar o if)
*/
  return (
    <ul>
      {data?.map(user => {
        return (
          <li key={user.id}>
            <Link to={`/users/${user.id}`}>
              {user.name}
            </Link>
          </li>
        );
      })}
    </ul>
  );
};

Algumas configurações que você pode passar no SWR

export function useFetch<Data = any, Error = any>(url: string) {
  const { data, error } = useSWR<Data, Error>(url, async url => {
    const response = await fetch(url);
    const data = await response.json();

    return data;
  }, {
    errorRetryCount: 5,
		onErrorRetry(...),
		errorRetryInterval: 5000,
		initialData...,
		loadingTimeout...,
		loadingTimeout: 5000,
    onLoadingSlow(key, config, loadingTimeout),
		revalidateOnReconnect: true
  });
	// errorRetryCount: Se ocorrer alguma error, quantas vezes ele vai tentar.
	// onErrorRetry: Se ocorrer um error, devo tentar novamente?
	/* errorRetryInterval: Se ocorrer um error, quanto tempo de intervalo devo 
	tentar novamente.
	*/
	// initialData: se os dados não estiverem prontos oque devo mostrar...
	// loadingTimeout: posso colocar um timeout na minha aplicação inteira.
	// onLoadingSlow: Caso esteja demorando muito, eu posso mostrar uma mensagem
	/* revalidateOnReconnect: Caso o user ficar offline, quando ele ficar online,
		E feito um recarregamento dos dados automaticamente sem precisar fechar 
		e abrir o browser.
	*/
	

  return { data, error };
};

Axios, Mutação de dados e multiplos componentes.