Como migramos do Redux para TanStack Query e Redux Toolkit

Dec 03 2022
Na Storyly, temos dois projetos React muito diferentes; um é "painel" e o outro é "estúdio". Esses dois projetos diferem em propósito, bem como em desafios técnicos.

No Storyly , temos dois projetos React muito diferentes; um é "painel" e o outro é "estúdio".

Esses dois projetos diferem em propósito, bem como em desafios técnicos. O painel é um projeto CMS onde nossos usuários gerenciam seus aplicativos, instâncias, grupos de histórias, configurações e integrações e veem suas análises. O projeto Studio, por outro lado, é uma ferramenta de design; permite que nossos usuários criem suas histórias em uma tela vazia usando nossos elementos predefinidos.

Uma captura de tela do nosso painel
Uma captura de tela do nosso estúdio

Em um nível técnico, como você também deve imaginar, o painel contém dados pesados ​​do lado do servidor e o estúdio é principalmente dados do lado do cliente. Então, ao categorizar, estou me concentrando nos propósitos dos projetos e não apenas nos aspectos técnicos.

Nós, como desenvolvedores front-end, não devemos tomar decisões técnicas puramente nos aspectos técnicos. Existem muitos outros aspectos a serem considerados, incluindo a equipe, usuários atuais e possíveis, o futuro pretendido do projeto e a cultura da empresa. Tudo isso terá um impacto em suas soluções técnicas fundamentalmente durante o processo de tomada de decisão.

Digamos que sua tarefa seja escolher uma solução de gerenciamento de estado para seu projeto. Existem MUITOS deles por aí, com diferentes prós e contras. É seguro dizer que o tópico de gerenciamento de estado no ecossistema front-end vem com o maior número de soluções próximo ao tópico “frameworks”.

Se você considerar apenas os prós e contras técnicos, os números de desempenho, a facilidade de uso da solução e talvez o número de commits, estrelas e problemas da solução será o que você está verificando. E todos esses são pontos válidos ao escolher uma biblioteca.

Quando vejo as soluções de gerenciamento de estado para usar em ambas as bases de código do ponto de vista técnico, estou inclinado a usar Zustand ou Jotai. Eles são bem conservados, incrivelmente fáceis de usar e têm bom desempenho. Foi uma decisão fácil, certo?

Bem, estávamos usando o poderoso Redux em ambas as nossas bases de código para gerenciar seu estado, e eu precisava simplificar essa parte do projeto porque ela ficou mais extensa do que precisava. Foi a fonte primária de muitos dos nossos bugs. Imediatamente pensei “Ótimo, devemos usar o Zustand para ambos os projetos porque é incrível!” mas então dei um passo para trás e refleti um pouco mais sobre isso.

Processo de Migração

Como expliquei no início, nossas duas bases de código são muito diferentes.

O painel mostra os dados do lado do servidor para o usuário com alterações muito sutis e upserts nos dados do lado do servidor. Existem muitas páginas com dados analíticos, listas e estatísticas computadas. O futuro deste projeto também será semelhante; um painel tipo CMS com muitas estatísticas e listas. Então eu precisava considerar o cache dos dados, invalidação do cache, cascatas de rede, atualizações de dados em tempo real, atualizações otimistas, etc. Com esses tópicos em mente, decidi que não precisávamos mudar nossa solução de gerenciamento de estado (Redux ); simplesmente precisávamos removê-lo do painel porque não precisamos “gerenciar” nenhum estado.

Em seguida, examinei as soluções de busca de dados, como SWR , TanStack Query e RTK Query .

O SWR não tem um fluxo de mutação estável e o RTK Query também está acoplado ao Redux Toolkit. Então, segui em frente com o TanStack Query.

O TanStack Query remove a sobrecarga de gerenciamento de dados do lado do servidor com seus fluxos de cache, invalidação e mutação. Sempre há um estado a ser gerenciado, mas nem sempre você precisa gerenciá-lo sozinho. Demos esse trabalho pesado ao TanStack Query e não olhamos para trás. Estamos usando Redux e TanStack Query em paralelo e movendo o estado Redux peça por peça para a consulta TanStack até que não haja mais nada no estado Redux e possamos com segurança yarn remove.

