<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ React Native - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Aprenda a codificar - de graça. Tutoriais de programação em Python, JavaScript, Linux e muito mais. ]]>
        </description>
        <link>https://www.freecodecamp.org/portuguese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ React Native - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/portuguese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 30 May 2026 13:56:29 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/portuguese/news/tag/react-native/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Como integrar mapas no React Native usando react-native-maps ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Mukhamed Khasanza Hoje em dia, quase todas as aplicações para dispositivos móveis têm um recurso de mapas. Eu tive que integrar o Google Maps à minha aplicação para o React Native, e a única opção era o react-native-maps da Airbnb (é o único ainda suportado pela comunidade do ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-integrar-mapas-no-react-native-usando-react-native-maps/</link>
                <guid isPermaLink="false">6671c1bd79dc5c03cfad4203</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sabrina ]]>
                </dc:creator>
                <pubDate>Mon, 24 Jun 2024 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/1_qp8QiCRmx0D041XU4qhx4g.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/how-to-integrate-maps-in-react-native-using-react-native-maps-5745490fe055/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to integrate maps in React Native using react-native-maps</a>
      </p><p>Escrito por: Mukhamed Khasanza</p><p>Hoje em dia, quase todas as aplicações para dispositivos móveis têm um recurso de mapas. Eu tive que integrar o Google Maps à minha aplicação para o React Native, e a única opção era o react-native-maps da Airbnb (é o único ainda suportado pela comunidade do React Native).</p><p>Encontrei vários tutoriais sobre como configurar essa biblioteca, mas nenhum funcionou totalmente para mim. Isso porque eu tinha que rodar em plataformas iOS e Android, além de dar suporte ao Google Maps para iOS.</p><p>Vamos criar uma aplicação do React Native do zero usando react-native-cli para mostrar, passo a passo, como tudo é instalado. Se você quiser integrar o react-native-maps à sua aplicação existente, pule a <strong>Etapa<strong> 1</strong></strong>.</p><h4 id="etapa-1-instalar-e-configurar-a-aplica-o-do-react-native"><strong>Etapa<strong> 1: </strong>i<strong>nstal</strong>ar e configurar a aplicação do<strong> React Native</strong></strong></h4><p>Se você não instalou a interface de linha de comando do React Native, execute: <code>npm install -g react-native-cli</code>. Agora, você pode criar seu projeto, simplesmente usando: <code>react-native init ReactNativeMaps</code></p><p>Aqui estão as versões de dependência no momento da construção deste projeto:</p><ul><li>"react": "16.6.1"</li><li>"react-native": "0.57.5"</li><li>"react-native-maps": "0.22.1" — instalaremos este mais tarde.</li></ul><blockquote>Nota da tradução: mantivemos as versões constantes no artigo original, mas, na data da tradução, as versões são 18.2.0 e 1.15.6, respectivamente.</blockquote><p>Tente executar sua aplicação, <code>react-native run-ios</code> ou <code>react-native run-android</code>. Normalmente, isso funciona sem problemas.</p><h4 id="etapa-2-adicionar-e-vincular-o-pacote-react-native-maps"><strong>Etapa<strong> 2: </strong>a<strong>d</strong>icionar e vincular o pacote<strong> react-native-maps</strong></strong></h4><p>Agora, vamos instalar o react-native-maps: <code>npm install --save react-native-maps</code>. Depois de instalar o pacote, você deve vinculá-lo às suas aplicações nativas: <code>react-native link react-native-maps</code>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/UIyvyNDxVXBMQeYn9Wno72ob5T8iqR7Cr1c3.png" class="kg-image" alt="UIyvyNDxVXBMQeYn9Wno72ob5T8iqR7Cr1c3" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/UIyvyNDxVXBMQeYn9Wno72ob5T8iqR7Cr1c3.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/UIyvyNDxVXBMQeYn9Wno72ob5T8iqR7Cr1c3.png 800w" sizes="(min-width: 720px) 720px" width="800" height="84" loading="lazy"><figcaption>Se você recebeu uma tela semelhante a essa, podemos continuar.</figcaption></figure><h4 id="etapa-3-configurar-o-apple-maps-ios-"><strong>Etapa<strong> 3: </strong>configurar o<strong> Apple Maps (iOS)</strong></strong></h4><p>Será mais fácil se os configurarmos separadamente por plataforma. Então, vamos primeiro fazer isso no iOS. Antes de integrar o Google Maps, verificaremos se o Apple Maps funciona corretamente. Adicione o seguinte código ao seu componente de renderização atual, onde você deseja renderizar seu MapView.</p><pre><code>import MapView from 'react-native-maps'</code></pre><pre><code>export default class App extends Component&lt;Props&gt; {
  render() {
    return (&lt;MapView style={{flex: 1}} region={{ latitude: 42.882004, longitude: 74.582748, latitudeDelta: 0.0922, longitudeDelta: 0.0421 }} showsUserLocation={true} /&gt;);
  }
}</code></pre><p>Você pode testar qualquer local que quiser. Basta especificar a latitude e a longitude apropriadas. Como você pode ver, eu habilitei a localização do usuário simplesmente adicionando a prop <code>showUserLocation</code> ao componente MapView. Se você estiver executando no dispositivo real, verá sua localização atual.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/qtVkxY6KL4FhpwLUbEbBeqN8o6o7poi1ewRF.png" class="kg-image" alt="qtVkxY6KL4FhpwLUbEbBeqN8o6o7poi1ewRF" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/qtVkxY6KL4FhpwLUbEbBeqN8o6o7poi1ewRF.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/qtVkxY6KL4FhpwLUbEbBeqN8o6o7poi1ewRF.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Então, como você pode ver, por padrão, o Apple Maps já está funcionando. Mais do que isso, se você vinculou tudo corretamente e habilitou a localização do usuário, ele realmente fez muitas coisas para nós (a permissão do usuário para a localização com uma mensagem padrão). Se você veio do desenvolvimento nativo do iOS, então, provavelmente, sabe o que é um arquivo info.plist.</p><h4 id="etapa-4-instalar-o-cocoapods-e-o-pacote-googlemaps-ios-"><strong>Etapa<strong> 4: </strong>i<strong>nstal</strong>ar o<strong> Cocoapods </strong>e o pacote<strong> </strong>"<strong>GoogleMaps</strong>"<strong> (iOS)</strong></strong></h4><p>O Apple Maps foi fácil, certo? Concordo — então, vamos ver o que o Google Maps tem para nós. Temos que instalar o Google Maps SDK para iOS. Usaremos o Cocoapods. Se você não o usou antes, execute <code>sudo gem install cocoapods</code>.</p><p>Agora, você tem que criar um Podfile, onde você especificará as dependências da sua aplicação para o &nbsp;iOS. Navegue até sua pasta iOS/ na sua aplicação do React Native e execute: <code>pod init</code> ou você pode usar &nbsp;<code>touch Podfile</code>. Você deve ter algo similar a isto:</p><pre><code># platform :ios, '9.0'</code></pre><pre><code>target 'ReactNativeMaps' do</code></pre><pre><code># Pods for ReactNativeMaps</code></pre><pre><code>pod 'GoogleMaps'</code></pre><pre><code>end</code></pre><p>Como você pode ver, adicionei o pod GoogleMaps e agora temos que instalá-lo. Se você ainda estiver na pasta iOS/, execute: <code>pod install</code> . Se você tentar executá-lo agora, provavelmente receberá um erro:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/soaOtijGp-7CiGQVsNiwgljfHyLEQvrDJvEg.png" class="kg-image" alt="soaOtijGp-7CiGQVsNiwgljfHyLEQvrDJvEg" width="600" height="400" loading="lazy"></figure><p>Ok, vamos fazer o que ele quer. Agora, devemos abrir o espaço de trabalho do xCode.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/Vr6q4qYXaiFqnHdGtSNnhKSIZFqCMCFVeVEI.png" class="kg-image" alt="Vr6q4qYXaiFqnHdGtSNnhKSIZFqCMCFVeVEI" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/Vr6q4qYXaiFqnHdGtSNnhKSIZFqCMCFVeVEI.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/Vr6q4qYXaiFqnHdGtSNnhKSIZFqCMCFVeVEI.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Navegue até a pasta AirGoogleMaps em node_modules/</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/Taoc1pnk-dNBMzyAmjjE3CO8AkOm8t9KQhXf.png" class="kg-image" alt="Taoc1pnk-dNBMzyAmjjE3CO8AkOm8t9KQhXf" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/Taoc1pnk-dNBMzyAmjjE3CO8AkOm8t9KQhXf.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/Taoc1pnk-dNBMzyAmjjE3CO8AkOm8t9KQhXf.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Arraste-a para o topo do seu projeto do xCode</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/ewvVl0gCwzwrNj1gd3itRZnWJVPGOCiKkdSo.png" class="kg-image" alt="ewvVl0gCwzwrNj1gd3itRZnWJVPGOCiKkdSo" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/ewvVl0gCwzwrNj1gd3itRZnWJVPGOCiKkdSo.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/ewvVl0gCwzwrNj1gd3itRZnWJVPGOCiKkdSo.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Tente construir seu projeto do xCode, se estiver falhando.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/6aQVp2Zl6gKnE6d3DdqMULm2WHmp70ws6QBE.png" class="kg-image" alt="6aQVp2Zl6gKnE6d3DdqMULm2WHmp70ws6QBE" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/6aQVp2Zl6gKnE6d3DdqMULm2WHmp70ws6QBE.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/6aQVp2Zl6gKnE6d3DdqMULm2WHmp70ws6QBE.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Você deve adicionar <code>HAVE_GOOGLE_MAPS=1</code> Preprocessor Macro para Build Settings</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/IhgPZQBomXmc4UKlP4ynYNIoU3Y0hlyGivGc.png" class="kg-image" alt="IhgPZQBomXmc4UKlP4ynYNIoU3Y0hlyGivGc" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/IhgPZQBomXmc4UKlP4ynYNIoU3Y0hlyGivGc.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/IhgPZQBomXmc4UKlP4ynYNIoU3Y0hlyGivGc.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><h4 id="etapa-5-obter-a-chave-da-api-do-google-maps-e-executar-a-aplica-o-do-ios-com-o-google-maps"><strong>Etapa<strong> 5: </strong>obter a chave da api do<strong> Google Maps</strong> e executar a aplicação do<strong> iOS </strong>com o<strong> Google Maps</strong></strong></h4><p>Agora, temos que gerar uma <a href="https://developers.google.com/maps/documentation/ios-sdk/get-api-key" rel="noopener"><strong><strong>Goo</strong>g<strong>le Maps API key</strong></strong></a><strong><strong>.</strong></strong></p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/dnmuyvL7Nd99BHxkK2F4iUCBbBeoypyPVfyw.png" class="kg-image" alt="dnmuyvL7Nd99BHxkK2F4iUCBbBeoypyPVfyw" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/dnmuyvL7Nd99BHxkK2F4iUCBbBeoypyPVfyw.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/dnmuyvL7Nd99BHxkK2F4iUCBbBeoypyPVfyw.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Copie sua chave de API e adicione-a ao arquivo AppDelegate.m.</p><p><code>#import &lt;GoogleMaps/GoogleMaps.h&gt;</code></p><p><code>[GMSServices provideAPIKey:@"SUA_CHAVE_DE_API"]</code></p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/oHeCkflMd3zznfYFMPBD6tglu4n9tfnoCghs.png" class="kg-image" alt="oHeCkflMd3zznfYFMPBD6tglu4n9tfnoCghs" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/oHeCkflMd3zznfYFMPBD6tglu4n9tfnoCghs.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/oHeCkflMd3zznfYFMPBD6tglu4n9tfnoCghs.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Informe ao seu componente MapView que está pronto para usar o Google Maps.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/EojYRgWTNtO0zlMmicx0EVmv-0dBi22Y3Euf.png" class="kg-image" alt="EojYRgWTNtO0zlMmicx0EVmv-0dBi22Y3Euf" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/EojYRgWTNtO0zlMmicx0EVmv-0dBi22Y3Euf.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/EojYRgWTNtO0zlMmicx0EVmv-0dBi22Y3Euf.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Ah, sim. Não se esqueça de executar sua aplicação do iOS. Agora, você já terá o Google Maps à disposição.</p><p>Eu espero.</p><h4 id="etapa-6-vamos-tentar-no-android-agora"><strong>Etapa<strong> 6: </strong>vamos tentar no<strong> Android </strong>agora</strong></h4><p>Ok. Agora, podemos sair do xCode e vamos apenas tentar <code>react-native run-android</code>. Se você estiver recebendo o mesmo que isto:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2024/06/PZJ0vNEXuf1F-IUTAx0UAoJcW9rZy9V1FlbR.png" class="kg-image" alt="PZJ0vNEXuf1F-IUTAx0UAoJcW9rZy9V1FlbR" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2024/06/PZJ0vNEXuf1F-IUTAx0UAoJcW9rZy9V1FlbR.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2024/06/PZJ0vNEXuf1F-IUTAx0UAoJcW9rZy9V1FlbR.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>verifique seu arquivo <strong>android/app/build.gradle</strong> e substitua <code>compile project(':react-native-maps')</code> por isto:</p><pre><code>implementation(project(':react-native-maps')){        exclude group: 'com.google.android.gms', module: 'play-services-base'        exclude group: 'com.google.android.gms', module: 'play-services-maps'    }implementation 'com.google.android.gms:play-services-base:12.0.0'implementation 'com.google.android.gms:play-services-maps:12.0.0'</code></pre><p>Não se esqueça de adicionar a API_KEY ao arquivo AndroidManifest.xml.</p><pre><code>&lt;application&gt;
   &lt;meta-data android:name="com.google.android.geo.API_KEY"      android:value="SUA_CHAVE_DA_API"/&gt;
&lt;/application&gt;</code></pre><p>Sim, agora sua aplicação está rodando em ambas as plataformas. Verifique o repositório do <a href="https://github.com/react-community/react-native-maps/blob/master/README.md" rel="noopener"><strong><strong>react-native-maps</strong></strong></a> para mais coisas divertidas que você pode fazer com seu componente MapView.</p><h4 id="conclus-o"><strong><strong>Conclus</strong>ão</strong></h4><p>Espero que meu primeiro artigo tenha sido útil para você.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como estruturar seu projeto e gerenciar recursos estáticos no  React Native ]]>
                </title>
                <description>
                    <![CDATA[ Escrito por: Khoa Pham React e React Native são apenas frameworks, e não ditam como devemos estruturar nossos projetos. Tudo depende do seu gosto pessoal e do projeto em que você está trabalhando. Neste post, vamos abordar como estruturar um projeto e como gerenciar ativos locais. Isso, claro, não está ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-estruturar-seu-projeto-e-gerenciar-recursos-estaticos-no-react-native/</link>
                <guid isPermaLink="false">64ad32b5d4e9dc0571a410cc</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Rosa ]]>
                </dc:creator>
                <pubDate>Tue, 11 Jul 2023 18:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2023/07/0_i9u5ERjY-T2ZgjHX.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/how-to-structure-your-project-and-manage-static-resources-in-react-native-6f4cfc947d92/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to structure your project and manage static resources in React Native</a>
      </p><p>Escrito por: Khoa Pham</p><p>React e React Native são apenas frameworks, e não ditam como devemos estruturar nossos projetos. Tudo depende do seu gosto pessoal e do projeto em que você está trabalhando.</p><p>Neste post, vamos abordar como estruturar um projeto e como gerenciar ativos locais. Isso, claro, não está escrito em pedra, e você é livre para aplicar apenas as peças que lhe convierem. Espero que você aprenda alguma coisa.</p><p>Para um projeto inicializado com <code>react-native-init</code>, obtemos apenas a <a href="https://medium.com/fantageek/what-is-create-react-native-app-9f3bc5a6c2a3">estrutura básica</a> (texto em inglês).</p><p>Há a pasta <code>ios</code> para projetos do Xcode, a pasta <code>android</code> para projetos para o Android e arquivos <code>index.js</code> e <code>App.js</code> para o ponto de partida do React Native.</p><pre><code>ios/
android/
index.js
App.js</code></pre><p>Por já ter trabalhado com arquivos nativos no Windows Phone, no iOS e no Android, penso que estruturar um projeto se resume a separar arquivos por <strong>tipo</strong> ou por <strong>recurso</strong>.</p><h3 id="tipo-x-recurso"><strong>Tipo x recurso</strong></h3><p>Separar por tipo significa organizarmos os arquivos por seu tipo. Se o tipo for um componente, haverá arquivos de contêiner e arquivos de apresentação. Se for do Redux, haverá arquivos de ação, <em>reducers</em> e arquivos de armazenamento. Se for uma <em>view</em>, haverá arquivos JavaScript, HTML e CSS.</p><h4 id="agrupar-por-tipo"><strong>Agrupar por tipo</strong></h4><pre><code>redux
  actions
  store
  reducers
