React Native na Web: saiba como usar a estratégia

Neste artigo você vai ver:

Antes de se aventurar com React Native rodando na web, é essencial que você conheça alguns conceitos e estratégias de compartilhamento de código entre React e React Native

Afinal, a biblioteca react-native-web é só isso. Uma estratégia que tem como finalidade compartilhar o máximo possível da sua aplicação web para mobile.

Rodar React Native na web não é novo, inclusive alguns grandes aplicativos já utilizam, como Skype e Twitter. Apesar do react-native-web ser mantido pela comunidade e não oficialmente pelo Facebook, essa é uma tecnologia estável o suficiente para você usar neste instante, diferentemente do Flutter Web que está em beta há mais de um ano.

Estratégias de compartilhamento de código

Existem duas formas básicas de compartilhamento de código entre React e React Native, são elas: o “alias” e o “container”

Importante: os dois termos foram criados por mim para me referir às estratégias. A ideia de componente primitivo (primitive component) é a mesma do “alias”. Achei melhor usar essa nomenclatura para facilitar o entendimento e exemplificar, do que propriamente explicar componentes primitivos.

Alias

Um “alias” seria um apelido, um atalho, uma espécie de “de para”.

O React Native não roda na web, ele foi feito para rodar em dispositivos móveis. Quando falamos de React Native Web, na verdade, estamos falando de uma biblioteca que substituirá o “react-native” pelo “react-native-web” durante o build, para que seja possível “simular” o comportamento do React Native no navegador web.

Se você sabe webpack, é muito simples configurar uma aplicação React Native para rodar na web, basta adicionar as configurações do seu webpack um “alias” desta maneira:

react native

Simples assim!

O webpack substituirá tudo que é react-native por react-native-web antes de “buildar”. O build do webpack não influencia o build do react-native que serve tanto para iOS, quanto para Android. 

Vale lembrar que se for seguir essa estratégia de usar react-native-cli com webpack, você deve também configurar o webpack para rodar React, CSS, imagens, etc. 

Seria uma configuração normal do webpack para React. Em outras palavras, você pode criar um projeto novo de React Native normalmente e depois criar seu webpack dentro desse projeto do React Native.

Caso você não tenha familiaridade com o webpack, uma ótima alternativa é usar o Expo. 

Atualmente, o Expo já vem com o react-native-we configurado por padrão. Em outras palavras, o Expo já fez essa configuração do webpack para você, se olhar os scripts dentro do package.json verá que existe um para rodar na web.

Container

Uma forma muito conhecida no mundo React é a ideia de componente container e componente de apresentação (presentation). 

Essa estratégia de compartilhamento não está ligada ao react-native-web ou qualquer outro alias, mas, sim, a um recurso muito útil, conhecido por poucos do react-native, que é a identificação de arquivos por determinada plataforma se baseando na extensão. 

Quer dizer, se você tem um diretório Button, dentro dele você pode ter um index.js para cada plataforma: um index.android.js para Android; index.ios.js para iOS; index.web.js para web; index.native.js para Android e iOS; e, index.js que é o padrão de todas as plataformas.

Com isso, você poderia ter um componente container “genérico”, ele não seria nem react-native, nem React Web, seria apenas React, pois apenas as importações que estariam nesse container seriam diferentes para cada plataforma, já o container seria único.

Para exemplificar, vamos continuar falando do exemplo do Button.

Este seria o button para web:

button

E este para React Native:

button react

Ambos estão na mesma pasta, o que muda é só a extensão. Na hora de importar basta usar “importa Button from ‘../Components/Button’”. Esta importação vale para qualquer plataforma, basta importar uma vez.

Aqui seria esse botão aplicado em um componente container:

Todos os componentes usados neste formulário são componentes de apresentação com dois indexes, um para nativo (Component.native.js) e outro para web (Component.js).

Alias ou Container, qual usar?

Um simula o comportamento do nativo para a web, já o outro cria um index para cada plataforma. 

Portanto, é difícil dizer qual é melhor, já que são estratégias diferentes para compartilhar código entre React e react-native, porém é importante entendermos os pontos fortes e fracos de cada estratégia. 

E, claro, nada impede de usarmos as duas no mesmo projeto se for necessário.

O alias é mais rápido de desenvolver. Basicamente, você vai escrever uma vez e vai rodar para tudo: Android, iOS e web. Porém, da mesma forma que existem diferenças entre Android e iOS, essas diferenças são muito maiores quando colocamos a web no meio. 

Lembre-se: a ideia do react-native-web é simular o comportamento do nativo na web, então não são todos os recursos que vão funcionar ali, essas limitações devem ficar no seu radar. Também é importante que a leitura da documentação do react-native-web seja obrigatória para entender quais são essas limitações.

O container segue a ideia de compartilhar a store (redux), as chamadas de API e os containers com as lógicas. Compartilhar isso já é o suficiente para muita gente, mantendo as coisas separadas, você consegue ter uma clareza maior sobre o que é de cada ambiente.

Navegação/Rotas

Está aí um ponto que o nativo e o web são totalmente diferentes, não é possível compartilhar esse recurso entre as plataformas. 

No react-navigation, a navegação é baseada em stacks, cada um tem um fluxo específico. Fluxo no qual está associado ao botão voltar, já na web não temos isso, temos apenas o histórico geral de onde você estava (react-router-dom). 

Uma opção seria usar react-router-native, mas até nele seria necessário configurações adicionais para conseguir rodar nas duas plataformas. O controle da navegação deve ser configurado à parte para react-native e web. 

De qualquer maneira, ainda não há uma forma fácil de compartilhar essa configuração de navegação entre diferentes plataformas.

