Série React Hooks: useSyncExternalStore
Tags: usesyncexternalstore, react, typescript, javascript
Published: 2023-07-10 11:10:06


![useSyncExternalStore](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i241dkt5c5dcp1sw2sku.png)

Olá pessoas, vamos dar continuidade em nossa série onde desvendando todos os hooks padrões do nosso querido React.js.

Caso queriam ver os outros artigos sobre essa série, segue links de artigos anteriores:

- [Série React Hooks: useImperativeHandle](https://dev.to/taisesoares/serie-react-hooks-useimperativehandle-44d)
- [Série React Hooks: useDeferredValue](https://dev.to/taisesoares/serie-react-hooks-usedeferredvalue-13d)
- [Série React Hooks: useMemo](https://dev.to/taisesoares/serie-react-hooks-usememo-5pc)
- [Série React Hooks: useCallback](https://dev.to/taisesoares/serie-react-hooks-usecallback-49ap)
- [Série React Hooks: useRef](https://dev.to/taisesoares/serie-react-hooks-useref-2mjl)

Hoje vamos falar sobre um hook bem interessante do ReactJS chamado `useSyncExternalStore`. Vamos entender como ele funciona, como utilizá-lo com exemplos em TypeScript e quais são os benefícios e ganhos em utilizá-lo. Bora lá?

## O que é o `useSyncExternalStore`? 

O `useSyncExternalStore` é um hook do ReactJS que permite sincronizar o estado de um componente com uma fonte de dados externa. Ele é especialmente útil quando você precisa compartilhar o estado entre vários componentes sem usar um gerenciador de estado global, como o Redux por exemplo, como o armazenamento local (local storage) ou uma API de armazenamento em nuvem. Com esse superpoder, você pode compartilhar o estado em tempo real entre diferentes partes da sua aplicação e até mesmo entre dispositivos distintos. Imagine só, atualizações instantâneas em tempo real em qualquer lugar!

Agora você deve estar se perguntando: Mas como esse hook mágico funciona? É simples! Basta chamar o useSyncExternalStore e passar a chave de identificação do estado e a fonte externa que deseja utilizar.

## Como utilizar o `useSyncExternalStore`?

Vamos para um exemplo, externo e interno ao mesmo tempo, vamos começar criando uma função que será nossa fonte de dados externa. Essa função será responsável por armazenar e atualizar o estado. No nosso exemplo, vamos criar uma função que armazena um contador.

```typescript
typescript
type State = { count: number };

const initialState: State = { count: 0 };

let state = initialState;
let listeners: Set<() => void> = new Set();

function getState(): State {
  return state;
}

function setState(newState: State): void {
  state = newState;
  listeners.forEach((listener) => listener());
}

function subscribe(listener: () => void): () => void {
  listeners.add(listener);
  return () => {
    listeners.delete(listener);
  };
}
```

Agora que temos nossa fonte de dados externa, podemos criar o hook `useSyncExternalStore`. Vamos importar o hook do pacote `react` e criar uma função que utiliza o `useSyncExternalStore` para sincronizar o estado do componente com nossa fonte de dados externa.

```typescript
import { useSyncExternalStore } from 'react';

function useCounter(): State {
  return useSyncExternalStore(getState, subscribe);
}
```

E isso é tudo, está pronto! Agora podemos utilizar o hook useCounter em nossos componentes para sincronizar o estado do contador.

```typescript
import React from 'react';

const Counter: React.FC = () => {
  const { count } = useCounter();

  return (
    <div>
      <p>Contador: {count}</p>
      <button onClick={() => setState({ count: count + 1 })}>Incrementar</button>
    </div>
  );
};

export default Counter;
```

Legal não é mesmo, mas vamos para um outro exemplo utilizando localStorage agora para tentar ficar mais simples:

```typescript
import { useSyncExternalStore } from 'react';

function App() {
  const [count, setCount] = useSyncExternalStore('count', localStorage);

  return (
    <div>
      <p>Contagem: {count}</p>
      <button onClick={() => setCount(count + 1)}>Incrementar</button>
    </div>
  );
}
```

Neste exemplo, estamos utilizando o armazenamento local (`localStorage`) como a fonte externa. O estado `'count'` será sincronizado com o valor armazenado no localStorage e qualquer alteração feita no estado será automaticamente refletida no localStorage e vice-versa. Incrível, não é?

A mágica não para por aí. O hook `useSyncExternalStore` também permite que você compartilhe o estado entre diferentes abas ou janelas do navegador. Isso significa que se você tiver a mesma aplicação aberta em duas abas diferentes, qualquer alteração feita em uma aba será instantaneamente refletida na outra aba. Isso abre um mundo de possibilidades para colaboração em tempo real e sincronização de dados entre usuários. Bora de outro exemplo:

```typescript
import { useSyncExternalStore } from 'react';

function App() {
  const [count, setCount] = useSyncExternalStore('count', localStorage, 0);

  return (
    <div>
      <p>Contagem: {count}</p>
      <button onClick={() => setCount(count + 1)}>Incrementar</button>
    </div>
  );
}
```

No exemplo acima, estamos passando `0` como valor inicial para o estado `'count'`. Isso significa que, caso não haja um valor previamente armazenado no localStorage, o estado será iniciado com o valor padrão de `0`. Isso garante que sua aplicação funcione sem problemas mesmo quando o estado inicial não está disponível.

## Benefícios e ganhos em utilizar o `useSyncExternalStore`

Agora que vimos como utilizar o `useSyncExternalStore`, vamos falar sobre os benefícios e ganhos em utilizá-lo.

1. **Sincronização de estado entre componentes**: O `useSyncExternalStore` permite que você compartilhe o estado entre vários componentes sem a necessidade de um gerenciador de estado global, como o Redux. Isso pode simplificar seu código e torná-lo mais fácil de entender e manter.

2. **Performance**: O `useSyncExternalStore` é otimizado para evitar renderizações desnecessárias. Ele só atualiza os componentes que realmente precisam ser atualizados, melhorando a performance da sua aplicação.

3. **Flexibilidade**: O `useSyncExternalStore` pode ser utilizado com qualquer fonte de dados externa, não apenas com o estado do React. Isso significa que você pode utilizá-lo para sincronizar o estado do componente com outras bibliotecas, APIs ou até mesmo com o LocalStorage.

4. **Escalabilidade**: Como o `useSyncExternalStore` é um hook nativo do React, ele é compatível com todas as funcionalidades e otimizações do React, como o Concurrent Mode e o React Server Components. Isso garante que sua aplicação continuará escalável e performática à medida que o React evolui.

## Resumindo

Os benefícios e ganhos ao utilizar o hook `useSyncExternalStore` são inúmeros. Com ele, você pode facilmente compartilhar e sincronizar o estado da sua aplicação em tempo real entre diferentes partes do seu código, diferentes abas ou até mesmo diferentes dispositivos. Isso proporciona uma experiência do usuário mais rica e colaborativa.

Além disso, o `useSyncExternalStore` simplifica a recuperação e persistência do estado, garantindo que os dados não sejam perdidos mesmo em situações como atualização da página ou novos acessos à aplicação.

Portanto, se você está em busca de superpoderes para o gerenciamento de estado no ReactJS, não deixe de experimentar o hook `useSyncExternalStore`. Ele vai revolucionar a forma como você compartilha, sincroniza e persiste o estado da sua aplicação. Aproveite e conquiste o mundo React com esse hook poderoso!