components
  container
  presentational
view
  javascript
  html
  css</code></pre><p>Desse modo, podemos ver o tipo de cada arquivo e executar facilmente um script para determinado tipo de arquivo. Isso vale para todos os projetos, mas não responde à pergunta "Qual é o objetivo deste projeto?" É uma aplicação de notícias? É uma aplicação de fidelização? É um acompanhamento nutricional?</p><p>Organizar arquivos por tipo é útil para máquinas, mas não para humanos. Muitas vezes, trabalhamos em recursos. Encontrar arquivos para corrigir em diversos diretórios é muito cansativo. Também é um incômodo quando planejamos fazer a estrutura de nosso projeto, já que os arquivos estão espalhados por muitos lugares.</p><h4 id="agrupar-por-recurso"><strong>Agrupar por recurso</strong></h4><p>Uma solução mais razoável é organizar arquivos por recurso. Os arquivos relacionados a um recurso devem ser colocados juntos. Os arquivos de teste devem ficar próximos aos arquivos de origem. Confira <a href="https://medium.com/@JeffLombardJr/organizing-tests-in-jest-17fc431ff850">este artigo</a> (texto em inglês) para saber mais.</p><p>Um recurso pode estar relacionado ao <em>login</em>, inscrição, integração ou ao perfil de um usuário. Um recurso pode conter sub-recursos, desde que pertençam ao mesmo fluxo. Se quiséssemos mover o sub-recurso, seria fácil, pois todos os arquivos relacionados já estariam agrupados.</p><p>Minha estrutura típica de projeto baseada em recursos tem a seguinte aparência:</p><pre><code>index.js
App.js
ios/
android/
src
  screens
    login
      LoginScreen.js
      LoginNavigator.js
    onboarding
      OnboardingNavigator    
      welcome 
        WelcomeScreen.js
      term
        TermScreen.js
      notification
        NotificationScreen.js
    main
      MainNavigator.js
      news
        NewsScreen.js
      profile
        ProfileScreen.js
      search
        SearchScreen.js
  library
    package.json
    components
      ImageButton.js
      RoundImage.js
    utils
      moveToBottom.js
      safeArea.js
    networking
      API.js
      Auth.js
  res
    package.json
    strings.js
    colors.js
    palette.js
    fonts.js
    images.js
    images
      logo@2x.png
      logo@3x.png
      button@2x.png
      button@3x.png
scripts
  images.js
  clear.js</code></pre><p>Além dos arquivos <code>App.js</code> e <code>index.js</code> e das pastas <code>ios1</code> e <code>android</code> tradicionais, coloquei todos os arquivos de origem na pasta <code>src</code>. Dentro de <code>src</code>, tenho <code>res</code>, para recursos (do inglês, <em>resources</em>), <code>library</code>, para arquivos comuns usados em mais de um recurso, e <code>screens</code>, para a tela de conteúdo.</p><h4 id="o-menor-n-mero-de-depend-ncias-poss-vel"><strong>O menor número de dependências possível</strong></h4><p>Como o React Native é fortemente dependente de uma infinidade de dependências, tento tomar muito cuidado ao adicionar mais dependências. No meu projeto, uso apenas <code>react-navigation</code> para navegação. Não sou um fã do <code>redux</code>. Acho que ele adiciona uma complexidade desnecessária. Só adicione uma dependência quando você realmente precisar dela. Caso contrário, você está apenas se preparando para ter mais problemas.</p><p>O que eu gosto no React são os componentes. Um componente é onde definimos visão, estilo e comportamento. O React tem estilo em linha — é como usar JavaScript para definir scripts, HTML e CSS. Isso se encaixa na abordagem de recursos que estamos buscando. É por isso que eu não uso o <a href="https://github.com/styled-components/styled-components">styled-components</a>. Como os estilos são apenas objetos JavaScript, podemos simplesmente compartilhar estilos de comentário em <code>library</code>.</p><h3 id="src"><strong>src</strong></h3><p>Gosto muito do Android. Por isso, coloco os nomes <code>src</code> e <code>res</code> para corresponder às convenções de pasta do sistema.</p><p>O <code>react-native init</code> configura o <code>babel</code> para nós. Porém, em um projeto em JavaScript típico, é bom organizar os arquivos na pasta <code>src</code>. Na minha aplicação <a href="https://github.com/onmyway133/IconGenerator/tree/master/src" rel="noopener">IconGenerator</a>, que usa o <code>electron.js</code>, coloquei os arquivos de origem dentro da pasta <code>src</code>. Isso não só ajuda em termos de organização, mas também ajuda o <code>babel</code> a transpilar toda a pasta de uma só vez. Basta um comando e eu tenho os arquivos de <code>src</code> transpilados para <code>dist</code> em um piscar de olhos.</p><pre><code class="language-bash">babel ./src --out-dir ./dist --copy-files</code></pre><h3 id="screen"><strong><em>Screen</em></strong></h3><p>O React é baseado em componentes. Sim. Existem <a href="https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0">componentes de contêiner e de apresentação</a> (texto em inglês), mas podemos compor componentes para criar componentes mais complexos. Eles, geralmente, terminam aparecendo em tela cheia. Chama-se <code>Page</code> no Windows Phone, <code>ViewController</code> no iOS e <code>Activity</code> no Android. O guia do React Native menciona <a href="https://reactnative.dev/docs/navigation">a tela</a> (em inglês, <em>screen</em>) com muita frequência como algo que cobre todo o espaço:</p><blockquote>As aplicações para dispositivos móveis raramente são compostas de uma única tela. O gerenciamento da apresentação e da transição entre várias telas normalmente é manipulado pelo que é conhecido como navegador.</blockquote><h4 id="usar-ou-n-o-usar-o-index-js"><strong>Usar ou não usar o index.js?</strong></h4><p>Cada tela é considerada o ponto de entrada para um recurso. Você pode renomear <code>LoginScreen.js</code> como <code>index.js</code> para aproveitar o recurso de <a href="https://www.freecodecamp.org/portuguese/news/requisitando-modulos-no-node-js-tudo-o-que-voce-precisa-saber/">módulos</a> do Node:</p><blockquote><code>find-me</code> &nbsp;<code>node_modules</code> &nbsp;<code>index.js</code> &nbsp;<code>require('find-me')</code> &nbsp;<code>index.js</code></blockquote><p>Assim, em vez de <code>import LoginScreen from './screens/LoginScreen'</code>, podemos simplesmente usar <code>import LoginScreen from './screens'</code>.</p><p>Usar o <code>index.js</code> resulta em encapsulamento e fornece uma interface pública para o recurso. Isso tudo se baseia em gosto pessoal. Eu mesmo prefiro nomear explicitamente um arquivo – daí o nome <code>LoginScreen.js</code>.</p><h3 id="navigator"><strong><em>Navigator</em></strong></h3><p>O <a href="https://github.com/react-navigation/react-navigation" rel="noopener">react-navigation</a> parece ser a escolha mais popular para lidar com a navegação em uma aplicação do React Native. Para um recurso como a integração (do inglês, <em>onboarding</em>), provavelmente, existem muitas telas gerenciadas por uma navegação pela pilha. Assim, temos o <code>OnboardingNavigator</code>.</p><p>Pense no Navigator como algo que agrupe subtelas ou recursos. Como estamos agrupando por recurso, é natural colocarmos o navegador dentro da pasta de recursos. A aparência, basicamente, é esta:</p><pre><code class="language-jsx">import { createStackNavigator } from 'react-navigation'
import Welcome from './Welcome'
import Term from './Term'

const routeConfig = {
  Welcome: {
    screen: Welcome
  },
  Term: {
    screen: Term
  }
}

const navigatorConfig = {
  navigationOptions: {
    header: null
  }
}

export default OnboardingNavigator = createStackNavigator(routeConfig, navigatorConfig)</code></pre><h3 id="library"><strong>library</strong></h3><p>Esta é a parte mais polêmica da estruturação de um projeto. Se você não gosta do nome <code>library</code>, pode chamá-la de <code>utilities</code>, <code>common</code>, <code>citadel</code>, ou o que quer que seja...</p><p>Essa pasta não é destinada a arquivos sem outro lugar para ficar, mas é onde colocamos utilitários e componentes comuns, que são usados por muitos recursos. Coisas como componentes atômicos, <em>wrappers</em>, função de correções rápidas, coisas relacionadas à rede e informações de login são muito usadas, sendo difícil movê-las para uma pasta de recursos específica. Às vezes, só precisamos ser práticos e fazer o trabalho.</p><p>No React Native, muitas vezes, precisamos implementar um botão com uma imagem de fundo em muitas telas. Aqui está um botão simples, colocado em <code>library/components/ImageButton.js</code>. A pasta <code>components</code> é para componentes reutilizáveis, às vezes chamados de componentes atômicos. De acordo com as convenções de nomenclatura do React, a primeira letra deve ser maiúscula.</p><pre><code class="language-jsx">import React from 'react'
import { TouchableOpacity, View, Image, Text, StyleSheet } from 'react-native'
import images from 'res/images'
import colors from 'res/colors'

export default class ImageButton extends React.Component {
  render() {
    return (
      &lt;TouchableOpacity style={styles.touchable} onPress={this.props.onPress}&gt;
        &lt;View style={styles.view}&gt;
          &lt;Text style={styles.text}&gt;{this.props.title}&lt;/Text&gt;
        &lt;/View&gt;
        &lt;Image
          source={images.button}
          style={styles.image} /&gt;
      &lt;/TouchableOpacity&gt;
    )
  }
}

const styles = StyleSheet.create({
  view: {
    position: 'absolute',
    backgroundColor: 'transparent'
  },
  image: {
  
},
  touchable: {
    alignItems: 'center',
    justifyContent: 'center'
  },
  text: {
    color: colors.button,
    fontSize: 18,
    textAlign: 'center'
  }
})</code></pre><p>Se quisermos colocar o botão na parte inferior, usamos uma função utilitária para evitar a duplicação de código. Aqui temos a <code>library/utils/moveToBottom.js</code>:</p><pre><code class="language-jsx">import React from 'react'
import { View, StyleSheet } from 'react-native'

function moveToBottom(component) {
  return (
    &lt;View style={styles.container}&gt;
      {component}
    &lt;/View&gt;
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'flex-end',
    marginBottom: 36
  }
})

export default moveToBottom</code></pre><h4 id="usando-o-package-json-para-evitar-caminhos-relativos"><strong>Usando o package.json para evitar caminhos relativos</strong></h4><p>Em algum ponto de <code>src/screens/onboarding/term/Term.js</code>, podemos importar usando caminhos relativos:</p><pre><code class="language-js">import moveToBottom from '../../../../library/utils/move'
import ImageButton from '../../../../library/components/ImageButton'</code></pre><p>Aqui, temos um problema bem visível. A chance de cometermos erros é muito grande, pois precisamos calcular de quantos <code>..</code> precisamos. Se movermos o recurso para outro lugar, todos esses caminhos precisarão ser recalculados.</p><p>Como <code>library</code> é para ser usado em muitos lugares, é bom referenciá-la como um caminho absoluto. Em JavaScript, geralmente, existem milhares de bibliotecas para um único problema. Uma rápida pesquisa no Google revela centenas de bibliotecas para resolver esse problema. Porém, não precisamos de outra dependência, pois isso é extremamente fácil de corrigir.</p><p>A solução é transformar <code>library</code> em um módulo <code>module</code> para que o <code>node</code> consiga encontrá-la. Adicionar o <code>package.json</code> a qualquer pasta a torna um <code>módulo</code> no Node. Adicionamos o <code>package.json</code> dentro da pasta <code>library</code> com este conteúdo simples:</p><pre><code class="language-json">{
  "name": "library",
  "version": "0.0.1"
}</code></pre><p>Agora, em <code>Term.js</code>, podemos importar as coisas de <code>library</code> facilmente, pois, agora, a pasta se tornou um <code>módulo</code>:</p><pre><code class="language-jsx">import React from 'react'
import { View, StyleSheet, Image, Text, Button } from 'react-native'
import strings from 'res/strings'
import palette from 'res/palette'
import images from 'res/images'
import ImageButton from 'library/components/ImageButton'
import moveToBottom from 'library/utils/moveToBottom'

export default class Term extends React.Component {
  render() {
    return (
      &lt;View style={styles.container}&gt;
        &lt;Text style={styles.heading}&gt;{strings.onboarding.term.heading.toUpperCase()}&lt;/Text&gt;
        {
          moveToBottom(
            &lt;ImageButton style={styles.button} title={strings.onboarding.term.button.toUpperCase()} /&gt;
          )
        }
      &lt;/View&gt;
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center'
  },
  heading: {...palette.heading, ...{
    marginTop: 72
  }}
})</code></pre><h3 id="res">res</h3><p>Você pode estar se perguntando o que são <code>res/colors</code>, <code>res/strings</code>, <code>res/images</code> e <code>res/fonts</code> nos exemplos acima. Bem, para projetos de <em>front-end</em>, geralmente temos componentes e os estilizamos usando fontes, strings com localização (traduzidas), cores, imagens e estilos propriamente ditos. O JavaScript é uma linguagem muito dinâmica, sendo fácil usar tipos em formato string em qualquer lugar. Podemos ter várias definições do tipo <code>color: #00B75D;</code> em vários arquivos, ou <code>fontFamily: Fira;</code> em vários componentes do tipo <code>Text</code>. Isso também leva a erros e é difícil de refatorar.</p><p>Vamos encapsular o uso dos recursos na pasta <code>res</code> com objetos mais seguros. Veja a aparência disso nos exemplos a seguir:</p><h3 id="res-colors">res/colors</h3><pre><code class="language-js">const colors = {
  title: '#00B75D',
  text: '#0C222B',
  button: '#036675'
}

export default colors</code></pre><h3 id="res-strings">res/strings</h3><pre><code class="language-js">const strings = {
  onboarding: {
    welcome: {
      heading: 'Welcome',
      text1: "What you don't know is what you haven't learn",
      text2: 'Visit my GitHub at https://github.com/onmyway133',
      button: 'Log in'
    },
    term: {
      heading: 'Terms and conditions',
      button: 'Read'
    }
  }
}

export default strings</code></pre><h3 id="res-fonts">res/fonts</h3><pre><code class="language-js">const fonts = {
  title: 'Arial',
  text: 'SanFrancisco',
  code: 'Fira'
}

export default fonts</code></pre><h3 id="res-images">res/images</h3><pre><code class="language-js">const images = {
  button: require('./images/button.png'),
  logo: require('./images/logo.png'),
  placeholder: require('./images/placeholder.png')
}

export default images</code></pre><p>Assim como em <code>library</code>, os arquivos de <code>res</code> podem ser acessados de qualquer lugar. Assim, vamos tornar a pasta <code>res</code> um <code>módulo</code>. Adicione o <code>package.json</code> à pasta <code>res</code>:</p><pre><code>{
  "name": "res",
  "version": "0.0.1"
}</code></pre><p>Desse modo, podemos acessar a pasta de recursos como se fosse um módulo normal:</p><pre><code>import strings from 'res/strings'
import palette from 'res/palette'
import images from 'res/images'</code></pre><h4 id="agrupar-cores-imagens-e-fontes-com-uma-paleta"><strong>Agrupar cores, imagens e fontes com uma paleta</strong></h4><p>O design da aplicação deve ser consistente. Certos elementos devem ter a mesma aparência para não confundir o usuário. Por exemplo, os títulos do componente <code>Text</code> devem usar uma cor, fonte e tamanho de fonte iguais. O componente <code>Image</code> deve usar a mesma imagem <em>placeholder</em>. No React Native, já usamos o nome <code>styles</code> em <code>const styles = StyleSheet.create({})</code>. Então, vamos usar o nome <code>palette</code> (em português, paleta).</p><p>Abaixo, vemos minha paleta simplificada. Ela define estilos comuns para os títulos e para <code>Text</code>:</p><h3 id="res-palette">res/palette</h3><pre><code>import colors from './colors'

const palette = {
  heading: {
    color: colors.title,
    fontSize: 20,
    textAlign: 'center'
  },
  text: {
    color: colors.text,
    fontSize: 17,
    textAlign: 'center'
  }
}

