<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Richard Rosko</title>
    <description>The latest articles on DEV Community by Richard Rosko (@nuallian).</description>
    <link>https://dev.to/nuallian</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F167391%2F843aa512-1438-4f8e-907f-078338f0f3bb.png</url>
      <title>DEV Community: Richard Rosko</title>
      <link>https://dev.to/nuallian</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nuallian"/>
    <language>en</language>
    <item>
      <title>Setting up an infrastructure for a monorepo on Render</title>
      <dc:creator>Richard Rosko</dc:creator>
      <pubDate>Fri, 08 May 2020 07:58:23 +0000</pubDate>
      <link>https://dev.to/sudolabs_io/setting-up-an-infrastructure-for-a-monorepo-on-render-42ni</link>
      <guid>https://dev.to/sudolabs_io/setting-up-an-infrastructure-for-a-monorepo-on-render-42ni</guid>
      <description>&lt;p&gt;I feel that DevOps is something that has not yet been solved and all the existing providers (AWS, GCP, Azure) leave much to be desired. That is why every time we are starting a new project, I always do extensive research on existing solutions and new players on the market. At the beginning of 2020, we were, once again, in a situation where we had to research and pick a provider for a new project we started working on. During that research, we stumbled upon Render.&lt;/p&gt;

&lt;p&gt;We were looking for a quick setup and wanted to spend less than a full day on infrastructure. That is why we were looking for something simple, fast and reliable. We decided to give Render a try and knew that there was always the option to fall back to AWS. Render is a fairly new cloud provider you might have never heard of. They have launched in 2019 and won the &lt;a href="https://techcrunch.com/2019/10/04/and-the-winner-of-startup-battlefield-at-disrupt-sf-2019-is-render/"&gt;TechCrunch Disrupt&lt;/a&gt; that year. They have a lot going for them.&lt;/p&gt;

&lt;p&gt;I'd like to first talk about the infrastructure of our app, so you can see what moving parts we wanted to have. We will also take a look at all that Render has to offer and see how we managed to utilize it in our project. Lastly, I'd like to talk about some shortcomings and take a look at what Render can not help you with (yet, since they are adding new features all the time).&lt;/p&gt;

&lt;h2&gt;
  
  
  Our infrastructure and Render
&lt;/h2&gt;

&lt;p&gt;We are building a travel platform for companies. The app that we are building consists of a &lt;strong&gt;GraphQL backend&lt;/strong&gt;, combined with a &lt;strong&gt;Postgres database&lt;/strong&gt; for data persistence. On the frontend, we have a user-facing &lt;strong&gt;React application&lt;/strong&gt; that uses Apollo for communicating with our backend. We will also have a standalone &lt;strong&gt;Node&lt;/strong&gt; application that is doing &lt;a href="https://www.stitchdata.com/resources/what-is-elt/"&gt;ELT&lt;/a&gt; for us. This background application also has its own &lt;strong&gt;Postgres&lt;/strong&gt; database. We will also host a static landing page, that will be built with &lt;strong&gt;gatsby.js&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Render has our back on most of the things we will need. But first, let's set up our environment for local development.&lt;br&gt;
For this particular project, we will use a monorepo, which means all of our services will live in one directory and under one repository. Fortunately, it's easy to work with monorepos on Render even though it requires some workarounds. But more on that later.&lt;/p&gt;
&lt;h3&gt;
  
  
  API
&lt;/h3&gt;