Uma versão simplificada de nosso arquivo App.js para nosso painel usando o TanStack Query Provider e o Redux Provider.

React Hooks nos permite usá-los em paralelo e mover a lógica entre eles de forma incremental:

Exemplo de uma página usando o estado Redux e a consulta TanStack

No estúdio, no entanto, há muitos dados puramente do lado do cliente gerados para serem enviados ao servidor. Você pode projetar completamente uma história com elementos predefinidos; você pode movê-los na tela, redimensioná-los, alterar seu conteúdo de acordo com suas necessidades, alterar a imagem de fundo da história ou até mesmo colocar um vídeo em segundo plano. E as possibilidades são infinitas antes de você enviar os dados finais ao servidor para salvá-los. Todos esses recursos são dados do lado do cliente até que você os salve. E depois de salvá-los e voltar a editá-los, eles são novamente dados do lado do cliente derivados dos dados do lado do servidor.

Também precisamos pensar nos recursos possíveis - a capacidade de desfazer alterações, criar desenhos à mão livre, projetar transições entre histórias... As possibilidades são infinitas, mas todos os recursos possíveis são dados pesados ​​do lado do cliente. Portanto, precisamos “gerenciar” nosso estado aqui para obter o máximo de flexibilidade.

Para o Studio, já usávamos uma solução de gerenciamento de estado, o Redux. Então, perguntei aos meus colegas de equipe: “O que devemos usar para consertar nosso gerenciamento de estado?”

Depois de todas as respostas, o caminho ficou claro: usaremos o Redux Toolkit .

RTK (Redux Toolkit) é um conjunto de ferramentas da equipe Redux para melhorar a qualidade de vida dos desenvolvedores. Simplifica a configuração da loja e a gestão de múltiplas lojas através de slices . Então, migramos nosso antigo estado Redux para a nova arquitetura RTK. Estamos executando a arquitetura antiga e a nova lado a lado e movendo partes dos estados para a nova arquitetura enquanto a refatoramos. Tudo isso nos permite mover de forma rápida e incremental sem bloquear o fluxo de trabalho do produto.

Estamos executando essa arquitetura antiga e nova em paralelo, passando um React Context personalizado para os provedores Redux :

Uma versão simplificada do nosso arquivo Studio.js usando dois provedores Redux diferentes com contextos diferentes

Lembre-se de que, ao passar um contexto personalizado para o Provedor Redux, você precisa criar todos os ganchos Redux relacionados com os geradores fornecidos e usá-los em seu código, em vez de importar diretamente do pacote react-redux:

Exemplo de geração de ganchos Redux com contexto personalizado

Nosso objetivo de longo prazo é remover completamente o Redux do projeto Dashboard e remover o “velho” Redux do projeto Studio. Estamos avançando em direção a esse objetivo, refatorando cada arquivo que precisamos tocar enquanto desenvolvemos novos recursos e corrigimos bugs.

Essas transições técnicas significativas devem ser suaves e incrementais principalmente por dois motivos: primeiro, você está reformulando a rotina de trabalho diária de sua equipe. Eles devem ficar felizes em trabalhar com essas mudanças, ou seu desempenho diminuirá substancialmente. Por outro lado, se eles amam as ferramentas que usam para construir e essas ferramentas os ajudam em vez de bloqueá-los, seu desempenho aumentará substancialmente. E segundo, o produto deve continuar a ser construído . O show tem que continuar. Deve haver novos recursos. Precisa estar avançando. Portanto, as transições técnicas não devem bloquear o desenvolvimento do produto. Toda mudança deve ser incremental.

Resumo

Ao tomar decisões técnicas como desenvolvedores, devemos considerar todos os aspectos do projeto em que estamos trabalhando e as necessidades da equipe com a qual estamos trabalhando. Isso ocorre simplesmente porque essas decisões técnicas afetam a equipe e todos os outros que trabalham no projeto, não apenas os desenvolvedores.

As mudanças técnicas devem ser incrementais a todo custo. Essas mudanças não devem bloquear o pipeline do produto e, portanto, seu sucesso.

E lembre-se sempre, para que um desenvolvedor seja produtivo, você precisa fornecer a ele as ferramentas que o deixam feliz.