export default palette</code></pre><p>Também podemos usá-los em nossa tela:</p><pre><code class="language-js">const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center'
  },
  heading: {...palette.heading, ...{
    marginTop: 72
  }}
})</code></pre><p>Aqui, usamos o <a href="https://github.com/tc39/proposal-object-rest-spread" rel="noopener">operador spread em um objeto</a> para unir <code>palette.heading</code> e nosso objeto de estilo personalizado. Isso quer dizer que usamos estilos de <code>palette.heading</code>, mas também especificamos outras propriedades.</p><p>Se fôssemos remodelar a aplicação para diversas marcas, poderíamos ter diversas paletas. Esse é um padrão muito útil.</p><h4 id="gera-o-de-imagens"><strong>Geração de imagens</strong></h4><p>Podemos ver que, em <code>/src/res/images.js</code>, temos propriedades para cada imagem na pasta <code>src/res/images</code>:</p><pre><code>const images = {
  button: require('./images/button.png'),
  logo: require('./images/logo.png'),
  placeholder: require('./images/placeholder.png')
}

export default images</code></pre><p>É um tédio fazer isso manualmente. Teríamos que atualizar se houvesse mudanças na convenção de nomenclatura de imagem. Em vez disso, podemos adicionar um script para gerar <code>images.js</code> com base nas imagens que temos. Adicione um arquivo <code>/scripts/images.js</code> na raiz do projeto:</p><pre><code>const fs = require('fs')

const imageFileNames = () =&gt; {
  const array = fs
    .readdirSync('src/res/images')
    .filter((file) =&gt; {
      return file.endsWith('.png')
    })
    .map((file) =&gt; {
      return file.replace('@2x.png', '').replace('@3x.png', '')
    })
    
return Array.from(new Set(array))
}

const generate = () =&gt; {
  let properties = imageFileNames()
    .map((name) =&gt; {
      return `${name}: require('./images/${name}.png')`
    })
    .join(',\n  ')
    
const string = `const images = {
  ${properties}
}

export default images
`

fs.writeFileSync('src/res/images.js', string, 'utf8')
}

generate()</code></pre><p>No Node, temos um recurso interessante que é o acesso ao módulo <code>fs</code>, muito útil no processamento de arquivos. Aqui, simplesmente percorremos as imagens e atualizamos <code>/src/res/images.js</code> conforme o caso.</p><p>Sempre que adicionarmos ou alterarmos imagens, podemos executar:</p><pre><code class="language-bash">node scripts/images.js</code></pre><p>Também podemos declarar o script dentro de nosso <code>package.json</code> principal:</p><pre><code class="language-json">"scripts": {
  "start": "node node_modules/react-native/local-cli/cli.js start",
  "test": "jest",
  "lint": "eslint *.js **/*.js",
  "images": "node scripts/images.js"
}</code></pre><p>Agora, basta executar <code>npm run images</code> e obtemos o arquivo de recurso <code>images.js </code>atualizado.</p><h4 id="fontes-personalizadas"><strong>Fontes personalizadas</strong></h4><p>O React Native tem algumas <a href="https://medium.com/react-native-training/list-of-available-react-native-fonts-ed78b48bd45e" rel="noopener">fontes personalizadas</a> (texto em inglês) que podem ser boas o suficiente para seu projeto. Você também pode usar fontes personalizadas.</p><p>Uma coisa que se deve perceber é que o Android usa o nome do arquivo de fonte, mas o iOS usa o nome completo. Você pode ver o nome completo na aplicação Font Book ou inspecionando na aplicação em execução</p><pre><code class="language-js">for (NSString* family in [UIFont familyNames]) {
  NSLog(@"%@", family);
  
for (NSString* name in [UIFont fontNamesForFamilyName: family]) {
    NSLog(@"Family name:  %@", name);
  }
}</code></pre><p>Para fontes personalizadas a serem registradas no iOS, precisamos declarar <code>UIAppFonts</code> em <code>Info.plist</code> usando o nome do arquivo das fontes. Para o Android, as fontes precisam ser colocadas em <code>app/src/main/assets/fonts</code>.</p><p>É uma boa prática nomear o arquivo de fonte da mesma forma que o nome completo. Diz-se que o React Native carrega dinamicamente fontes personalizadas, mas, no caso de você obter um "<em>Unrecognized font family</em>" (família de fontes não reconhecidas), basta adicionar essas fontes ao destino dentro do Xcode.</p><p>Fazer isso a mão leva tempo. Por sorte, temos o <a href="https://github.com/rnpm/rnpm" rel="noopener">rnpm</a>, que pode ser útil. Primeiro, adicione todas as fontes na pasta <code>res/fonts</code>. Depois, basta declarar o <code>rnpm</code> no <code>package.json</code> e executar <code>react-native link</code>. Isso deverá declarar o <code>UIAppFonts</code> no iOS e mover todas as fontes para <code>app/src/main/assets/fonts</code> para o Android.</p><pre><code>"rnpm": {
  "assets": [
    "./src/res/fonts/"
  ]
}</code></pre><p>Acessar fontes pelo nome é propenso a erros. Podemos criar um script semelhante ao que fizemos com as imagens para gerar um acesso mais seguro. Adicione <code>fonts.js</code> à nossa pasta <code>scripts</code>:</p><pre><code>const fs = require('fs')

const fontFileNames = () =&gt; {
  const array = fs
    .readdirSync('src/res/fonts')
    .map((file) =&gt; {
      return file.replace('.ttf', '')
    })
    
return Array.from(new Set(array))
}

const generate = () =&gt; {
  const properties = fontFileNames()
    .map((name) =&gt; {
      const key = name.replace(/\s/g, '')
      return `${key}: '${name}'`
    })
    .join(',\n  ')
    
const string = `const fonts = {
  ${properties}
}

export default fonts
`

fs.writeFileSync('src/res/fonts.js', string, 'utf8')
}

generate()</code></pre><p>Agora, você pode usar as fontes personalizadas por meio do <em>namespace</em> <code>R</code>.</p><pre><code>import R from 'res/R'

const styles = StyleSheet.create({
  text: {
    fontFamily: R.fonts.FireCodeNormal
  }
})</code></pre><h3 id="o-namespace-r"><strong>O <em>namespace</em> R</strong></h3><p>Essa etapa depende do gosto pessoal, mas acho mais organizada se introduzirmos o <em>namespace</em> R, assim como o Android faz para ativos com a classe R gerada.</p><p>Ao externalizar os recursos da sua aplicação, você pode acessá-los usando os IDs dos recursos gerados na classe <code>R</code> do seu projeto. Esse documento mostra como agrupar seus recursos no seu projeto para Android e fornece recursos alternativos para configurações de dispositivos específicos, além de mostrar como acessá-los a partir do código de sua aplicação ou de outros arquivos XML.</p><p>Desse modo, vamos criar um arquivo chamado <code>R.js</code> em <code>src/res</code>:</p><pre><code class="language-js">import strings from './strings'
import images from './images'
import colors from './colors'
import palette from './palette'

const R = {
  strings,
  images,
  colors,
  palette
}

export default R</code></pre><p>Depois, vamos acessá-lo na tela:</p><pre><code class="language-jsx">import R from 'res/R'

render() {
  return (
    &lt;SafeAreaView style={styles.container}&gt;
      &lt;Image
        style={styles.logo}
        source={R.images.logo} /&gt;
      &lt;Image
        style={styles.image}
        source={R.images.placeholder} /&gt;
      &lt;Text style={styles.title}&gt;{R.strings.onboarding.welcome.title.toUpperCase()}&lt;/Text&gt;
  )
}</code></pre><p>Substituímos <code>strings</code> por <code>R.strings</code>, <code>colors</code> por <code>R.colors</code> e <code>images</code> por <code>R.images</code>. Com a anotação de R, fica claro que estamos acessando ativos estáticos a partir do pacote da aplicação.</p><p>Isso também corresponde à <a href="https://github.com/airbnb/javascript#naming--PascalCase-singleton" rel="noopener">convenção</a> da Airbnb para os <em>singletons</em>, já que nosso R agora é uma constante global.</p><blockquote><a href="https://github.com/airbnb/javascript#naming--PascalCase-singleton" rel="noopener">23.8</a> Use PascalCase ao exportar um construtor/classe/singleton/função/biblioteca/objeto puro.</blockquote><pre><code class="language-js">const AirbnbStyleGuide = {
  es6: {
  },
}

export default AirbnbStyleGuide</code></pre><h3 id="o-que-mais-podemos-ver"><strong>O que mais podemos ver?</strong></h3><p>Neste artigo, busquei mostrar como penso que deve ser a estruturação de pastas e arquivos em um projeto do React Native. Também aprendemos a gerenciar recursos e a acessá-los de maneira mais segura. Espero que você tenha achado este artigo útil. Aqui estão mais alguns recursos para explorar mais (textos em inglês):</p><ul><li><a href="https://medium.com/the-react-native-log/organizing-a-react-native-project-9514dfadaa0" rel="noopener">Organizing a React Native Project</a></li><li><a href="https://hackernoon.com/structuring-projects-and-naming-components-in-react-1261b6e18d76" rel="noopener">Structuring projects and naming components in React</a></li><li><a href="https://alligator.io/react/index-js-public-interfaces/" rel="noopener">Using index.js for Fun and Public Interfaces</a></li></ul><p>Já que você está aqui, que tal dar uma olhada em outros artigos que escrevi (textos em inglês)?</p><ul><li><a href="https://medium.com/react-native-training/fixing-react-native-issues-and-happy-deploy-to-bitrise-fabric-circleci-44da4ab1487b" rel="noopener">Deploying React Native to Bitrise, Fabric, CircleCI</a></li><li><a href="https://medium.com/react-native-training/position-element-at-the-bottom-of-the-screen-using-flexbox-in-react-native-a00b3790ca42" rel="noopener">Position element at the bottom of the screen using Flexbox in React Native</a></li><li><a href="https://codeburst.io/setting-up-eslint-and-editorconfig-in-react-native-projects-31b4d9ddd0f6" rel="noopener">Setting up ESLint and EditorConfig in React Native projects</a></li><li><a href="https://medium.com/react-native-training/firebase-sdk-with-firestore-for-react-native-apps-in-2018-aa89a67d6934" rel="noopener">Firebase SDK with Firestore for React Native apps in 2018</a></li></ul><p>Se gostou deste artigo, dê uma olhada também em <a href="https://github.com/onmyway133/blog/issues/165" rel="noopener">outros artigos de minha autoria</a> e nas minhas <a href="https://onmyway133.github.io/" rel="noopener">aplicações</a>. Obrigado! </p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Componentes funcionais x componentes de classe no React Native ]]>
                </title>
                <description>
                    <![CDATA[ No React Native, há dois tipos principais de componentes que compõem uma aplicação: componentes funcionais e componentes de classe. Eles são estruturados do mesmo modo que seriam em uma aplicação para a web normal do React. Componentes de classe Os componentes de classe são classes do JavaScript ES2015 que estendem ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/componentes-funcionais-x-componentes-de-classe-no-react-native/</link>
                <guid isPermaLink="false">645da45215c958056bc6d335</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Carlos Silva. ]]>
                </dc:creator>
                <pubDate>Tue, 30 May 2023 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2023/05/5f9c9dcf740569d1a4ca39c4.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/functional-vs-class-components-react-native/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Functional vs Class Components in React Native</a>
      </p><p>No React Native, há dois tipos principais de componentes que compõem uma aplicação: <strong>componentes funcionais</strong> e <strong><strong>c</strong>omponentes de<strong> </strong>classe</strong>. Eles são estruturados do mesmo modo que seriam em uma aplicação para a web normal do React.</p><h2 id="componentes-de-classe"><strong>Componentes de classe</strong></h2><p>Os componentes de classe são classes do JavaScript ES2015 que estendem uma classe base do React chamada <code>Component</code>.</p><pre><code class="language-js">class App extends Component {
    render () {
        return (
            &lt;Text&gt;Hello World!&lt;/Text&gt;
        )
    }
}</code></pre><p>Isso dá para a classe <code>App</code> acesso aos métodos do ciclo de vida do React, como <code>render</code>, bem como às funcionalidades de <em>state</em>/<em>props</em> dos componentes pai.</p><h2 id="componentes-funcionais"><strong>Componentes funcionais</strong></h2><p>Os componentes funcionais são mais simples. Eles não gerenciam seu próprio <em>state</em> nem têm acesso aos métodos de ciclo de vida fornecidos pelo React Native. Eles são, literalmente, funções do JavaScript antigas e simples – às vezes, chamados de componentes sem estado (do inglês, <em>stateless</em>).</p><pre><code class="language-js">const PageOne = () =&gt; {
    return (
        &lt;h1&gt;Page One&lt;/h1&gt;
    );
}</code></pre><h2 id="sum-rio"><strong>Sumário</strong></h2><p>Os componentes de classe são usados como componentes de contêiner para lidar com o gerenciamento do <em>state</em> e para integrar componentes secundários.</p><p>Os componentes funcionais geralmente são usados apenas para fins de exibição – esses componentes chamam funções dos componentes pai para lidar com interações do usuário ou atualizações do <em>state</em>.</p><h2 id="mais-informa-es-sobre-o-estado-do-componente"><strong>Mais informações sobre o estado do componente</strong></h2><h3 id="estado-do-componente"><strong>Estado do componente</strong></h3><p>Nos componentes <code>Class</code>, há uma maneira de armazenar e gerenciar o <em>state</em> criado no React Native.</p><pre><code class="language-javascript">class App extends Component {
  constructor () {
    super();
    this.state = {
      counter: 0
    };
  }
  incrementCount () {
    this.setState({
      counter: this.state.counter + 1
    });
  }
  decrementCount () {
    this.setState({
      counter: this.state.counter - 1
    });
  }
  render () {
    return (
      &lt;View&gt;
        &lt;Text&gt;Count: {this.state.counter}&lt;/Text&gt;
        &lt;Button onPress={this.decrementCount.bind(this)}&gt;-&lt;/Button&gt;
        &lt;Button onPress={this.incrementCount.bind(this)}&gt;+&lt;/Button&gt;
      &lt;/View&gt;
    );
  }
}</code></pre><p>O <em>state </em>é semelhante às <em>props</em>, mas é privado e totalmente controlado pelo componente. Aqui, o método <code>constructor()</code> chama o construtor da classe pai com <code>super();</code> – <strong><strong><strong><strong><code>Component</code></strong></strong></strong></strong> é a classe pai do <code>App</code>, pois estamos usando a palavra-chave <code>extends</code>. O método <code>constructor()</code> também inicializa o objeto de <em>state</em> do componente:</p><pre><code class="language-text">this.state = {
  counter: 0
};</code></pre><p>O <em>state </em>pode ser exibido dentro do componente:</p><pre><code class="language-js">{this.state.counter}</code></pre><p>Ele também pode ser atualizado pela chamada:</p><pre><code class="language-js">this.setState({});</code></pre><p><strong>Observação<strong><strong><strong>:</strong></strong></strong></strong> após a criação inicial no método <code>constructor()</code> do componente, você nunca deve modificar diretamente o <em>state</em> do componente com <code>this.state =</code>. Você deve usar <code>this.setState</code>, como pode ser visto nas funções <code>incrementCount</code> e <code>decrementCount</code> acima.</p><p>A contagem é ampliada e reduzida ao chamar as funções passadas para os manipuladores <code>onPress</code> do mesmo modo que seriam se você chamasse um manipulador de clique do JavaScript na web.</p><p><em><em>A</em>dendo<em>: </em>no primeiro exemplo<em>, <code>&lt;Button&gt;</code> </em>é um componente personalizado<em>; </em>se trata de uma combinação de<em> <code>&lt;TouchableOpacity&gt;</code> </em>e<em> <code>&lt;Text&gt;</code> </em>da<em> </em>API do<em> React Nativ</em>e<em>:</em></em></p><pre><code class="language-js">const Button = ({ onPress, children, buttonProps, textProps }) =&gt; {
  const { buttonStyle, textStyle } = styles;
  return (
    &lt;TouchableOpacity onPress={onPress} style={[buttonStyle, buttonProps]}&gt;
      &lt;Text style={[textStyle, textProps]}&gt;
        {children}
      &lt;/Text&gt;
    &lt;/TouchableOpacity&gt;
  );
};</code></pre><h2 id="mais-informa-es-sobre-o-react-native-"><strong>Mais informações sobre o React Native:</strong></h2><ul><li><a href="https://www.freecodecamp.org/news/react-native-guide/">Guia do React Native</a> (em inglês)</li></ul> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como configurar o login do Google no React Native com Firebase ]]>
                </title>
                <description>
                    <![CDATA[ O login do Google é um ótimo recurso de login a ser oferecido aos usuários de sua aplicação. Ele facilita para os usuários a criação de uma conta e o login. Melhor do que isso, o Firebase torna extremamente fácil para os desenvolvedores adicionar suporte ao login do Google. Configurar ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-configurar-o-login-do-google-no-react-native-com-firebase/</link>
                <guid isPermaLink="false">63234337926c2f06e57cf4cf</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Renato Almeida ]]>
                </dc:creator>
                <pubDate>Mon, 05 Dec 2022 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/React-native-Google-login.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/google-login-with-react-native-and-firebase/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Set Up Google Login in React Native &amp; Firebase</a>
      </p><p>O login do Google é um ótimo recurso de login a ser oferecido aos usuários de sua aplicação. Ele facilita para os usuários a criação de uma conta e o login.</p><p>Melhor do que isso, o Firebase torna extremamente fácil para os desenvolvedores adicionar suporte ao login do Google. Configurar o ambiente do React Native, no entanto, pode criar alguns desafios, os quais são totalmente tratados neste tutorial.</p><p>O React Native e o SDK do Firebase tornam a implementação do login do Google bastante simples. Vamos construir uma aplicação simples que tem apenas um único botão de login do Google. Uma vez que o usuário faça login no Google com sucesso, exibiremos as informações do usuário recuperadas de sua conta do Google, bem como um botão de logout.</p><p>Você também pode adicionar o login do Facebook à aplicação se estiver interessado em fornecer ainda mais opções de login para seus usuários. Você pode conferir este guia para <a href="https://www.instamobile.io/react-native-tutorials/facebook-login-react-native-firebase/">login do Facebook no React Native com Firebase</a> (texto em inglês) se quiser aprender mais sobre como configurar o login no Facebook.</p><h2 id="por-que-usar-um-bot-o-de-login-do-google-em-aplica-es-para-dispositivos-m-veis"><strong>Por que usar um botão de login do Google em aplicações para dispositivos móveis<strong>?</strong></strong></h2><ol><li>Usar o Google ou outras aplicações de terceiros pode fazer o seu processo de autenticação descomplicado e amigável. Os usuários não precisam perder tempo no processo de registro, o que melhorará tremendamente suas taxas de registro e retenção.</li><li>É seguro e protegido.</li><li>Os usuários confiam mais no Google ou no Facebook do que em um portal ou aplicação desconhecida da internet.</li><li>Ele fornece uma boa experiência ao usuário. Como usuário, temos pouca paciência para qualquer ação ou trabalho que precisemos fazer, especialmente em uma aplicação bastante desconhecida que estamos testando pela primeira vez.</li></ol><p>Sem mais delongas, vamos pular diretamente para a parte de desenvolvimento de aplicações deste tutorial.</p><h2 id="configurando-o-projeto-do-firebase"><strong>Configurando o projeto do Firebase</strong></h2><p>Vá até o <a href="https://firebase.google.com/" rel="noopener">console do Firebase</a> e crie um projeto do Firebase:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/create-new-firebase-project.png" class="kg-image" alt="create-new-firebase-project" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/11/create-new-firebase-project.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/11/create-new-firebase-project.png 807w" sizes="(min-width: 720px) 720px" width="807" height="450" loading="lazy"><figcaption>Cria um projeto do Firebase</figcaption></figure><p>Aqui, precisaremos configurar o nome do projeto do Firebase e o identificador da aplicação. Então, vamos primeiro criar a aplicação do React Native.</p><h2 id="criando-o-projeto-do-react-native"><strong>Criando o projeto do <strong>React Native</strong></strong></h2><p>Primeiro, precisamos criar um projeto do React Native usando o seguinte comando:</p><p><code>react-native init instamobile-google-login-demo</code></p><p>Aqui, demos ao projeto o nome <strong>instamobile-google-login-demo</strong>. Agora, precisamos instalar o pacote <strong>react-native-google-signin</strong> usando o seguinte comando:</p><p><code>yarn add react-native-google-singin</code></p><p>O pacote <code>react-native-google-signin</code> é usado para implementar as funções de autenticação do Google na aplicação do React Native. Agora, precisamos importar os módulos e componentes necessários do respectivo pacote, conforme mostrado no trecho de código abaixo:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">import {