&lt;p&gt;On the backend, we will be running our development environment in Docker, since we want to make sure everybody on the team has the same environment. Another advantage here is, that most machines do not come with Postgres pre-installed and even if it did, it might not be the same version. We can avoid a lot of headaches doing it this way. In production on Render, we will not be using Docker (although we could because it is supported). Let's spin up two services in our Docker with this &lt;code&gt;docker-compose.yml&lt;/code&gt; in our &lt;code&gt;api&lt;/code&gt; project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3"&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nextretreat_dev"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db-volume:/var/lib/postgresql/data&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3001:3001"&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.:/home/app/&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/home/app/node_modules&lt;/span&gt;
&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="na"&gt;db-volume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Our Dockerfile will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:12.14.1-alpine&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3001&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /home/app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json /home/app/&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package-lock.json /home/app/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /home/app&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["npm", "run", "start:dev"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is a pretty standard configuration if you're used to working with Docker, but there is one thing to keep in mind that is specific to Render and that is the way of specifying &lt;code&gt;npm&lt;/code&gt; version. Locally, it's always a good idea to have an &lt;code&gt;.nvmrc&lt;/code&gt; file that will help the developers on the team to use the same &lt;code&gt;npm&lt;/code&gt; version. In order to let Render know what version it should use, we need to add a &lt;code&gt;.node-version&lt;/code&gt; file in the root of the repository. For this project we are using &lt;code&gt;12.4.1&lt;/code&gt;, so the only thing you need to do is paste that in the &lt;code&gt;.node-version&lt;/code&gt; file. Every time a service is built / re-built on Render servers, it reads the file and uses that for &lt;code&gt;npm&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Long-running service
&lt;/h3&gt;

&lt;p&gt;Next up is our ELT Node service. It will live in our monorepo, in a directory called &lt;code&gt;data-service&lt;/code&gt;. It is a simple app with an &lt;code&gt;index.js&lt;/code&gt; file in the root of the directory that will manage the extraction and loading of the data into our warehouse. As we mentioned before, it has its own database that it stores the information in, so we will once again use Docker for that. We will re-use our docker configuration from our &lt;code&gt;api&lt;/code&gt; service. There are only a couple of things we will change here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We have to use a different port on our computer (the first one of the &lt;code&gt;port:port&lt;/code&gt; directive in &lt;code&gt;docker-compose.yml&lt;/code&gt;) because that would prevent us from running both &lt;code&gt;api&lt;/code&gt; and &lt;code&gt;data-service&lt;/code&gt; at the same time. Let's change it &lt;code&gt;5433:5432&lt;/code&gt; instead of &lt;code&gt;5432:5432&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We can remove the EXPOSE 3001 from our &lt;code&gt;Dockerfile&lt;/code&gt;, since this app does not require it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For these kinds of long-running services, you would most likely want to leverage some sort of restart-on-error tool, like forever, or pm2. But we will leave all of this up to Render and its Background Worker service. The start command for this service is a simple &lt;code&gt;node index.js&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static site
&lt;/h3&gt;

&lt;p&gt;For our static site we will be using Gatsby, which is an awesome tool for building static applications. We will use a simple template, add in our code for the landing page in the &lt;code&gt;landing-page&lt;/code&gt; directory and specify the build command as &lt;code&gt;gatsby build&lt;/code&gt;. Not much else to do here.&lt;/p&gt;

&lt;h3&gt;
  
  
  User-facing client
&lt;/h3&gt;

&lt;p&gt;The last app in our repository is the web client. Following the super simple documentation, we will create and move into our &lt;code&gt;web-client&lt;/code&gt; directory in the monorepo and scaffold our application using &lt;code&gt;npx create-react-app my-app&lt;/code&gt;. We will specify two main scripts for this app. For local development, we will have a &lt;code&gt;react-scripts start&lt;/code&gt; command and the build command will be &lt;code&gt;react-scripts build&lt;/code&gt;. Super easy. Now we can start developing our app as a regular CRA app.&lt;/p&gt;

&lt;p&gt;The only thing left to do for now is to &lt;code&gt;git push&lt;/code&gt; this project to Github (or another git provider).&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Render
&lt;/h2&gt;

&lt;p&gt;We now have our monorepo ready with all the services we will be using locally.&lt;br&gt;
Let's recreate our services on Render for the production environment and hook it all up. After creating an account and linking it to our github repository we are presented with a plethora of services we can choose from. For this project, we will not be using Docker in production and this is still going to be extremely easy to set up. We are going to start with databases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Databases
&lt;/h3&gt;

&lt;p&gt;As of writing this article, Render only supports one type of database and that is Postgres. Fortunately, that is exactly what we want to use in this case anyway. Setting up a database is very easy, we just head to the Databases section and create a new database. If your database increases in size during later stages, no worries, you can easily scale it up with a click of a button. Scaling down, however, is not supported yet, so make sure you pick right at this point so that you won't pay for something you will not end up using. We will create 2 databases for now, one for the &lt;code&gt;api&lt;/code&gt; and one for our &lt;code&gt;data-service&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When you click on a detail of an existing database you can see a pair of connection strings. It is pretty self-explanatory, but if you are connecting to a database from within a Render-hosted service, you use the internal connection string. If you want to connect to the database from outside (GUI app, or a service that is running elsewhere), you use the external connection string.&lt;/p&gt;

&lt;h3&gt;
  
  
  API
&lt;/h3&gt;

&lt;p&gt;Let's navigate to the Services tab and create our &lt;code&gt;api&lt;/code&gt; service. We will be using a Web Service and choose Node as our environment. Next up, we specify the &lt;code&gt;master&lt;/code&gt; branch for the production version of our app (we follow the &lt;a href="https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow"&gt;Git-flow&lt;/a&gt; Workflow).&lt;/p&gt;

&lt;p&gt;Since this project is living inside of a monorepo we have to remember that when it's cloned, it is located in the root of the repository. We therefore need to prepend all our commands with a &lt;code&gt;cd &amp;lt;service-directory&amp;gt;&lt;/code&gt; in order to be in the correct folder. The build command is here to make sure you have any prep work, like installing dependencies, or setting up external configuration ready before you start the service. In our case, it will be: &lt;code&gt;cd api &amp;amp;&amp;amp; npm install&lt;/code&gt;. The start command is &lt;code&gt;cd api &amp;amp;&amp;amp; npm start&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After the service is created, there is only one thing left to do and that is to create our list of production environment variables. For the database connection string, we can just copy the internal connection string and, voilà, our &lt;code&gt;api&lt;/code&gt; service is hooked up to our database. What's more, if you have more services that will use the same environment variables you can also create environment groups and assign those to different services here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Long-running service
&lt;/h3&gt;

&lt;p&gt;For our long-running service, we will return to the Services tab and create a New Background Worker. As a sidenote, background worker is ideal for processes like this one. They need to run indefinitely and do not expose a port, whereas web services are meant to be accessed by the outside world. We will once again opt-in for the Node environment and specify the &lt;code&gt;master&lt;/code&gt; branch for building. Our build command is: &lt;code&gt;cd data-service &amp;amp;&amp;amp; npm install&lt;/code&gt;. Our start command is: &lt;code&gt;cd data-service &amp;amp;&amp;amp; npm start&lt;/code&gt;. You can also scale up all of your services horizontally by running multiple instances of that service. This might be useful for a data acquisition service like this one, but let's leave it on 1 for now and see what we will require in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static site and user-facing client
&lt;/h3&gt;

&lt;p&gt;Setting up static sites is extremely straight forward and if you want to try Render out, your first static site is even free of charge.&lt;br&gt;
For our landing page, we will select Static Site as our environment when creating this service and make &lt;code&gt;cd landing-page &amp;amp;&amp;amp; npm install &amp;amp;&amp;amp; npx run gatsby build&lt;/code&gt; our build command. We specify our publish directory to be &lt;code&gt;./landing-page&lt;/code&gt; as instructed in our template.&lt;/p&gt;

&lt;p&gt;In order to deploy our &lt;code&gt;web-client&lt;/code&gt;, we create another Static Site and make our build command &lt;code&gt;cd web-client &amp;amp;&amp;amp; npm install &amp;amp;&amp;amp; npm run build&lt;/code&gt;. The publish directory will be &lt;code&gt;./web-client/build&lt;/code&gt;, since this is a CRA app.&lt;/p&gt;

&lt;p&gt;After all of this, we can kick back and relax, because we are now running all our services in the cloud on Render. Everything is hooked up, and we can turn on auto deploys if we choose to. This will make sure, that every time something is pushed to our repository, on the specified &lt;code&gt;master&lt;/code&gt; branch, our services get updated and are re-built with the newest additions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shortcomings of Render
&lt;/h2&gt;

&lt;p&gt;At the time of writing this article, Render doesn't currently support CDNs and object storage, whereas something like AWS along with S3 has these capabilities. For now, it is a disadvantage, because we have to use another service for our CDN and object storage.&lt;/p&gt;

&lt;p&gt;It also doesn't have real support for monorepos. If you do it the way I described, every time you push something to any service in your repository, the hook registers the command on all the other services you have and rebuilds everything. This might not be ideal, but it works and is not that bad.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We usually use AWS on larger projects and my main beef with Amazon is, that it is very complicated to set up. Render on the other hand (kind of like Heroku, or Digital Ocean), has preexisting services that are super easy to set up and scale well at the same time. Although there were inquiries from the community, they do not plan to open source the configurations for their services, because they believe that it would defeat the purpose. It would go against the one-click setup functionality, and I have to say I am with them on this one. This is what makes Render special and so easy to use.&lt;br&gt;
For us, it met the requirements we had for it, as we've been able to easily set up this infrastructure in less than a day. That was what we initially wanted to achieve and Render delivered.&lt;/p&gt;

&lt;p&gt;Even though it is missing some services and features, the team is very active in delivering new features. While the documentation is pretty complete, some edge cases are not covered and since Render is still pretty new, the internet might be short on answers. But the community is super helpful and the Slack channel is bustling. Whenever I had an issue, a team member always reached out and helped me with whatever I was dealing with.&lt;/p&gt;

&lt;p&gt;This post was originally published on &lt;a href="https://sudolabs.io/blog/setting-up-an-infrastructure-for-a-monorepo-on-render"&gt;sudolabs.io's blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>render</category>
      <category>gatsby</category>
      <category>react</category>
      <category>devops</category>
    </item>
    <item>
      <title>React Native Navigation and its caveats</title>
      <dc:creator>Richard Rosko</dc:creator>
      <pubDate>Tue, 14 May 2019 12:48:41 +0000</pubDate>
      <link>https://dev.to/sudolabs_io/react-native-navigation-and-its-caveats-1249</link>
      <guid>https://dev.to/sudolabs_io/react-native-navigation-and-its-caveats-1249</guid>
      <description>&lt;p&gt;So you went out on a journey to create a &lt;code&gt;react-native&lt;/code&gt; application and you feel like you have superpowers. You create your components, style them, make API calls just like you do on the web and you're practically walking on sunshine.&lt;/p&gt;

&lt;p&gt;But then you want to implement navigation and the world starts crumbling around you. You try out the navigation that comes pre-packaged in React Native, but it's not cross-platform consistent. Then you discover a JavaScript solution, but the performance is sub-optimal for most apps. You need a solution that uses native navigation definitions. And then you discover &lt;code&gt;react-native-navigation&lt;/code&gt; (RNN from now on) from Wix and you are saved as it has all you need.&lt;/p&gt;

&lt;p&gt;It is a native solution, that boasts great performance, uses native events on the background and is cross-platform in its true meaning.&lt;/p&gt;

&lt;p&gt;Unfortunately, it has some weird issues and you are once again lost. Do not give up hope yet though! Rather than that, let's walk through the breaking points and jot down some notes on how to work with/around those weird issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;v1&lt;/code&gt; VS &lt;code&gt;v2&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The guys over at Wix are working really hard on providing all of us with a native cross-platform solution to navigate in React Native apps - huge kudos to them for maintaining the library. With that being said, the documentation is a bit rough around the edges and sometimes it's hard to find what you are looking for.&lt;/p&gt;

&lt;p&gt;A quick look into the the ecosystem of RNN will reveal, that there are two versions of the library that are currently being maintained - the older &lt;code&gt;v1&lt;/code&gt; and the "brand" new &lt;code&gt;v2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The differences between the two versions are marginal and although there is a &lt;a href="https://github.com/wix-playground/react-native-navigation-v1-v2-adapter" rel="noopener noreferrer"&gt;way&lt;/a&gt; to migrate v1  to v2, it's best to make your mind up before starting a new project.&lt;/p&gt;

&lt;p&gt;The question is, which one should you use for your new React Native project?&lt;/p&gt;

&lt;p&gt;The quick answer is: &lt;code&gt;v2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The long answer is, that both versions are still actively maintained, but &lt;code&gt;v2&lt;/code&gt; has a priority in the development process. And although there are some features, that are not yet implemented in &lt;code&gt;v2&lt;/code&gt;, the team is very active in making that a thing of the past. Also, the official recommendation from Wix is to use &lt;code&gt;v2&lt;/code&gt; in your projects and so, we should stick with what the authors are saying in this case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stacks
&lt;/h2&gt;

&lt;p&gt;This is something you will probably use in any app that uses navigation. A general consensus of what a stack actually is would probably be that is it a collection of screens that are somehow related and, therefore, can be navigated &lt;em&gt;to&lt;/em&gt; and &lt;em&gt;from&lt;/em&gt;. This does not, however, directly translate to how the stacks work in RNN applications.&lt;/p&gt;

&lt;p&gt;In my opinion, it's just an issue with naming here. &lt;code&gt;stack&lt;/code&gt; in RNN simply represents an arbitrary screen, that you can use to navigate to any other arbitrary screen. Don't try to find any deeper meaning in the name of the definition here.&lt;/p&gt;

&lt;p&gt;The way you define a stack in and RNN app is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;screen.Home&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the &lt;code&gt;Home&lt;/code&gt; screen is registered with this definition you can use &lt;code&gt;Navigation.push()&lt;/code&gt; (and all other navigation events) from the &lt;code&gt;Home&lt;/code&gt; screen to &lt;strong&gt;any&lt;/strong&gt; other registered screen. They do not have to be defined in the same &lt;code&gt;stack: {}&lt;/code&gt; in order for those transition to work. This was an issue for me when I started using RNN as it makes little sense to me given the naming. I hope you learn from my mistake and navigate properly with &lt;code&gt;stack&lt;/code&gt; definitions from now on.&lt;/p&gt;

&lt;p&gt;One more word of caution here though - I have seen people who define all of their screens in &lt;code&gt;stacks&lt;/code&gt; to make sure they are able to navigate from them if the need arises. I wouldn't personally do that, because if you define a screen in &lt;code&gt;stack&lt;/code&gt; it naturally adds some overhead code on the native side to your screens that are defined this way and that is not optimal. You are better off paying attention to the definitions of your screens and only define the screens which you will be navigating from with &lt;code&gt;Navigation&lt;/code&gt; events. Such is the will of RNN.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping registered components in Redux (or any other Provider)
&lt;/h2&gt;

&lt;p&gt;Can you use RNN in conjunction with Redux? Yes, you can. But you have to do some prep work to make it possible. You will probably find many different ways to do it if you make a quick Google search, but there is only one official way and that is through the RNN's own API. The only thing you need to do is use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Navigation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerComponentWithRedux&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to register your components. This function accepts exactly three parameters, the first being the component you want to register, the second being the &lt;code&gt;Provider&lt;/code&gt; (&lt;code&gt;import { Provider } from react-redux&lt;/code&gt;) and the third being your custom redux store. In the end, you should have something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;Navigation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerComponentWithRedux&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;screen.Home&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why stop there though? Even though the method is called &lt;code&gt;registerComponentWithRedux&lt;/code&gt;, what it actually does is, it wraps all of the defined components with whatever component you provide it as the second parameter. Therefore, this is the ideal spot to wrap your component with whatever else you need to, like a &lt;code&gt;ThemeProvider&lt;/code&gt;, or, e.g. React's &lt;code&gt;Contexts&lt;/code&gt; if you use those in your app.&lt;/p&gt;

&lt;p&gt;Not only is this the ideal place to wrap your app in any wrappers, but it's probably one of the only places you can do so. Why is that you might ask? Well, you probably already figured it out when you were initializing RNN in your app. The way RNN works is it pre-registers all of your screens ahead of the time for optimization purposes. This is a good thing, but it also unavoidably means, that the entry point of your app changes from being declarative (that's the way, uh huh huh, we like it, uh huh huh) to being imperative.&lt;/p&gt;