Responsivo

O React Native não usa CSS, logo não usa mediaqueries. Com isso o controle do responsivo fica a cargo do JavaScript controlar os breakpoints da tela. 

Basicamente, você pode usar alguma lib para isso, ou criar um listener no módulo Dimensions do react-native e colocar a altura e largura dentro do redux para que seja acessível a todos os componentes. Caso o valor mude, os componentes serão renderizados, exibindo-os ou não, ou mudando sua aparência ou não, baseando-se na largura e altura armazenadas na store.

Plug-ins

Plug-ins são um universo à parte, pois geralmente cada lib é pensada para apenas uma das duas plataformas, web ou native. 

E, como vimos antes, o react-native por si só não é capaz de rodar na web, sendo necessário um alias com o react-native-web para tal. 

Essa ideia também vale para plug-ins. Assim como você não pode pegar uma lib que roda no Android e esperar que ela rode na web, você não pode pegar um lib conhecido na web e esperar que rode no Android, mas há como contornar isso.

Alias de libs

Está se tornando comum bibliotecas com suporte para native e web, porém não ao mesmo tempo, não com a mesma fonte, mas com a mesma lib. 

Um bom exemplo é o “react-content-loader”, que é para web, se você importar como “react-content-loader/native” o uso é para native. 

Como usar isso então? 

Simples, é só usar a ideia de container, cria-se um diretório “./lib/react-content-loader” e dentro dois arquivos: um index.js e outro index.native.js, você vai importar e exportar em seguida a lib dentro desses arquivos.

Alias do react-native-web dentro do fonte da lib

Vamos pegar a lib “react-native-calendars” como exemplo. Como o próprio nome diz é uma lib para react-native, porém queremos que ela rode na web. Como podemos fazer isso? 

Nós podemos fazer o webpack ler tudo o que está dentro do diretório dessa lib, para que então seja possível que o alias que temos no react-native para react-native-web também seja executado dentro do react-native-calendars. 

Em outras palavras, por padrão, o nosso alias do react-native-web só funciona no nosso projeto, não roda nas dependências (libs de terceiros). Para isso, existe um esforço adicional para fazer esse processo acontecer, e essa configuração varia se você está usando Expo ou webpack. 

Como testar isso facilmente sem configuração adicional? 

Baixe o código fonte da lib que você quer e coloque a pasta dentro do seu projeto. Com isso, o webpack lerá o código por padrão, sendo possível fazer o alias do react-native-web. 

Lembre-se: essa forma, mesmo sendo mais prática, não é recomendada, uma vez que você perde o versionamento dessa lib. 

Resumindo, você deve configurar o loader no seu webpack a incluir (include) a lib que deseja “buildar” junto com o seu projeto para que o alias do react-native-web também funcione nela. 

Container

Você também pode usar a ideia de container com libs diferentes.  

Imagine que você quer usar uma lib conhecida da web e outra lib diferente, que também é conhecida no react-native, ambas são feitas por pessoas diferentes, porém resolvem a mesma dor. 

Você pode criar um diretório /lib/UmaLibIncrivel com dois arquivos, um index.js para web e um index.native.js para native. Entretanto você deve ter o cuidado de criar uma “interface” para unificar tudo, se você trabalhar com Typescript vai entender de cara o problema. 

Cada lib tem suas próprias opções e recursos, mesmo duas libs parecidas ainda terão muitas diferenças de implantação. Para poder ter uma lib web e outra lib native rodando em paralelo, você precisa criar um wrapper dentro desses arquivos indexes para que a interface (métodos, props) seja a mesma tanto para web quanto para native.

API Universal

E, finalmente, a melhor solução (que infelizmente é a menos usada por quem cria de libs): uma API única, uma lib única que pode ser importada tanto para web quanto para native. Exemplo: expo-camera.

Conclusão

Se parece confuso para você essa mistura de arquivos com alias e containers, pense assim: web e native são plataformas totalmente diferentes, com comportamentos diferentes. 

O react-native-web já resolve muitos destes problemas para nós. Porém, ainda não é possível escrever um só código e esperar que ele rode em tudo por padrão, mas existe muita gente correndo atrás disso. 

Para se trabalhar com código React e react-native é necessário ter um conhecimento que vai além do básico, tanto de web (dom) quanto de react-native para que essa mistura de conceitos faça mais sentido. Muitas coisas que existem em uma plataforma não existem em outra, neste caso, cabe a você adaptar isso, não existe um guia de boas práticas, temos que usar o bom senso.

Talvez para um iniciante em React isso seja demais, muitos conceitos a serem levados em consideração ao mesmo tempo, talvez uma clássica webview resolva seu problema.

Mas se você é mais experiente e sua empresa quer ter um produto web e mobile, eu não vejo opção melhor no mercado para se ter um aplicativo multiplataforma do que usar React e React Native juntos.

Com isso você consegue ter uma aplicação rodando em pelo menos três plataformas (daria pra ter em mais, como Windows e Mac com react-native-windows, mas requer mais configurações) com apenas um time.

Por mais que a princípio pareça complicado, ainda é muito mais simples do que criar três apps em três plataformas nativamente, o que ao meu entender é desnecessário.

Quer complementar seu estudo sobre o tema? Então assista o webinar que fizemos sobre React Native:

Qual sua opinião sobre o assunto? Escreva nos comentários suas dúvidas, sugestões e questionamentos para continuarmos o papo. 

Rodrigo Mello
Tech Lead
Entusiasta de interfaces digitais

Artigos relacionados

Este site utiliza cookies para proporcionar uma experiência de navegação melhor. Consulte nossa Política de Privacidade.