GoogleSignin,
GoogleSigninButton,
statusCodes,
} from 'react-native-google-signin';</code></pre><figcaption>Importa o componente de login do google</figcaption></figure><p>Em seguida, precisamos criar os estados para lidar com o estado de autenticação e as informações do usuário. Para isso, utilizamos o módulo <code>useState</code>, conforme mostrado no trecho de código abaixo:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">const [loggedIn, setloggedIn] = useState(false);
const [userInfo, setuserInfo] = useState([]);</code></pre><figcaption>Adiciona os estados</figcaption></figure><p>Agora, precisamos criar uma função de login para lidar com a autenticação, conforme mostrado no trecho de código abaixo:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">_signIn = async () =&gt; {
  try {
    await GoogleSignin.hasPlayServices();
    const {accessToken, idToken} = await GoogleSignin.signIn();
    setloggedIn(true);
  } catch (error) {
    if (error.code === statusCodes.SIGN_IN_CANCELLED) {
      // usuário cancelou o fluxo de login
      alert('Cancel');
    } else if (error.code === statusCodes.IN_PROGRESS) {
      alert('Signin in progress');
      // operação (por exemplo, o login) já está em andamento
    } else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
      alert('PLAY_SERVICES_NOT_AVAILABLE');
      // serviços de execução não disponível ou desatualizado
    } else {
      // algum outro erro ocorreu
    }
  }
};</code></pre><figcaption>Adiciona a função do google sign-in</figcaption></figure><p>A seguir, precisamos inicializar a configuração do objeto de login do Google, fazendo uso da função <code>useEffect</code>:</p><pre><code class="language-javascript">useEffect(() =&gt; {
   GoogleSignin.configure({
     scopes: ['email'], // qual API você quer acessar em nome do usuário; o padrão é o email e o perfil
     webClientId:
       '418977770929-g9ou7r9eva1u78a3anassxxxxxxx.apps.googleusercontent.com', // o ID do client do tipo WEB para seu servidor (necessário para verificar o ID do usuário e o acesso off-line)
     offlineAccess: true, // se você deseja acessar a API do Google API em nome do usuário DE SEU SERVIDOR
   });
 }, []);</code></pre><p>Por fim, precisamos de uma função que lide com a ação de logout. Para isso, vamos implementar o método <code>signOut</code>, conforme mostrado no trecho de código abaixo:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">signOut = async () =&gt; {
    try {
      await GoogleSignin.revokeAccess();
      await GoogleSignin.signOut();
      setloggedIn(false);
      setuserInfo([]);
    } catch (error) {
      console.error(error);
    }
  };</code></pre><figcaption>Adiciona a função de sign-out do Google&nbsp;</figcaption></figure><p>Agora, precisamos apresentar os componentes na tela também. Para isso, vamos fazer uso de vários componentes como <code>View</code> e <code>Button</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">return (
    &lt;&gt;
      &lt;StatusBar barStyle="dark-content" /&gt;
      &lt;SafeAreaView&gt;
        &lt;ScrollView
          contentInsetAdjustmentBehavior="automatic"
          style={styles.scrollView}&gt;
          &lt;Header /&gt;

          &lt;View style={styles.body}&gt;
            &lt;View style={styles.sectionContainer}&gt;
              &lt;GoogleSigninButton
                style={{width: 192, height: 48}}
                size={GoogleSigninButton.Size.Wide}
                color={GoogleSigninButton.Color.Dark}
                onPress={this._signIn}
              /&gt;
            &lt;/View&gt;
            &lt;View style={styles.buttonContainer}&gt;
              {!loggedIn &amp;&amp; &lt;Text&gt;You are currently logged out&lt;/Text&gt;}
              {loggedIn &amp;&amp; (
                &lt;Button
                  onPress={this.signOut}
                  title="LogOut"
                  color="red"&gt;&lt;/Button&gt;
              )}
            &lt;/View&gt;
          &lt;/View&gt;
        &lt;/ScrollView&gt;
      &lt;/SafeAreaView&gt;
    &lt;/&gt;
  );</code></pre><figcaption>Código da IU</figcaption></figure><p>Agora, se nós executarmos nosso projeto no emulador, teremos os seguintes resultados:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/google-login-first-screen.png" class="kg-image" alt="google-login-first-screen" width="560" height="315" loading="lazy"><figcaption>Login com Google React Native</figcaption></figure><p>Bem legal, certo? Concluímos a implementação (tanto da interface do usuário quanto da lógica de negócios) a nível do React Native em nosso projeto.</p><p>Como você pode ver, temos um botão "Sign in with Google" (<em>Fazer login com o Google</em>, em português) que se converte em um botão de logout assim que a operação de login é concluída com sucesso.</p><p>Agora, vamos configurar o pacote do Google SignIn e a aplicação do Firebase.</p><h2 id="configurando-os-projetos-nativos-do-ios-e-do-android"><strong><strong>Configur</strong>ando os projetos nativos do <strong>iOS </strong>e do<strong> Android</strong></strong></h2><p>Existem algumas etapas de configuração que precisamos seguir antes que o projeto esteja totalmente funcionando. Elas estão relacionadas principalmente ao verdadeiro lado nativo da aplicação.</p><h3 id="para-ios"><strong>Para<strong> iOS</strong></strong></h3><p>No VSCode (ou em qualquer Terminal), basta executar <code>cd ios &amp;&amp; pod install</code>. Em seguida, abra o arquivo <em>.xcworkspace</em> no Xcode (da pasta ios) e verifique se os Pods estão incluídos:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/install-google-login-lib-in-xcode.png" class="kg-image" alt="install-google-login-lib-in-xcode" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/11/install-google-login-lib-in-xcode.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/11/install-google-login-lib-in-xcode.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/11/install-google-login-lib-in-xcode.png 1019w" sizes="(min-width: 720px) 720px" width="1019" height="523" loading="lazy"><figcaption>Instala a biblioteca google login no xcode</figcaption></figure><h3 id="para-android"><strong>Para<strong> Android</strong></strong></h3><p>1. Primeiro, precisamos vincular o módulo nativo.</p><ul><li>Se RN &gt;= 0.60, você não precisa fazer nada, graças à vinculação automática.</li><li>Se RN &lt; 0.60, execute <code>react-native link <strong><strong>react-native-google-signin</strong></strong></code>.</li></ul><p>2. Atualize o <strong><strong>android/build.gradle</strong></strong> com a seguinte configuração:</p><pre><code class="language-java">buildscript {
    ext {
        buildToolsVersion = "27.0.3"
        minSdkVersion = 16
        compileSdkVersion = 27
        targetSdkVersion = 26
        supportLibVersion = "27.1.1"
        googlePlayServicesAuthVersion = "16.0.1" // &lt;--- use esta versão ou uma mais recente
    }
...
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.2' // &lt;--- use esta versão ou uma mais recente
        classpath 'com.google.gms:google-services:4.1.0' // &lt;--- use esta versão ou uma mais recente
    }
...
allprojects {
    repositories {
        mavenLocal()
        google() // &lt;--- certifique-se de que isto está incluído
        jcenter()
        maven {
            // Todo o React Native (JS, fontes do Obj-C, binários do Android) é instalado a partir do npm
            url "$rootDir/../node_modules/react-native/android"
        }
    }
}</code></pre><p>3. Atualize o <code>android/app/build.gradle</code> com a seguinte configuração:</p><pre><code class="language-java">...
dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "com.android.support:appcompat-v7:23.0.1"
    implementation "com.facebook.react:react-native:+"
    implementation(project(":react-native-community_google-signin")) // &lt;--- adicione esta dependência
}</code></pre><p>Confira se o <code>react-native link</code> vinculou o módulo nativo – porém, apenas se você usou o <code>react-native link</code>!</p><p>Em <code>android/settings.gradle</code>, devemos ter as seguintes configurações:</p><figure class="kg-card kg-code-card"><pre><code class="language-java">...
include ':react-native-google-signin', ':app'
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/google-signin/android')</code></pre><figcaption>Configura o google login para android em setting.gradle</figcaption></figure><p>Em seguida, em <code>MainApplication.java</code> , devemos ter o pacote do Google adicionado, conforme o trecho de código a seguir:</p><figure class="kg-card kg-code-card"><pre><code class="language-java">import co.apptailor.googlesignin.RNGoogleSigninPackage;  // &lt;--- importar

public class MainApplication extends Application implements ReactApplication {

  ......