&lt;p&gt;React likes it much more, if we use declarative definitions for our codebase (layouts and all). But if you use RNN in your app it's just not possible to do that for the root components of your app. This is my main beef with the library, but that's a topic for another time and at least there is a way to wrap your top-level components, albeit not being the most user-friendly.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;componentId&lt;/code&gt; and making peace with it using &lt;code&gt;React.Context&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;As mentioned in the first article, there are two versions of the library. Let's assume that you are using the preferred &lt;code&gt;v2&lt;/code&gt;. One of the main changes to the API of the library is the presence of &lt;code&gt;componentId&lt;/code&gt; - a unique identifier of any RNN registered component. You have to use it anytime you want to perform a &lt;code&gt;Navigation&lt;/code&gt; event (e.g. &lt;code&gt;.push()&lt;/code&gt;, &lt;code&gt;.pop()&lt;/code&gt;) and each root component that is registered in the initialization step of an RNN app receives it as a prop. This fact could prove problematic and here's why.&lt;/p&gt;

&lt;p&gt;Let's say you want to create a reusable component for your app that needs to perform a navigation event as part of its functionality. You could define it as part of your route stack, but that wouldn't really make sense from a functional point of view. It is not a specific screen that the app displays, but just an arbitrary component that could be reused. This approach could bring its own fair share of problems, like unnecessary code duplication and complicated definitions in the scope of a component.&lt;/p&gt;