  @Override
    protected List&lt;ReactPackage&gt; getPackages() {
      return Arrays.&lt;ReactPackage&gt;asList(
          new MainReactPackage(),
          new RNGoogleSigninPackage() // &lt;-- isto precisa estar na lista
      );
    }
  ......

}</code></pre><figcaption>Configura o google login para android em MainApplication.java</figcaption></figure><h2 id="configurando-o-firebase"><strong>Configurando o <strong>Firebase</strong></strong></h2><h3 id="para-ios-1"><strong>Para<strong> iOS</strong></strong></h3><p>Agora, precisamos começar a configuração do Firebase. No Firebase, precisamos configurar uma aplicação em nuvem do Google. Quando configuramos o método de autenticação no Firebase, no entanto, isso também cria uma aplicação em nuvem do Google.</p><p>Primeiro, precisamos criar a aplicação do iOS do Firebase para obter o <strong>GoogleServiceinfo.plist</strong>, como mostrado na captura de tela abaixo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/add-new-firebase-app-name.png" class="kg-image" alt="add-new-firebase-app-name" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/11/add-new-firebase-app-name.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/11/add-new-firebase-app-name.png 713w" width="713" height="525" loading="lazy"><figcaption>Adiciona novo nome de aplicação do Firebase</figcaption></figure><p>Em seguida, copiamos o arquivo <strong><strong>GoogleService-info.plist</strong></strong> para o projeto do Xcode, como mostrado na captura de tela abaixo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/add-google-service-plist-to-xcode.png" class="kg-image" alt="add-google-service-plist-to-xcode" width="263" height="377" loading="lazy"><figcaption>Adiciona o serviço do google plist ao xcode</figcaption></figure><p>Agora, precisamos adicionar o ID do client invertido que está presente no arquivo <strong>GoogleService-info.plist</strong> aos tipos de URL, tal como mostrado na captura de tela abaixo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/get-reverse-client-id-from-xcode.png" class="kg-image" alt="get-reverse-client-id-from-xcode" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/11/get-reverse-client-id-from-xcode.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/11/get-reverse-client-id-from-xcode.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/11/get-reverse-client-id-from-xcode.png 1020w" sizes="(min-width: 720px) 720px" width="1020" height="395" loading="lazy"><figcaption>Obtém o id do client invertido do xcode</figcaption></figure><p>O próximo passo é ir até <strong><strong>Info</strong></strong> → <strong><strong>URL Types</strong></strong> e preencher o <strong><strong>URL Schemes</strong></strong> como mostrado na captura de tela abaixo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/add-url-scheme-to-xcode.png" class="kg-image" alt="add-url-scheme-to-xcode" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/11/add-url-scheme-to-xcode.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/11/add-url-scheme-to-xcode.png 999w" sizes="(min-width: 720px) 720px" width="999" height="628" loading="lazy"><figcaption>Adiciona o url scheme ao xcode</figcaption></figure><h3 id="para-android-1"><strong>Para<strong> Android</strong></strong></h3><p>Primeiro, precisamos criar uma aplicação do Android no Firebase. Para isso, precisamos de um nome de pacote e certificado <strong>SHA-1</strong> da nossa aplicação. Em seguida, podemos registrar a aplicação do Firebase, conforme mostrado abaixo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/create-new-android-firebase-app-300x252.png" class="kg-image" alt="create-new-android-firebase-app-300x252" width="300" height="252" loading="lazy"><figcaption>Cria uma nova aplicação do Android do Firebase</figcaption></figure><p>Podemos obter o nome do pacote em <strong>MainApplication.java</strong> do nosso projeto, conforme destacado no trecho de código abaixo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/find-out-bundle-name-in-android-app-1024x408.png" class="kg-image" alt="find-out-bundle-name-in-android-app-1024x408" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/11/find-out-bundle-name-in-android-app-1024x408.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/11/find-out-bundle-name-in-android-app-1024x408.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/11/find-out-bundle-name-in-android-app-1024x408.png 1024w" sizes="(min-width: 720px) 720px" width="1024" height="408" loading="lazy"><figcaption>Descobre o nome do pacote na aplicação do Android</figcaption></figure><p>Em seguida, podemos obter a chave SHA-1 no arquivo Keystore. No diretório <strong>android/app</strong>, podemos executar o comando:</p><figure class="kg-card kg-code-card"><pre><code class="language-shell">cd android/app ; 
keytool -exportcert -keystore debug.keystore -list -v</code></pre><figcaption>Gera sha-1</figcaption></figure><p>Então, a chave <strong>SHA-1</strong> aparecerá, conforme mostrado na captura de tela abaixo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/generate-sha1-for-register-android-app-in-firebase.png" class="kg-image" alt="generate-sha1-for-register-android-app-in-firebase" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/11/generate-sha1-for-register-android-app-in-firebase.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/11/generate-sha1-for-register-android-app-in-firebase.png 814w" sizes="(min-width: 720px) 720px" width="814" height="278" loading="lazy"><figcaption>Gera sha1 para registrar a aplicação do Android no Firebase</figcaption></figure><p>Após criar a aplicação de configuração do Firebase com sucesso, precisamos baixar o arquivo <strong>google-services.json</strong> e copiá-lo para o diretório, conforme mostrado na captura de tela abaixo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/add-google-service-json-to-android-app-folder-250x300.png" class="kg-image" alt="add-google-service-json-to-android-app-folder-250x300" width="250" height="300" loading="lazy"><figcaption>Adiciona google service json à pasta da aplicação do android</figcaption></figure><p>Agora, a etapa final é configurar um componente de login do Google no Android.</p><h3 id="instalando-o-pacote-do-firebase-do-react-native"><strong><strong>Instal</strong>ando o pacote do <strong>Firebase</strong> do <strong>React Native </strong></strong></h3><p>Para instalar o pacote <strong>react-native-firebase</strong>, versão 6, precisamos executar o seguinte comando no prompt de comando do nosso projeto:</p><figure class="kg-card kg-code-card"><pre><code class="language-shell"># Using npm 
npm install --save @react-native-firebase/app 
# Using Yarn 
yarn add @react-native-firebase/app</code></pre><figcaption>Instala o componente principal react-native-firebase</figcaption></figure><p>O módulo <code>@react-native-firebase/app</code> deve ser instalado antes de usar qualquer outro serviço do Firebase.</p><h3 id="para-ios-2"><strong>Para<strong> iOS</strong></strong></h3><p>Já adicionamos <strong>GoogleService-Info.plist</strong> ao Xcode. O que resta é permitir que o Firebase no iOS use as credenciais. O SDK do Firebase para iOS deve ser configurado durante a fase de inicialização da aplicação.</p><p>Para fazer isso, precisamos abrir nosso arquivo <code>/ios/{projectName}/AppDelegate.m</code>, e adicionar o seguinte:</p><p>Na parte superior do arquivo, precisamos importar o SDK do Firebase:</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">#import &lt;Firebase.h&gt;</code></pre><figcaption>Inclui o Firebase</figcaption></figure><p>Dentro do método <code>didFinishLaunchingWithOptions</code> existente, precisamos adicionar o seguinte ao topo do método:</p><figure class="kg-card kg-code-card"><pre><code class="language-m">- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // Adicione-me --- \/
  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }
  // Adicione-me --- /\
  // ...
}</code></pre><figcaption>Firebase React Native</figcaption></figure><p>Por fim, precisamos executar o seguinte comando para finalizar a instalação do pacote CocoaPods:</p><figure class="kg-card kg-code-card"><pre><code class="language-shell">cd ios ; pod install</code></pre><figcaption>instala CocoaPods</figcaption></figure><p>É isso. Concluímos a instalação do pacote principal do Firebase no iOS.</p><h3 id="para-android-2"><strong>Para<strong> Android</strong></strong></h3><p>Precisamos configurar o Firebase com as credenciais do Android. Para permitir que o Firebase no Android use as credenciais, o <em>plugin</em> google-services deve estar ativado no projeto. Isso requer a modificação em dois arquivos no diretório Android.</p><p>Primeiro, adicione o plug-in google-services como uma dependência dentro do arquivo <strong>android/build.gradle</strong>:</p><figure class="kg-card kg-code-card"><pre><code class="language-java">buildscript {
  dependencies {
    // ... outras dependências
    classpath 'com.google.gms:google-services:4.2.0'
    // Adicione-me --- /\
  }
}
// Por fim, execute o plug-in adicionando o seguinte ao final do arquivo /android/app/build.gradle:

apply plugin: 'com.google.gms.google-services'</code></pre><figcaption>Adiciona o serviço google</figcaption></figure><h2 id="m-dulo-de-autentica-o-do-react-native-firebase"><strong>Módulo de autenticação do <strong>React Native Firebase</strong></strong></h2><p>Após a conclusão da instalação, precisamos configurar o pacote pai do Firebase. Em seguida, precisamos instalar o módulo filho para autenticação. Para isso, precisamos abrir um terminal e executar o seguinte comando:</p><figure class="kg-card kg-code-card"><pre><code class="language-shell">yarn add @react-native-firebase/auth</code></pre><figcaption>install react native firebase auth&nbsp;</figcaption></figure><h3 id="para-ios-3"><strong>Para<strong> iOS</strong></strong></h3><p>Precisamos instalar os pods novamente na linha de comando:</p><figure class="kg-card kg-code-card"><pre><code>cd ios/ &amp;&amp; pod install</code></pre><figcaption>Instala o cacao pod</figcaption></figure><h3 id="para-android-3"><strong>Para<strong> Android</strong></strong></h3><p>Você pode seguir as instruções na <a href="https://rnfirebase.io/auth/usage/installation/android" rel="noopener">documentação oficial</a>, a qual é necessária somente se você estiver usando o React Native &lt;= 0.59 ou se precisar integrar manualmente a biblioteca.</p><h3 id="ativando-o-login-do-google-no-firebase"><strong>Ativando o login do <strong>Google </strong>no<strong> Firebase</strong></strong></h3><p>Precisamos ir ao console do Firebase. Em seguida, na seção Authentication (<em>Autenticação</em>, em português), precisamos clicar em Google, conforme mostrado na captura de tela abaixo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/authentication-method-in-firebase-1024x396.png" class="kg-image" alt="authentication-method-in-firebase-1024x396" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/11/authentication-method-in-firebase-1024x396.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/size/w1000/2022/11/authentication-method-in-firebase-1024x396.png 1000w, https://www.freecodecamp.org/portuguese/news/content/images/2022/11/authentication-method-in-firebase-1024x396.png 1024w" sizes="(min-width: 720px) 720px" width="1024" height="396" loading="lazy"><figcaption>Método de autenticação no Firebase</figcaption></figure><p>Em seguida, precisamos habilitar a configuração e salvá-la conforme mostrado na captura de tela abaixo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/select-support-email-in-firebase-app.png" class="kg-image" alt="select-support-email-in-firebase-app" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/11/select-support-email-in-firebase-app.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/11/select-support-email-in-firebase-app.png 928w" sizes="(min-width: 720px) 720px" width="928" height="472" loading="lazy"><figcaption>Ativa o e-mail de suporte do projeto</figcaption></figure><p>No <strong><strong>App.js</strong></strong>, precisamos importar o <strong><strong>auth</strong></strong> do pacote Firebase, como mostrado no trecho de código abaixo:</p><figure class="kg-card kg-code-card"><pre><code>import auth from '@react-native-firebase/auth';</code></pre><figcaption>Importa o auth do pacote firebase</figcaption></figure><p>Em seguida, precisamos integrar a configuração de autenticação à função de login. Após um login bem-sucedido, armazenamos o <strong>accessToken</strong> e o <strong>idToken</strong> no <strong>Firebase</strong>. Agora, podemos tentar fazer login com o Google em nossa aplicação do React Native de demonstração.</p><figure class="kg-card kg-code-card"><pre><code class="language-javacript">_signIn = async () =&gt; {
    try {
      await GoogleSignin.hasPlayServices();
      const {accessToken, idToken} = await GoogleSignin.signIn();
      setloggedIn(true);
      const credential = auth.GoogleAuthProvider.credential(
        idToken,
        accessToken,
      );
      await auth().signInWithCredential(credential);
    } catch (error) {</code></pre><figcaption>Função de Login do Firebase</figcaption></figure><p>Agora, concluímos com sucesso a integração do Login do Google em nossa aplicação do React Native:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/2020-06-29-17.52.16.gif" class="kg-image" alt="2020-06-29-17.52.16" width="330" height="701" loading="lazy"><figcaption>Resultado do login do Google com o React Native</figcaption></figure><p>Podemos ver novos dados que são adicionados ao console do Firebase:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/firebase-authentication-console.png" class="kg-image" alt="firebase-authentication-console" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/11/firebase-authentication-console.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/11/firebase-authentication-console.png 800w" sizes="(min-width: 720px) 720px" width="800" height="137" loading="lazy"><figcaption>Console de autenticação do firebase</figcaption></figure><h2 id="rastreando-o-status-do-usu-rio"><strong>Rastreando o status do usuário</strong></h2><p>Para verificar o status do login do usuário, usamos o Firebase Auth. Para isso, precisamos adicionar o método <strong>onAuthStateChanged</strong> ao <strong>useEffect</strong> para que ele seja executado em cada chamada do evento <strong>componentDidMount</strong>.</p><p>Além disso, precisamos passar um retorno de chamada para a função denominada <strong>onAuthStateChanged</strong> como um argumento, conforme mostrado no trecho de código abaixo:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">useEffect(() =&gt; {
    .............
    const subscriber = auth().onAuthStateChanged(onAuthStateChanged);
    return subscriber; // remover a inscrição ao desmontar
  }, []);</code></pre><figcaption>Subscreve ao estado da autenticação</figcaption></figure><p>Na função <strong><strong>onAuthStateChanged, </strong></strong>tratamos os dados do estado local conforme mostrado no trecho de código abaixo:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">function onAuthStateChanged(user) {
    setUser(user);
    console.log(user);
    if (user) setloggedIn(true);
  }</code></pre><figcaption>Define dados do usuário</figcaption></figure><p>Agora, precisamos armazenar os dados do usuário no estado. Em seguida, tentar exibir os dados do usuário após um login bem-sucedido. Para isso, precisamos usar o seguinte pedaço de código:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">{!user &amp;&amp; &lt;Text&gt;You are currently logged out&lt;/Text&gt;}
{user &amp;&amp; (
  &lt;View&gt;
    &lt;Text&gt;Welcome {user.displayName}&lt;/Text&gt;
    &lt;Button
      onPress={this.signOut}
      title="LogOut"
      color="red"&gt;&lt;/Button&gt;
  &lt;/View&gt;
)}</code></pre><figcaption>Código para exibir as informações do usuário</figcaption></figure><p>Teremos o seguinte resultado em nosso simulador:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/show-auth-user-name.png" class="kg-image" alt="show-auth-user-name" width="442" height="813" loading="lazy"><figcaption>Logout do auth do Firebase</figcaption></figure><h2 id="logout-do-firebase"><strong>Logout do <strong>Firebase</strong></strong></h2><p>Para sair, precisamos remover todas as credenciais do usuário e revogar o token de login do Google.</p><p>Primeiro, precisamos aguardar o módulo <strong>GoogleSignin</strong> revogar o acesso e sair. Em seguida, chamamos o método <strong>signOut</strong> da autenticação do <strong>Firebase</strong> para fazer logout com êxito.</p><p>A implementação completa do código é fornecida no trecho de código abaixo:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">signOut = async () =&gt; {
    try {
      await GoogleSignin.revokeAccess();
      await GoogleSignin.signOut();
      auth()
        .signOut()
        .then(() =&gt; alert('Your are signed out!'));
      setloggedIn(false);
      // setuserInfo([]);
    } catch (error) {
      console.error(error);
    }
  };</code></pre><figcaption>Função de logout do Firebase</figcaption></figure><p>Como resultado, agora podemos realizar operações de logout, conforme mostrado no trecho de código abaixo:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/11/firebase-signout-result.gif" class="kg-image" alt="firebase-signout-result" width="326" height="616" loading="lazy"><figcaption>Logout do Firebase com React Native</figcaption></figure><h2 id="conclus-o"><strong><strong>Conclus</strong>ão</strong></h2><p>Neste tutorial, aprendemos como configurar o Login do Google, além de armazenar um token de acesso, aproveitando o Firebase em nosso projeto React Native.</p><p>Primeiro, criamos o projeto do React Native com todos os componentes e configurações de funções necessários. Em seguida, aprendemos como configurar o Google Sign In e o Firebase para as plataformas do Android e do iOS. Por fim, configuramos o Firebase na aplicação do React Native usando um pacote do Firebase e exibimos os dados do usuário junto com o botão de logout.</p><p>Você pode baixar o código-fonte completo deste tutorial no <a href="https://github.com/florion101/firebase-google-login-react-native">Github</a>.</p><p>A melhor parte é que o Firebase e o Google Auth são compatíveis com todas as linguagens de desenvolvimento para dispositivos móveis, tais como <a href="https://www.instaflutter.com/">Flutter</a>, <a href="https://www.iosapptemplates.com/">Swift</a> ou <a href="https://www.instakotlin.com/">Kotlin</a>. As etapas de configuração e a abordagem arquitetural são exatamente as mesmas.</p><h2 id="pr-ximos-passos"><strong>Próximos passos</strong></h2><p>Agora que você aprendeu sobre como configurar o Login do Google com Firebase em aplicações do React Native, aqui estão alguns outros tópicos nos quais você pode dar uma olhada:</p><ul><li><a href="https://www.freecodecamp.org/portuguese/news/como-criar-uma-aplicacao-em-react-native-app-and-integrate-e-integra-la-com-firebase/">Como criar uma aplicação em React Native e integrá-la com Firebase</a></li><li>Firebase e React Native — &nbsp;<a href="https://www.instamobile.io/react-native-tutorials/push-notifications-react-native-firebase/" rel="noopener nofollow">Notificações push</a> | <a href="https://www.instamobile.io/mobile-development/react-native-firebase-storage/" rel="noopener nofollow">Armazenamento do Firebase</a> (textos em inglês)</li><li>Mais métodos de autenticação em React Native e Firebase — <a href="https://www.instamobile.io/mobile-development/google-login-react-native-firebase/" rel="noopener nofollow">Login do Google</a> | <a href="https://www.instamobile.io/react-native-tutorials/facebook-login-react-native-firebase/">Login do Facebook</a> | <a href="https://www.instamobile.io/mobile-development/firebase-phone-authentication-react-native/" rel="noopener nofollow">Autenticação OTP/SMS por telefone</a> (textos em inglês)</li></ul><p>Se você gostou deste tutorial do React Native, dê uma estrela no <a href="https://github.com/florion101/firebase-google-login-react-native">repositório do Github</a> e compartilhe-o com sua comunidade. Você pode conferir ainda mais <a href="https://www.instamobile.io/mobile-templates/react-native-templates-free/" rel="noopener">projetos do React Native gratuitos</a> na Instamobile. Obrigado!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como criar uma aplicação em React Native e integrá-la com Firebase ]]>
                </title>
                <description>
                    <![CDATA[ Neste tutorial, vamos construir uma aplicação em React Native integrada ao Firebase no back-end. A aplicação também terá suporte da React Native CLI e da Expo CLI. Este tutorial de React Native com Firebase abrangerá as funcionalidades principais, como autenticação, registro e operações CRUD no banco de dados (Firestore). Você ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-criar-uma-aplicacao-em-react-native-app-and-integrate-e-integra-la-com-firebase/</link>
                <guid isPermaLink="false">631fbc87926c2f06e57cea94</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ana Beatriz ]]>
                </dc:creator>
                <pubDate>Wed, 05 Oct 2022 09:34:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/react-native-firebase.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/react-native-firebase-tutorial/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Build a React Native App and Integrate It with Firebase</a>
      </p><p>Neste tutorial, vamos construir uma aplicação em React Native integrada ao Firebase no back-end. A aplicação também terá suporte da React Native CLI e da Expo CLI.</p><p>Este tutorial de <strong>React Native com Firebase</strong> abrangerá as funcionalidades principais, como autenticação, registro e operações CRUD no banco de dados (Firestore).</p><p>Você também pode <a href="https://github.com/instamobile/react-native-firebase">baixar o código completo</a> no GitHub se quiser conferi-lo.</p><p>Este tutorial percorrerá os detalhes por meio das seguintes seções:</p><ol><li><strong>Criação de um projeto com o Firebase</strong></li><li><strong>Criação e configuração de uma aplicação em React Native</strong></li><li><strong>Configuração da estrutura de pastas, rotas e navegação</strong></li><li><strong>Implementação da interface para telas de login, registro e início</strong></li><li><strong>Registro com Firebase Auth</strong></li><li><strong>Login com Firebase Auth</strong></li><li><strong>Persistência de credenciais de login</strong></li><li><strong>Escrita e leitura de dados a partir do Firebase Firestore</strong></li></ol><p>Sem mais delongas, vamos começar a construir o projeto em React Native com Firebase. A aplicação final ficará assim:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/react-native-firebase-1.png" class="kg-image" alt="react-native-firebase-1" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/react-native-firebase-1.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/react-native-firebase-1.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><h2 id="1-cria-o-de-um-projeto-com-o-firebase">1. Criação de um projeto com o Firebase</h2><p>Visite <a href="https://firebase.google.com/">Firebase.com</a> e crie uma conta. Quando fizer login, você poderá criar um projeto no <a href="https://console.firebase.google.com/u/0/">Firebase Console</a>.</p><ul><li>Crie uma conta no <a href="https://firebase.google.com/">Firebase.com</a></li><li>Crie um projeto no <a href="https://console.firebase.google.com/">Firebase Console</a></li><li>Habilite o método de autenticação com e-mail e senha em <em>Firebase Console</em> &nbsp;-&gt; &nbsp;<em>Authentication</em> &nbsp;-&gt; &nbsp;<em>Sign-in method</em></li></ul><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1__J2bqHTUxhs_sTxwRdbvAg.png" class="kg-image" alt="1__J2bqHTUxhs_sTxwRdbvAg" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/1__J2bqHTUxhs_sTxwRdbvAg.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1__J2bqHTUxhs_sTxwRdbvAg.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><ul><li>Crie uma aplicação para o iOS, com o ID de aplicação <em>com.reactnativefirebase</em></li></ul><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1_RFyy5eHgUlZIEQtaCj5ddA.png" class="kg-image" alt="1_RFyy5eHgUlZIEQtaCj5ddA" width="600" height="400" loading="lazy"></figure><ul><li>(Opcional) Crie uma aplicação do Android com o nome de pacote <em>com.reactnativefirebase</em></li><li>Baixe no seu computador o arquivo de configuração gerado no próximo passo (<em>GoogleService-Info.plist </em>para iOS e <em>google-services.json </em>para Android)</li></ul><p>O Firebase permite construir aplicações <em>sem o back-end</em>. É um produto que executa por dentro da Google Cloud e permite que os desenvolvedores construam aplicações para a web e dispositivos móveis sem precisarem de seus próprios servidores.</p><p>Isso faz você economizar muito tempo, por não haver a necessidade de escrever código para o back-end. Também é muito escalável, sendo sustentado pela infraestrutura do Google.</p><p>No Firebase, você poderá armazenar tudo que é necessário para sua aplicação – usuários, dados, arquivos, tokens para notificações por push, etc. Toda essa informação fica disponível nos clients para dispositivos móveis a partir dos SDKs do Firebase, que são compatíveis com o React Native. Isso significa que todas as interações com o back-end ficam abstraídas e encapsuladas no SDK. Então, os desenvolvedores para dispositivos móveis não precisam se preocupar com chamadas para API, análise de dados, gerenciamento de sockets e outros aspectos.</p><h2 id="2-cria-o-e-configura-o-de-uma-aplica-o-em-react-native">2. Criação e configuração de uma aplicação em React Native</h2><p>Vamos deixar nossa aplicação do React Native com Firebase compatível com a Expo CLI e a React Native CLI.‌‌ Vamos usar o Expo por agora, pois facilita a visualização da aplicação. Não usaremos, no entanto, bibliotecas específicas do Expo. Assim, o código fonte será usado de maneira simples em qualquer aplicação do React Native, não importando no que ele está baseado. ‌‌Vamos usar o <a href="https://firebase.google.com/docs/reference/js">SDK Web do Firebase</a>, que é compatível com o Expo e com a React Native CLI, além de ter suporte direto do Google.</p><p>Se você quiser usar <a href="https://rnfirebase.io/">react-native-firebase</a> como alternativa, fique à vontade para instalar e configurar (o código permanecerá o mesmo). Saiba que não recomendamos isso por alguns motivos:</p><ul><li>ele não possui suporte direto do Google, o que torna a manutenção mais difícil, dado que é uma camada extra que pode causar bugs e</li><li>ele não funciona com o Expo, o que pode ser um problema para muitos desenvolvedores.</li></ul><p>Os passos a seguir também estão na documentação oficial do React Native, em <a href="https://reactnative.dev/docs/environment-setup">Como configurar seu ambiente de desenvolvimento</a> (em inglês).</p><ul><li>Instale a Expo CLI</li></ul><p>No seu terminal, execute</p><p><code>npm install -g expo-cli</code></p><ul><li>Crie uma aplicação do React Native executando</li></ul><p><code>expo init react-native-firebase</code></p><p>Para o template, escolha <em>Managed Workflow</em> — <em>Blank</em></p><ul><li>Inicie a aplicação executando</li></ul><pre><code class="language-bash">yarn ios
// ou
yarn android</code></pre><p>O comando também fornecerá a você um QR Code que pode ser escaneado usando a aplicação de Camera, no iOS, ou o Expo, no Android.</p><p>Ótimo. Agora temos uma nova aplicação do React Native, executando no iOS e no Android. Vamos começar conectando-a ao nosso back-end usando o Firebase.</p><ul><li>Adicione o SDK do Firebase no projeto React Native</li></ul><p><code>yarn add firebase</code></p><ul><li>Adicione a biblioteca React Native Navigation executando</li></ul><pre><code>yarn add @react-navigation/native &amp;&amp; yarn add @react-navigation/stack &amp;&amp; expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view</code></pre><ul><li>Adicione vários componentes à interface e pacotes que serão usados no projeto</li></ul><p><code>yarn add react-native-keyboard-aware-scroll-view base-64</code></p><p>Crie um arquivo de configuração para o Firebase</p><p><code>mkdir src src/firebase &amp;&amp; touch src/firebase/config.js</code></p><p>Adicione a configuração do seu firebase em <em>src/firebase/config.js:</em></p><pre><code class="language-javascript">import * as firebase from 'firebase';
import '@firebase/auth';
import '@firebase/firestore';

const firebaseConfig = {
  apiKey: 'YOUR_KEY_HERE_AIzaSyAOWH',
  authDomain: 'your-auth-domain-b1234.firebaseapp.com',
  databaseURL: 'https://your-database-name.firebaseio.com',
  projectId: 'your-project-id-1234',
  storageBucket: 'your-project-id-1234.appspot.com',
  messagingSenderId: '12345-insert-yourse',
  appId: 'insert yours: 1:1234:web:ee873bd1234c0deb7eba61ce',
};

if (!firebase.apps.length) {
    firebase.initializeApp(firebaseConfig);
}

export { firebase };</code></pre><p>Você consegue toda a informação a partir do <em><a href="https://console.firebase.google.com/">Firebase Console</a> &nbsp;-&gt; Project Settings</em></p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1_RU6D6YeIhpIprROu8lmOOw.png" class="kg-image" alt="1_RU6D6YeIhpIprROu8lmOOw" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/1_RU6D6YeIhpIprROu8lmOOw.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1_RU6D6YeIhpIprROu8lmOOw.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><h2 id="3-configura-o-da-estrutura-de-pastas-rotas-e-navega-o">3. Configuração da estrutura de pastas, rotas e navegação</h2><ul><li>Crie a estrutura da pasta executando</li></ul><pre><code>mkdir src/screens src/screens/LoginScreen src/screens/RegistrationScreen src/screens/HomeScreen</code></pre><ul><li>Crie a estrutura de arquivos executando</li></ul><pre><code>touch src/screens/index.js src/screens/LoginScreen/LoginScreen.js src/screens/LoginScreen/styles.js src/screens/RegistrationScreen/RegistrationScreen.js src/screens/styles.js src/screens/HomeScreen/HomeScreen.js src/screens/HomeScreen/styles.js</code></pre><ul><li>Adicione este código a <em><em>src/screens/index.js</em></em></li></ul><pre><code class="language-javascript">export { default as LoginScreen } from './LoginScreen/LoginScreen'

export { default as HomeScreen } from './HomeScreen/HomeScreen'

export { default as RegistrationScreen } from './RegistrationScreen/RegistrationScreen'
</code></pre><p>Não se preocupe se o projeto apresentar erros! Tudo fará sentido daqui a pouco.</p><ul><li>Configure as rotas e navegações</li></ul><p>Sobrescreva o arquivo <em>App.js</em> com o seguinte código:</p><pre><code class="language-javascript">import 'react-native-gesture-handler';
import React, { useEffect, useState } from 'react'
import { NavigationContainer } from '@react-navigation/native'
import { createStackNavigator } from '@react-navigation/stack'
import { LoginScreen, HomeScreen, RegistrationScreen } from './src/screens'
import {decode, encode} from 'base-64'
if (!global.btoa) {  global.btoa = encode }
if (!global.atob) { global.atob = decode }

const Stack = createStackNavigator();

export default function App() {

  const [loading, setLoading] = useState(true)
  const [user, setUser] = useState(null)

  return (
    &lt;NavigationContainer&gt;
      &lt;Stack.Navigator&gt;
        { user ? (
          &lt;Stack.Screen name="Home"&gt;
            {props =&gt; &lt;HomeScreen {...props} extraData={user} /&gt;}
          &lt;/Stack.Screen&gt;
        ) : (
          &lt;&gt;
            &lt;Stack.Screen name="Login" component={LoginScreen} /&gt;
            &lt;Stack.Screen name="Registration" component={RegistrationScreen} /&gt;
          &lt;/&gt;
        )}
      &lt;/Stack.Navigator&gt;
    &lt;/NavigationContainer&gt;
  );
}</code></pre><h2 id="4-implementa-o-da-interface">4. Implementação da interface</h2><p>Agora que temos a base da aplicação, vamos continuar e implementar os componentes para a interface de todas as telas. Não falaremos sobre layout flexível, nem sobre estilização do React Native, visto que esses pontos estão fora do escopo deste tutorial. Vamos focar na integração entre React Native e Firebase.</p><p>Sobrescreva os arquivos a seguir:</p><ul><li>src/LoginScreen/LoginScreen.js</li></ul><pre><code class="language-javascript">import React, { useState } from 'react'
import { Image, Text, TextInput, TouchableOpacity, View } from 'react-native'
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import styles from './styles';

export default function LoginScreen({navigation}) {
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')

    const onFooterLinkPress = () =&gt; {
        navigation.navigate('Registration')
    }

    const onLoginPress = () =&gt; {
    }

    return (
        &lt;View style={styles.container}&gt;
            &lt;KeyboardAwareScrollView
                style={{ flex: 1, width: '100%' }}
                keyboardShouldPersistTaps="always"&gt;
                &lt;Image
                    style={styles.logo}
                    source={require('../../../assets/icon.png')}
                /&gt;
                &lt;TextInput
                    style={styles.input}
                    placeholder='E-mail'
                    placeholderTextColor="#aaaaaa"
                    onChangeText={(text) =&gt; setEmail(text)}
                    value={email}
                    underlineColorAndroid="transparent"
                    autoCapitalize="none"
                /&gt;
                &lt;TextInput
                    style={styles.input}
                    placeholderTextColor="#aaaaaa"
                    secureTextEntry
                    placeholder='Password'
                    onChangeText={(text) =&gt; setPassword(text)}
                    value={password}
                    underlineColorAndroid="transparent"
                    autoCapitalize="none"
                /&gt;
                &lt;TouchableOpacity
                    style={styles.button}
                    onPress={() =&gt; onLoginPress()}&gt;
                    &lt;Text style={styles.buttonTitle}&gt;Log in&lt;/Text&gt;
                &lt;/TouchableOpacity&gt;
                &lt;View style={styles.footerView}&gt;
                    &lt;Text style={styles.footerText}&gt;Don't have an account? &lt;Text onPress={onFooterLinkPress} style={styles.footerLink}&gt;Sign up&lt;/Text&gt;&lt;/Text&gt;
                &lt;/View&gt;
            &lt;/KeyboardAwareScrollView&gt;
        &lt;/View&gt;
    )
}</code></pre><ul><li>src/LoginScreen/styles.js</li></ul><pre><code class="language-javascript">import { StyleSheet } from 'react-native';

export default StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center'
    },
    title: {

    },
    logo: {
        flex: 1,
        height: 120,
        width: 90,
        alignSelf: "center",
        margin: 30
    },
    input: {
        height: 48,
        borderRadius: 5,
        overflow: 'hidden',
        backgroundColor: 'white',
        marginTop: 10,
        marginBottom: 10,
        marginLeft: 30,
        marginRight: 30,
        paddingLeft: 16
    },
    button: {
        backgroundColor: '#788eec',
        marginLeft: 30,
        marginRight: 30,
        marginTop: 20,
        height: 48,
        borderRadius: 5,
        alignItems: "center",
        justifyContent: 'center'
    },
    buttonTitle: {
        color: 'white',
        fontSize: 16,
        fontWeight: "bold"
    },
    footerView: {
        flex: 1,
        alignItems: "center",
        marginTop: 20
    },
    footerText: {
        fontSize: 16,
        color: '#2e2e2d'
    },
    footerLink: {
        color: "#788eec",
        fontWeight: "bold",
        fontSize: 16
    }
})</code></pre><ul><li>src/RegistrationScreen/RegistrationScreen.js</li></ul><pre><code class="language-javascript">import React, { useState } from 'react'
import { Image, Text, TextInput, TouchableOpacity, View } from 'react-native'
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import styles from './styles';

export default function RegistrationScreen({navigation}) {
    const [fullName, setFullName] = useState('')
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const [confirmPassword, setConfirmPassword] = useState('')

    const onFooterLinkPress = () =&gt; {
        navigation.navigate('Login')
    }

    const onRegisterPress = () =&gt; {
    }

    return (
        &lt;View style={styles.container}&gt;
            &lt;KeyboardAwareScrollView
                style={{ flex: 1, width: '100%' }}
                keyboardShouldPersistTaps="always"&gt;
                &lt;Image
                    style={styles.logo}
                    source={require('../../../assets/icon.png')}
                /&gt;
                &lt;TextInput
                    style={styles.input}
                    placeholder='Full Name'
                    placeholderTextColor="#aaaaaa"
                    onChangeText={(text) =&gt; setFullName(text)}
                    value={fullName}
                    underlineColorAndroid="transparent"
                    autoCapitalize="none"
                /&gt;
                &lt;TextInput
                    style={styles.input}
                    placeholder='E-mail'
                    placeholderTextColor="#aaaaaa"
                    onChangeText={(text) =&gt; setEmail(text)}
                    value={email}
                    underlineColorAndroid="transparent"
                    autoCapitalize="none"
                /&gt;
                &lt;TextInput
                    style={styles.input}
                    placeholderTextColor="#aaaaaa"
                    secureTextEntry
                    placeholder='Password'
                    onChangeText={(text) =&gt; setPassword(text)}
                    value={password}
                    underlineColorAndroid="transparent"
                    autoCapitalize="none"
                /&gt;
                &lt;TextInput
                    style={styles.input}
                    placeholderTextColor="#aaaaaa"
                    secureTextEntry
                    placeholder='Confirm Password'
                    onChangeText={(text) =&gt; setConfirmPassword(text)}
                    value={confirmPassword}
                    underlineColorAndroid="transparent"
                    autoCapitalize="none"
                /&gt;
                &lt;TouchableOpacity
                    style={styles.button}
                    onPress={() =&gt; onRegisterPress()}&gt;
                    &lt;Text style={styles.buttonTitle}&gt;Create account&lt;/Text&gt;
                &lt;/TouchableOpacity&gt;
                &lt;View style={styles.footerView}&gt;
                    &lt;Text style={styles.footerText}&gt;Already got an account? &lt;Text onPress={onFooterLinkPress} style={styles.footerLink}&gt;Log in&lt;/Text&gt;&lt;/Text&gt;
                &lt;/View&gt;
            &lt;/KeyboardAwareScrollView&gt;
        &lt;/View&gt;
    )
}</code></pre><ul><li>src/RegistrationScreen/styles.js</li></ul><pre><code class="language-javascript">import { StyleSheet } from 'react-native';