&lt;p&gt;This is better demonstrated on an example. Let's create a component that acts as a select screen with many options that displays an input and when tapped, it presents a separate screen that shows all the possible values for this input in a table. One of these components, let's call it &lt;code&gt;ListSelect&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fq8jhalqu69ecoc6xlaj5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fq8jhalqu69ecoc6xlaj5.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since you need to navigate from the screen that is currently displayed when the user interacts with this component you need to have the &lt;code&gt;componentId&lt;/code&gt; of the mounted screen ready for the &lt;code&gt;Navigation&lt;/code&gt; event in our &lt;code&gt;ListSelect&lt;/code&gt; component. If the &lt;code&gt;ListSelect&lt;/code&gt; component is used directly in the screen that has a &lt;code&gt;componentId&lt;/code&gt;, that wouldn't be a problem. You'd just need to pass it as a prop to the component and then inside of it you would receive it and perform the event, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigateToSelectScreen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;rootComponentId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Navigate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootComponentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;screen.ListSelect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ListSelect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;rootComponentId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TouchableOpacity&lt;/span&gt; &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;navigateToSelectScreen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;rootComponentId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Select a value
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TouchableOpacity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what if you use it extensively and you are sick of doing the &lt;code&gt;&amp;lt;ListSelect rootComponentId={componentId} /&amp;gt;&lt;/code&gt;? Or even worse, what if the component is nested deeper in the hierarchy and you'd need to prop drill it three, or even more levels? There has to be a better solution. Enter &lt;code&gt;Provider&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the previous section we were talking about how we can wrap our root components with a custom provider. What we could do here, is wrap our top level components with a Context Provider that stores the &lt;code&gt;componentId&lt;/code&gt; property which we can then access in a &lt;code&gt;Consumer&lt;/code&gt; to use literally anywhere else in the app and down the hierarchy tree. Context is a great way to lift such a UI specific piece of data and make it accessible in the hierarchy, but you could use any other global state management library, e.g. Redux, or Flux with the same results.&lt;/p&gt;

&lt;p&gt;Let's get back to our example and trace the steps we need to make to ensure we can use the component anywhere with no hassle. First of all, we define the screen we will be navigating to, from inside the component in our stack, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;Navigation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerComponentWithRedux&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;screen.ListSelect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ListSelect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next thing we need to do is create a Context that will keep track of the currently visible &lt;code&gt;componentId&lt;/code&gt; for us, let's call it &lt;code&gt;NavigationComponentIdProvider&lt;/code&gt; (duh). It's going to look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NavigationComponentIdProvider&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;navigationComponentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationEventsListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nx"&gt;Navigation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;events&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;registerComponentDidAppearListener&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;componentId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;navigationComponentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;componentId&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;componentWillUnmount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationEventsListener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationEventsListener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;componentDidMount&lt;/code&gt; we set up a listener that updates the state anytime a navigation event changes the active component. RNN has a useful listener for that using the provided&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;Navigation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;events&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;registerComponentDidAppearListener&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;method that receives the &lt;code&gt;componentId&lt;/code&gt; when it is called. We then simply update the state with this information. Do not forget to remove the listener in &lt;code&gt;componentWillUnmount&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We wrap it up by finishing the render method, which renders the &lt;code&gt;children&lt;/code&gt; wrapped with the Context's Provider. This should be the end result of our newly created Context that knows the currently displayed &lt;code&gt;componentId&lt;/code&gt; at any given time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NavigationComponentIdProvider&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;navigationComponentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationEventsListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nx"&gt;Navigation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;events&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;registerComponentDidAppearListener&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;componentId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;navigationComponentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;componentId&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;componentWillUnmount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationEventsListener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigationEventsListener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;navigationComponentId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationComponentIdContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;navigationComponentId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NavigationComponentIdContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NavigationComponentIdConsumer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;NavigationComponentIdContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Consumer&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NavigationComponentIdConsumer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NavigationComponentIdProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to update our global &lt;code&gt;Provider&lt;/code&gt; that we wrap all our top-level components with to include the &lt;code&gt;NavigationComponentIdProvider&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;Provider&lt;/code&gt; should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReduxProvider&lt;/span&gt; &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ThemeProvider&lt;/span&gt; &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AnyOtherProviderThatYouMightBeUsing&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationComponentIdProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NavigationComponentIdProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;AnyOtherProviderThatYouMightBeUsing&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ThemeProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ReduxProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have followed the tutorial up to this point, you can now &lt;code&gt;import { NavigationComponentIdConsumer }'&lt;/code&gt; and get the &lt;code&gt;componentId&lt;/code&gt; of a displayed screen anywhere in your app.&lt;/p&gt;