export default StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center'
    },
    title: {

    },
    logo: {
        flex: 1,
        height: 120,
        width: 90,
        alignSelf: "center",
        margin: 30
    },
    input: {
        height: 48,
        borderRadius: 5,
        overflow: 'hidden',
        backgroundColor: 'white',
        marginTop: 10,
        marginBottom: 10,
        marginLeft: 30,
        marginRight: 30,
        paddingLeft: 16
    },
    button: {
        backgroundColor: '#788eec',
        marginLeft: 30,
        marginRight: 30,
        marginTop: 20,
        height: 48,
        borderRadius: 5,
        alignItems: "center",
        justifyContent: 'center'
    },
    buttonTitle: {
        color: 'white',
        fontSize: 16,
        fontWeight: "bold"
    },
    footerView: {
        flex: 1,
        alignItems: "center",
        marginTop: 20
    },
    footerText: {
        fontSize: 16,
        color: '#2e2e2d'
    },
    footerLink: {
        color: "#788eec",
        fontWeight: "bold",
        fontSize: 16
    }
})</code></pre><ul><li>src/HomeScreen/HomeScreen.js</li></ul><pre><code class="language-javascript">import React from 'react'
import { Text, View } from 'react-native'

export default function HomeScreen(props) {
    return (
        &lt;View&gt;
            &lt;Text&gt;Home Screen&lt;/Text&gt;
        &lt;/View&gt;
    )
}</code></pre><ul><li>src/HomeScreen/styles.js</li></ul><pre><code class="language-javascript">import { StyleSheet } from 'react-native';

export default StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center'
    },
    input: {
        height: 48,
        borderRadius: 5,
        overflow: 'hidden',
        backgroundColor: 'white',
        marginTop: 10,
        marginBottom: 10,
        marginLeft: 30,
        marginRight: 30,
        paddingLeft: 16
    }
})</code></pre><p>Até aqui, sua aplicação deve executar corretamente e mostrar as seguintes telas (interface apenas):</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1_rwQyQ3ZCE7rgHukTAeLliw.png" class="kg-image" alt="1_rwQyQ3ZCE7rgHukTAeLliw" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/1_rwQyQ3ZCE7rgHukTAeLliw.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1_rwQyQ3ZCE7rgHukTAeLliw.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Você pode mudar entre as duas telas pressionando os links no rodapé.</p><p>Agora que temos uma interface bonita de login e registro, vamos ver como podemos integrar nossa aplicação do React Native (e Expo) com o Firebase.</p><h2 id="5-react-native-com-firebase-registro">5. React Native com Firebase  —  registro</h2><p>Vamos começar criando uma conta com o Firebase Auth, pois o login acontece depois. Para isso, vamos adicionar a lógica do Firebase para criar uma conta com e-mail e senha em <em>RegistrationScreen.js</em>, implementando o método <em>onRegisterPress,</em> assim:</p><pre><code class="language-javascript">//...

import { firebase } from '../../firebase/config'

//...

export default function RegistrationScreen({navigation}) {
    //...

    const onRegisterPress = () =&gt; {
        if (password !== confirmPassword) {
            alert("Passwords don't match.")
            return
        }
        firebase
            .auth()
            .createUserWithEmailAndPassword(email, password)
            .then((response) =&gt; {
                const uid = response.user.uid
                const data = {
                    id: uid,
                    email,
                    fullName,
                };
                const usersRef = firebase.firestore().collection('users')
                usersRef
                    .doc(uid)
                    .set(data)
                    .then(() =&gt; {
                        navigation.navigate('Home', {user: data})
                    })
                    .catch((error) =&gt; {
                        alert(error)
                    });
            })
            .catch((error) =&gt; {
                alert(error)
        });
    }
    
    //...
}</code></pre><p>No fluxo de criação de senha acima, fizemos algumas coisas importantes:</p><ul><li>Chamamos a função <code>createUserWithEmailAndPassword</code>, da API do Firebase Auth (linha 13), que cria uma conta que será mostrada na tabela em <em>Firebase Console -&gt; Authentication</em>.</li><li>Se o registro da conta foi feito com sucesso, também armazenamos os dados do usuário no Firebase Firestore (linha 24). Isso é necessário para armazenar informações adicionais do usuário, como nome completo, URL da foto de perfil e assim por diante, que não podem ser armazenadas na tabela de autenticação.</li><li>Se o registro foi feito com sucesso, vamos navegar para a tela de início, também passando os dados do usuário como objeto.</li><li>Se qualquer erro ocorrer, simplesmente mostramos um alerta mostrando o erro. Erros podem acontecer por causa de conexão de rede, senha muito curta, e-mail inválido e assim por diante.</li></ul><p>Recarregue sua aplicação e teste o registro. Se você criou uma conta com sucesso, veja se ela aparece em <em>Firebase Console</em> &nbsp;-&gt; &nbsp;<em>Authentication</em>:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2020/05/1_qy_k5wsgw4MAALmIeBxYpg.png" class="kg-image" alt="1_qy_k5wsgw4MAALmIeBxYpg" width="600" height="400" loading="lazy"></figure><h2 id="6-react-native-com-firebase-login">6. React Native com Firebase  —  login</h2><p>Agora que conseguimos criar as contas, vamos implementar a funcionalidade de login. O SDK do Firebase cuida de todos os passos necessários para que o login tenha autorização e autenticação seguras.</p><p>Abra <em>LoginScreen.js</em>, importe o firebase e complete o método <em><code>onLoginPress</code></em>:</p><pre><code class="language-javascript">//...

import { firebase } from '../../firebase/config'

//...

export default function LoginScreen({navigation}) {

    //...

    const onLoginPress = () =&gt; {
        firebase
            .auth()
            .signInWithEmailAndPassword(email, password)
            .then((response) =&gt; {
                const uid = response.user.uid
                const usersRef = firebase.firestore().collection('users')
                usersRef
                    .doc(uid)
                    .get()
                    .then(firestoreDocument =&gt; {
                        if (!firestoreDocument.exists) {
                            alert("User does not exist anymore.")
                            return;
                        }
                        const user = firestoreDocument.data()
                        navigation.navigate('Home', {user})
                    })
                    .catch(error =&gt; {
                        alert(error)
                    });
            })
            .catch(error =&gt; {
                alert(error)
            })
    }

    //...

}</code></pre><p>Recarregue sua aplicação e faça login com uma conta existente. A aplicação deverá enviar você para a tela de início se as credenciais estiverem corretas, ou mostrará um alerta com um erro, se algo der errado.</p><h2 id="7-persist-ncia-de-credenciais-de-login">7. Persistência de credenciais de login</h2><p>Você verá que, se sair da aplicação e abri-la novamente, ela mostrará a tela de login de novo. Para uma boa experiência do usuário, queremos redirecionar todos os usuários para a tela de início. Ninguém quer digitar suas credenciais de login toda vez que quiser usar a aplicação.</p><p>Isso também é conhecido como persistência de login. Felizmente, o SDK do Firebase cuida disso para nós, lidando com todas as questões de segurança. A persistência de login está habilitada por padrão no Firebase. Então, tudo que precisamos fazer é buscar pelo usuário atual que fez login.</p><p>Abra o arquivo <em>App.js</em> e vamos implementar a funcionalidade de persistência de login:</p><pre><code class="language-javascript">//...

import { firebase } from './src/firebase/config'

//...

export default function App() {

  //...

  if (loading) {	
    return (	
      &lt;&gt;&lt;/&gt;	
    )	
  }

  useEffect(() =&gt; {
    const usersRef = firebase.firestore().collection('users');
    firebase.auth().onAuthStateChanged(user =&gt; {
      if (user) {
        usersRef
          .doc(user.uid)
          .get()
          .then((document) =&gt; {
            const userData = document.data()
            setLoading(false)
            setUser(userData)
          })
          .catch((error) =&gt; {
            setLoading(false)
          });
      } else {
        setLoading(false)
      }
    });
  }, []);

  //...

}</code></pre><p><em>onAuthStateChanged</em> retorna o usuário atual que fez login. Então, procuramos toda a informação adicional que armazenamos no Firebase e a indicamos no estado atual do componente. Isso renderizará a aplicação novamente, o que mostrará a tela de início.</p><p>Note que, como usamos a função pela primeira vez, a aplicação carregou utilizando o hook <a href="https://reactjs.org/docs/hooks-effect.html">useEffect</a>.</p><h2 id="8-escrita-e-leitura-de-dados-a-partir-do-firebase-firestore">8. Escrita e leitura de dados a partir do Firebase Firestore</h2><p>Já usamos o Firebase acima, para salvar informações adicionais sobre nossos usuários (o nome completo). Nesta seção, vamos ver como podemos escrever dados no Firebase e como podemos buscá-los.</p><p>Vamos compreender como observar (ouvir) mudanças na coleção do Firebase e refleti-las na tela, em tempo real. Isso pode ser muito útil em aplicações de tempo real, como o <a href="https://www.instamobile.io/app-templates/video-chat-app-in-react-native/">React Native Chat</a>.</p><p>Para simplificar, vamos salvar alguns itens textuais na coleção do Firestore chamada "entities" (entidades). Pense nesses itens como se fossem tarefas, postagens, tweets, qualquer coisa. Vamos criar um arquivo simples, que adiciona uma nova entidade, e vamos também listar todas as entidades que pertencem ao usuário atual que fez login. Além disso, a lista será atualizada em tempo real.</p><ul><li>Implemente <em>HomeScreen.js</em> reescrevendo-o com o código abaixo</li></ul><pre><code class="language-javascript">import React, { useEffect, useState } from 'react'
import { FlatList, Keyboard, Text, TextInput, TouchableOpacity, View } from 'react-native'
import styles from './styles';
import { firebase } from '../../firebase/config'

export default function HomeScreen(props) {

    const [entityText, setEntityText] = useState('')
    const [entities, setEntities] = useState([])

    const entityRef = firebase.firestore().collection('entities')
    const userID = props.extraData.id

    useEffect(() =&gt; {
        entityRef
            .where("authorID", "==", userID)
            .orderBy('createdAt', 'desc')
            .onSnapshot(
                querySnapshot =&gt; {
                    const newEntities = []
                    querySnapshot.forEach(doc =&gt; {
                        const entity = doc.data()
                        entity.id = doc.id
                        newEntities.push(entity)
                    });
                    setEntities(newEntities)
                },
                error =&gt; {
                    console.log(error)
                }
            )
    }, [])

    const onAddButtonPress = () =&gt; {
        if (entityText &amp;&amp; entityText.length &gt; 0) {
            const timestamp = firebase.firestore.FieldValue.serverTimestamp();
            const data = {
                text: entityText,
                authorID: userID,
                createdAt: timestamp,
            };
            entityRef
                .add(data)
                .then(_doc =&gt; {
                    setEntityText('')
                    Keyboard.dismiss()
                })
                .catch((error) =&gt; {
                    alert(error)
                });
        }
    }

    const renderEntity = ({item, index}) =&gt; {
        return (
            &lt;View style={styles.entityContainer}&gt;
                &lt;Text style={styles.entityText}&gt;
                    {index}. {item.text}
                &lt;/Text&gt;
            &lt;/View&gt;
        )
    }

    return (
        &lt;View style={styles.container}&gt;
            &lt;View style={styles.formContainer}&gt;
                &lt;TextInput
                    style={styles.input}
                    placeholder='Add new entity'
                    placeholderTextColor="#aaaaaa"
                    onChangeText={(text) =&gt; setEntityText(text)}
                    value={entityText}
                    underlineColorAndroid="transparent"
                    autoCapitalize="none"
                /&gt;
                &lt;TouchableOpacity style={styles.button} onPress={onAddButtonPress}&gt;
                    &lt;Text style={styles.buttonText}&gt;Add&lt;/Text&gt;
                &lt;/TouchableOpacity&gt;
            &lt;/View&gt;
            { entities &amp;&amp; (
                &lt;View style={styles.listContainer}&gt;
                    &lt;FlatList
                        data={entities}
                        renderItem={renderEntity}
                        keyExtractor={(item) =&gt; item.id}
                        removeClippedSubviews={true}
                    /&gt;
                &lt;/View&gt;
            )}
        &lt;/View&gt;
    )
}</code></pre><ul><li>Estilize a tela inicial, sobrescrevendo <em>HomeScreen/styles.js </em>com:</li></ul><pre><code class="language-javascript">import { StyleSheet } from 'react-native';

export default StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center'
    },
    formContainer: {
        flexDirection: 'row',
        height: 80,
        marginTop: 40,
        marginBottom: 20,
        flex: 1,
        paddingTop: 10,
        paddingBottom: 10,
        paddingLeft: 30,
        paddingRight: 30,
        justifyContent: 'center',
        alignItems: 'center'
    },
    input: {
        height: 48,
        borderRadius: 5,
        overflow: 'hidden',
        backgroundColor: 'white',
        paddingLeft: 16,
        flex: 1,
        marginRight: 5
    },
    button: {
        height: 47,
        borderRadius: 5,
        backgroundColor: '#788eec',
        width: 80,
        alignItems: "center",
        justifyContent: 'center'
    },
    buttonText: {
        color: 'white',
        fontSize: 16
    },
    listContainer: {
        marginTop: 20,
        padding: 20,
    },
    entityContainer: {
        marginTop: 16,
        borderBottomColor: '#cccccc',
        borderBottomWidth: 1,
        paddingBottom: 16
    },
    entityText: {
        fontSize: 20,
        color: '#333333'
    }
})</code></pre><ul><li>Recarregue a aplicação e observe a nova tela inicial. Digite algo e pressione o botão <em>Add.</em></li><li>Nada acontece.</li><li>Crie um índice nas entidades da coleção do Firestore</li></ul><p>Você verá que a lista de entidades não foi renderizada. Se conferirmos os registros, veremos um aviso sobre "a busca precisar de um índice", seguido de um grande URL:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1_bfOrtReOOo9B_pDR4_Zm9w.png" class="kg-image" alt="1_bfOrtReOOo9B_pDR4_Zm9w" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/1_bfOrtReOOo9B_pDR4_Zm9w.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1_bfOrtReOOo9B_pDR4_Zm9w.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>Isso nos informa que não podemos buscar tabelas de entidades pelo <em>authorID</em> e classificar os dados por <em>createdAt</em> em ordem decrescente, a menos que criemos um índice. Criar um índice é bem fácil, na verdade—simplesmente clique no URL e, então, clique no botão:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1_72kARyPWnDypbCko7e4U1Q.png" class="kg-image" alt="1_72kARyPWnDypbCko7e4U1Q" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/1_72kARyPWnDypbCko7e4U1Q.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1_72kARyPWnDypbCko7e4U1Q.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><ul><li>Recarregue a aplicação novamente</li></ul><p>Agora, tudo funciona como o esperado:</p><ul><li>A aplicação lista todas as entidades na coleção entities, em ordem decrescente de acordo com a criação</li><li>Adicionar uma nova entidade funciona</li><li>A lista atualiza em tempo real (tente apagar um registro diretamente do banco de dados ou adicionar um novo diretamente da aplicação)</li></ul><p>Seu banco de dados do Firestore, agora, fica assim:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1_zPT7lLNr6kvtdazgN50eKg.png" class="kg-image" alt="1_zPT7lLNr6kvtdazgN50eKg" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/1_zPT7lLNr6kvtdazgN50eKg.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/1_zPT7lLNr6kvtdazgN50eKg.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><p>É assim que você lê e escreve no Firestore em React Native. Vamos para a última seção.</p><p>Brinque com a aplicação, adicionando novas entidades. Este é o projeto final:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/09/react-native-firebase-2.png" class="kg-image" alt="react-native-firebase-2" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/09/react-native-firebase-2.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/09/react-native-firebase-2.png 800w" sizes="(min-width: 720px) 720px" width="600" height="400" loading="lazy"></figure><h2 id="conclus-o"><strong>Conclusão</strong></h2><p>O Firebase facilita o suporte para autenticação e banco de dados para qualquer aplicação em React Native. O SDK do Firebase é extremamente poderoso, suporta vários padrões de leitura e escrita em bancos de dados.</p><p>Além do React Native, o SDK do Firebase providencia suporte para várias outras linguagens, como <a href="https://www.iosapptemplates.com/blog/swift-programming/firebase-swift-tutorial-login-registration-ios">Swift</a>, &nbsp;<a href="https://www.instakotlin.com/templates/android-starter-kit-with-firebase/">Kotlin</a> ou <a href="https://www.instaflutter.com/app-templates/flutter-login-screen/">Flutter</a>. Confira esses links para ver instruções para os iniciantes no Firebase em várias linguagens.</p><p>Mostramos o básico neste tutorial de React Native com Firebase. Nos próximos, vamos abranger mais funcionalidades avançadas, como Firebase Storage (carregamento de arquivos) e notificações por push.</p><p>Se você gostou deste tutorial, dê uma estrela no <a href="https://github.com/instamobile/react-native-firebase">repositório do GitHub</a> e compartilhe este artigo com sua comunidade. Você pode conferir muitos <a href="https://www.instamobile.io/mobile-templates/react-native-templates-free/">projetos gratuitos em React Native</a> no Instamobile. Abraços!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Como fazer sua aplicação em React Native responder normalmente quando o teclado aparecer ]]>
                </title>
                <description>
                    <![CDATA[ por Spencer Carli Quando você está trabalhando com aplicações do React Native, um problema comum é que o teclado aparecerá e ocultará as entradas de texto quando você focar nelas. Algo assim: Existem algumas maneiras de evitar isso. Algumas são simples, outras nem tanto. Algumas podem ser personalizadas. Outras, não. ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/como-fazer-sua-aplicacao-em-react-native-responder-normalmente-quando-o-teclado-aparecer/</link>
                <guid isPermaLink="false">62ecf8bdfea2f10707d6a5d2</guid>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Paula Flávia Pagotto Simionato ]]>
                </dc:creator>
                <pubDate>Thu, 08 Sep 2022 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2022/08/1_gQEm5r-73VpwmSrHYRi0AQ.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/how-to-make-your-react-native-app-respond-gracefully-when-the-keyboard-pops-up-7442c1535580/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to make your React Native app respond gracefully when the keyboard pops up</a>
      </p><p>por Spencer Carli</p><p>Quando você está trabalhando com aplicações do React Native, um problema comum é que o teclado aparecerá e ocultará as entradas de texto quando você focar nelas. Algo assim:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/08/1_dcFgfha_NfuPIi4YqEnsmQ.gif" class="kg-image" alt="1_dcFgfha_NfuPIi4YqEnsmQ" width="368" height="674" loading="lazy"></figure><p>Existem algumas maneiras de evitar isso. Algumas são simples, outras nem tanto. Algumas podem ser personalizadas. Outras, não. Hoje, vou mostrar três maneiras diferentes de evitar o teclado no React Native.</p><blockquote>Eu coloquei todo o código-fonte para este tutorial <a href="https://github.com/spencercarli/react-native-keyboard-avoidance-examples">no Github</a>.</blockquote><h4 id="keyboardavoidingview"><strong><strong>KeyboardAvoidingView</strong></strong></h4><p>A solução mais simples e mais fácil de instalar é o <a href="https://facebook.github.io/react-native/docs/keyboardavoidingview.html">KeyboardAvoidingView</a>. É um componente central, mas também é bastante simples no que faz.</p><p>Você pode pegar o <a href="https://gist.github.com/spencercarli/8acb7208090f759b0fc2fda3394796f1">código de base</a>, que tem o teclado cobrindo as entradas, e atualizá-lo para que as entradas não sejam mais cobertas. A primeira coisa que você precisa fazer é substituir o contêiner <code>View</code> pelo <code>KeyboardAvoidingView</code> e, em seguida, adicionar uma prop <code>behavior</code> a ele. Se você olhar a documentação, verá que ela aceita três valores diferentes – altura, preenchimento, posição. Descobri que o preenchimento funciona da maneira mais previsível. Então, é isso que eu vou usar.</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">import React from 'react';