&lt;p&gt;To make the whole process even simpler and cleaner, we can create a higher order component (HOC) that wraps the component with the &lt;code&gt;NavigationComponentIdConsumer&lt;/code&gt;. It's a very simple abstraction and it will help us to keep the resulting code much cleaner.&lt;/p&gt;

&lt;p&gt;The HOC could look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NavigationComponentIdConsumer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./NavigationComponentIdContext&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withNavigationComponentIdContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Comp&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NavigationComponentIdConsumer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;componentId&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Comp&lt;/span&gt; &lt;span class="na"&gt;componentId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;componentId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NavigationComponentIdConsumer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;withNavigationComponentIdContext&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last thing we do is wrap the export of our &lt;code&gt;ListSelect&lt;/code&gt; component in &lt;code&gt;withNavigationComponentIdContext&lt;/code&gt;, like so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;ListSelect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;withNavigationComponentIdContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ListSelect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component now has access to the &lt;code&gt;componentId&lt;/code&gt; from its props and we do not need to pass it in manually.&lt;/p&gt;

&lt;p&gt;The great thing about this is, that you can use this HOC anywhere in your app, so you needn't worry about the &lt;code&gt;componentId&lt;/code&gt; anymore if you don't want to . If you are in a situation where a component that is on a lower level in hierarchy needs to make a &lt;code&gt;Navigation&lt;/code&gt; event, don't drill the &lt;code&gt;componentId&lt;/code&gt; manually, just wrap it in &lt;code&gt;withNavigationComponentIdContext&lt;/code&gt; and get it in the props.&lt;/p&gt;

&lt;p&gt;Another good example for this usage would be creating a modal component. Although if modals are very specific in your app, it might make sense to define them as separate screens to make more sense from the semantical point of view.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;There are a few more RNN specific issues that come to mind. But most of those are version specific (RNN is updated almost every day!). It's probably a good idea to leave them be and not try to work around them that much as they are bound to be resolved in the near future. This article should serve as a quick write-up with solutions to common issues in RNN that are probably not likely to change, since they are tied to the API of the library.&lt;/p&gt;

&lt;p&gt;Other than that, if you have any more issues, I can definitely recommend the Discord &lt;a href="https://discord.gg/hnc8nq" rel="noopener noreferrer"&gt;community&lt;/a&gt; for &lt;code&gt;react-native-navigation&lt;/code&gt;. Folks there are very helpful and saved my skin loads of times before. Thanks for reading!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;First published on &lt;a href="https://sudolabs.io/blog/react-native-navigation-and-its-caveats/" rel="noopener noreferrer"&gt;sudolabs.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>reactnative</category>
    </item>
  </channel>
</rss>