import { View, TextInput, Image, KeyboardAvoidingView } from 'react-native';
import styles from './styles';
import logo from './logo.png';

const Demo = () =&gt; {
  return (
    &lt;KeyboardAvoidingView
      style={styles.container}
      behavior="padding"
    &gt;
      &lt;Image source={logo} style={styles.logo} /&gt;
      &lt;TextInput
        placeholder="Email"
        style={styles.input}
      /&gt;
      &lt;TextInput
        placeholder="Username"
        style={styles.input}
      /&gt;
      &lt;TextInput
        placeholder="Password"
        style={styles.input}
      /&gt;
      &lt;TextInput
        placeholder="Confirm Password"
        style={styles.input}
      /&gt;
      &lt;View style={{ height: 60 }} /&gt;
    &lt;/KeyboardAvoidingView&gt;
  );
};

export default Demo;</code></pre><figcaption>KeyboardAvoidingView.js</figcaption></figure><p>Isso nos dá o resultado que se vê abaixo. Não é perfeito, mas pelo pouquíssimo trabalho que dá, é muito bom.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/08/1_YrvCTP6RN8zn7r7W1lJtuQ.gif" class="kg-image" alt="1_YrvCTP6RN8zn7r7W1lJtuQ" width="368" height="674" loading="lazy"></figure><p>Uma coisa a ser notada é que, na linha 30, você verá uma <code>View</code> que tem uma altura definida como 60px. Descobri que a Key Avoiding View não funciona com o último elemento e a configuração de preenchimento e margem (<em>padding</em> e <em>margin</em>, em inglês) não funcionou. Então, eu adicionei um novo elemento para "aumentar" tudo em alguns pixels.</p><p>A imagem na parte superior é empurrada para fora da visualização ao usar essa implementação simples. Eu vou mostrar como você pode consertar isso no final.</p><blockquote>Usuários do Android: descobri que essa é a melhor/única opção. Ao adicionar <code>android:windowSoftInputMode="adjustResize"</code> ao seu AndroidManifest.xml, o sistema operacional cuidará da maior parte do trabalho para você e o KeyboardAvoidingView cuidará do resto (<a href="https://gist.github.com/spencercarli/e1b9575c1c8845c2c20b86415dfba3db#file-androidmanifest-xml-L23">exemplo de AndroidManifest.xml</a>). O restante deste artigo provavelmente não se aplicará a você.</blockquote><h4 id="keyboard-aware-scrollview"><strong><strong>Keyboard Aware ScrollView</strong></strong></h4><p>A próxima opção é a <a href="https://github.com/APSL/react-native-keyboard-aware-scroll-view">react-native-keyboard-aware-scroll-view</a>, que oferece muito retorno pelo seu investimento. Nos bastidores, você estará usando ScrollView ou ListView para lidar com tudo (dependendo do componente que você escolher), o que torna a interação de rolagem bastante perfeita. O outro grande benefício desse pacote é que ele rolará para a entrada que está em foco, o que proporciona ao usuário uma experiência agradável.</p><p>O uso também é muito fácil — você só precisa trocar o contêiner <code>View</code>, começando novamente com o <a href="https://gist.github.com/spencercarli/8acb7208090f759b0fc2fda3394796f1">código de base</a>, e definir algumas opções. Aqui está o código, então eu vou descrevê-lo.</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">import React from 'react';
import { View, TextInput, Image } from 'react-native';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'
import styles from './styles';
import logo from './logo.png';

const Demo = () =&gt; {
  return (
    &lt;KeyboardAwareScrollView
      style={{ backgroundColor: '#4c69a5' }}
      resetScrollToCoords={{ x: 0, y: 0 }}
      contentContainerStyle={styles.container}
      scrollEnabled={false}
    &gt;
        &lt;Image source={logo} style={styles.logo} /&gt;
        &lt;TextInput
          placeholder="Email"
          style={styles.input}
        /&gt;
        &lt;TextInput
          placeholder="Username"
          style={styles.input}
        /&gt;
        &lt;TextInput
          placeholder="Password"
          style={styles.input}
        /&gt;
        &lt;TextInput
          placeholder="Confirm Password"
          style={styles.input}
        /&gt;
    &lt;/KeyboardAwareScrollView&gt;
  );
};

export default Demo;</code></pre><figcaption>KeyboardAwareScrollView.js</figcaption></figure><p>Primeiro, você deve definir a <em>backgroundColor</em> do ScrollView. Dessa maneira (como se você fosse reativar a rolagem), a <em>backgroundColor</em> será sempre a mesma. Em seguida, você deve dizer ao componente onde está a posição padrão para que, uma vez que o teclado seja fechado, ele volte a esse ponto - omitindo esse suporte, a visualização deve ficar presa no topo depois de fechar o teclado, assim.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/08/1_WzOzG3P9npDpHpFj896nXA.png" class="kg-image" alt="1_WzOzG3P9npDpHpFj896nXA" width="361" height="650" loading="lazy"></figure><p>Após a prop <em>resetScrollToCoords</em>, você deve definir o <em>contentContainerStyle</em> - que, basicamente, substitui os estilos de exibição que você tinha antes. A última coisa que estou fazendo é desabilitar a ScrollView da interação do usuário. Isso pode nem sempre fazer sentido para sua UI (interface do usuário) – como no caso de uma interface em que um usuário edita muitos campos de perfil – mas, para esta, faz muito sentido. O que não faz sentido é permitir que o usuário role manualmente, pois não há para onde rolar.</p><p>Combinando essas props, você obtém o seguinte resultado, que funciona muito bem.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/08/1_M64W128GRs8X2IaBbSv7sA.gif" class="kg-image" alt="1_M64W128GRs8X2IaBbSv7sA" width="368" height="674" loading="lazy"></figure><h4 id="keyboard-module"><strong><strong>Keyboard Module</strong></strong></h4><p>Esta é, de longe, a opção mais manual, mas é, também, a que dá mais controle. Você usará a biblioteca <em>Animated </em>para ajudar a proporcionar interações suaves, como você viu antes.</p><p>O módulo Keyboard, que não está documentado no site do React Native, permite que você escute eventos de teclado emitidos pelo dispositivo. Os eventos que você usará são <em>keyboardWillShow</em> e <em>keyboardWillHide</em>, que retornam o tempo de duração da animação e a posição final do teclado (entre outras informações).</p><blockquote>Se você estiver no Android, convém usar keyboardDidShow e o keyboardDidHide.</blockquote><p>Quando o evento <em>keyboardWillShow</em> for emitido, você definirá uma variável <em>animated</em> para a altura final do teclado e fará com que ela seja animada pela mesma duração da animação de rolagem do teclado. Em seguida, você usa esse valor de <em>animated</em> para definir o preenchimento na parte inferior do contêiner para aumentar todo o conteúdo.</p><p>Mostrarei o código em um momento, mas fazer o que descrevi acima nos deixa com a seguinte experiência.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/08/1_mOhomWU9OwZN8Kieq3Pezw.gif" class="kg-image" alt="1_mOhomWU9OwZN8Kieq3Pezw" width="368" height="674" loading="lazy"></figure><p>Eu quero consertar essa imagem desta vez. Para isso, você usará um valor animado para gerenciar a altura da imagem, que você ajustará quando o teclado for aberto. Aqui está o código.</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">import React, { Component } from 'react';
import { View, TextInput, Image, Animated, Keyboard } from 'react-native';
import styles, { IMAGE_HEIGHT, IMAGE_HEIGHT_SMALL} from './styles';
import logo from './logo.png';

class Demo extends Component {
  constructor(props) {
    super(props);

    this.keyboardHeight = new Animated.Value(0);
    this.imageHeight = new Animated.Value(IMAGE_HEIGHT);
  }

  componentWillMount () {
    this.keyboardWillShowSub = Keyboard.addListener('keyboardWillShow', this.keyboardWillShow);
    this.keyboardWillHideSub = Keyboard.addListener('keyboardWillHide', this.keyboardWillHide);
  }

  componentWillUnmount() {
    this.keyboardWillShowSub.remove();
    this.keyboardWillHideSub.remove();
  }

  keyboardWillShow = (event) =&gt; {
    Animated.parallel([
      Animated.timing(this.keyboardHeight, {
        duration: event.duration,
        toValue: event.endCoordinates.height,
      }),
      Animated.timing(this.imageHeight, {
        duration: event.duration,
        toValue: IMAGE_HEIGHT_SMALL,
      }),
    ]).start();
  };

  keyboardWillHide = (event) =&gt; {
    Animated.parallel([
      Animated.timing(this.keyboardHeight, {
        duration: event.duration,
        toValue: 0,
      }),
      Animated.timing(this.imageHeight, {
        duration: event.duration,
        toValue: IMAGE_HEIGHT,
      }),
    ]).start();
  };

  render() {
    return (
      &lt;Animated.View style={[styles.container, { paddingBottom: this.keyboardHeight }]}&gt;
        &lt;Animated.Image source={logo} style={[styles.logo, { height: this.imageHeight }]} /&gt;
        &lt;TextInput
          placeholder="Email"
          style={styles.input}
        /&gt;
        &lt;TextInput
          placeholder="Username"
          style={styles.input}
        /&gt;
        &lt;TextInput
          placeholder="Password"
          style={styles.input}
        /&gt;
        &lt;TextInput
          placeholder="Confirm Password"
          style={styles.input}
        /&gt;
      &lt;/Animated.View&gt;
    );
  }
};

export default Demo;</code></pre><figcaption>KeyboardModule.js</figcaption></figure><p>Certamente, há muito mais aqui do que nas outras soluções. Em vez de uma <code>View</code> ou <code>Image</code>, você está usando <code>Animated.View</code> e <code>Animated.Image</code> para que os valores de <em>animated</em> possam ser aproveitados. A parte divertida está realmente nas funções <em>keyboardWillShow</em> e <em>keyboardWillHide,</em> onde os valores de <em>animated</em> estão mudando.</p><p>O que está acontecendo é que os dois valores de <em>animated</em> estão mudando em paralelo, os quais estão sendo usados para orientar a interface do usuário. Isso deixa você com o resultado abaixo.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/08/1_Fj87SXCLXlkKsG7aAi_5mg.gif" class="kg-image" alt="1_Fj87SXCLXlkKsG7aAi_5mg" width="368" height="674" loading="lazy"></figure><p>É uma quantidade razoável de código, mas fica muito bom. Você tem muitas opções para o que pode fazer e pode realmente personalizar a interação para o conteúdo do seu coração.</p><h4 id="combinando-op-es">Combinando opções</h4><p>Se você quiser diminuir um pouco o código, pode combinar algumas opções, que é o que costumo fazer. Por exemplo, combinando a primeira e a terceira opções, você precisa apenas se preocupar em gerenciar e animar a altura da imagem. </p><p>O código não é muito menor do que a fonte da terceira opção, mas à medida que uma interface do usuário cresce em complexidade, ele pode ajudá-lo um pouco mais.</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">import React, { Component } from 'react';
import { View, TextInput, Image, Animated, Keyboard, KeyboardAvoidingView } from 'react-native';
import styles, { IMAGE_HEIGHT, IMAGE_HEIGHT_SMALL } from './styles';
import logo from './logo.png';

class Demo extends Component {
  constructor(props) {
    super(props);

    this.imageHeight = new Animated.Value(IMAGE_HEIGHT);
  }

  componentWillMount () {
    this.keyboardWillShowSub = Keyboard.addListener('keyboardWillShow', this.keyboardWillShow);
    this.keyboardWillHideSub = Keyboard.addListener('keyboardWillHide', this.keyboardWillHide);
  }

  componentWillUnmount() {
    this.keyboardWillShowSub.remove();
    this.keyboardWillHideSub.remove();
  }

  keyboardWillShow = (event) =&gt; {
    Animated.timing(this.imageHeight, {
      duration: event.duration,
      toValue: IMAGE_HEIGHT_SMALL,
    }).start();
  };

  keyboardWillHide = (event) =&gt; {
    Animated.timing(this.imageHeight, {
      duration: event.duration,
      toValue: IMAGE_HEIGHT,
    }).start();
  };

  render() {
    return (
      &lt;KeyboardAvoidingView
        style={styles.container}
        behavior="padding"
      &gt;
          &lt;Animated.Image source={logo} style={[styles.logo, { height: this.imageHeight }]} /&gt;
          &lt;TextInput
            placeholder="Email"
            style={styles.input}
          /&gt;
          &lt;TextInput
            placeholder="Username"
            style={styles.input}
          /&gt;
          &lt;TextInput
            placeholder="Password"
            style={styles.input}
          /&gt;
          &lt;TextInput
            placeholder="Confirm Password"
            style={styles.input}
          /&gt;
      &lt;/KeyboardAvoidingView&gt;
    );
  }
};

export default Demo;</code></pre><figcaption>Combo.js</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/08/1_g3clh5FFPJzBWt9egIY2cA.gif" class="kg-image" alt="1_g3clh5FFPJzBWt9egIY2cA" width="368" height="674" loading="lazy"></figure><p>Cada uma dessas implementações tem seus prós e contras – você terá que escolher a mais apropriada, de acordo com a experiência do usuário que deseja</p><blockquote>Quer aprender mais sobre como usar o React Native para criar aplicações para dispositivos móveis de alta qualidade? <a href="http://learn.handlebarlabs.com/p/react-native-basics-build-a-currency-converter">Inscreva-se no curso de React Native gratuito do autor</a>!</blockquote> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
