<?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: Anders Aaen Springborg</title>
    <description>The latest articles on DEV Community by Anders Aaen Springborg (@aaen).</description>
    <link>https://dev.to/aaen</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F814764%2F7e3f1b24-b8e6-45e1-8f2b-9e084ef02bcd.JPG</url>
      <title>DEV Community: Anders Aaen Springborg</title>
      <link>https://dev.to/aaen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aaen"/>
    <language>en</language>
    <item>
      <title>I built a Jira CLI for my AI agents. My team thinks I should have used MCP</title>
      <dc:creator>Anders Aaen Springborg</dc:creator>
      <pubDate>Tue, 09 Jun 2026 19:36:40 +0000</pubDate>
      <link>https://dev.to/aaen/i-built-a-jira-cli-for-my-ai-agents-my-team-thinks-i-should-have-used-mcp-3ja9</link>
      <guid>https://dev.to/aaen/i-built-a-jira-cli-for-my-ai-agents-my-team-thinks-i-should-have-used-mcp-3ja9</guid>
      <description>&lt;p&gt;I recently put together a tiny open-source tool: a non-interactive, JSON-first Jira CLI tailored for AI agents. I called it the "kubectl of Jira." The idea is simple: it’s a stateless binary that outputs clean JSON so agents can pipe data straight into jq, grep, or wc without choking on interactive menus or ugly ASCII tables.&lt;/p&gt;

&lt;p&gt;I shared it in our team chat, expecting a few code comments. Instead, I accidentally started a argument: In the age of LLMs, why are we still building CLIs? Why aren't we just using MCP servers?&lt;/p&gt;

&lt;p&gt;Here is why my team thinks I'm living in the past, and why I still think the CLI wins.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Argument for MCP (What my team says)
&lt;/h2&gt;

&lt;p&gt;My colleagues made some good points.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;If you look at the MCP ecosystem, Jira servers already exist.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;They argued that MCP is fundamentally built for LLMs. It exposes clean, structured tool schemas natively. Instead of an agent trying to parse text or guess flags by running --help (which eats up tokens), an MCP server tells the model exactly what parameters it expects right out of the box. Plus, hitting a running MCP service over HTTP or standard I/O is computationally lighter than spawning a brand new OS process for every single command.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're building something with a session that is tied to your chat session, or your agent do not have a shell available, they are probably right. MCP is elegant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Still Prefer a CLI
&lt;/h2&gt;

&lt;p&gt;Despite their pushback, I’m sticking with the CLI approach for three practical reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The MCP "Schema Tax" burns tokens&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The true catch of MCP lies in its heavy JSON schema overhead. Whenever your agent initializes, the daemon dumps a verbose payload containing the names, descriptions, and strict parameters for every single tool directly into your context window. Unless you resort to clunky workarounds—like building a &lt;code&gt;search_tool(query: string)&lt;/code&gt; to fetch capabilities dynamically—a server exposing 40 or 50 tools will burn thousands of tokens on raw protocol syntax before the agent even reads your prompt.&lt;/p&gt;

&lt;p&gt;With a CLI, the LLM usually already knows the basic syntax from its training data. The agent runs a quick command, gets a tiny JSON blob back, and keeps 95% of its context window free for actual thinking.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Unix ecosystem is the ultimate tool schema&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With MCP, if your agent wants to search for a ticket, filter it by status, and count the results, you have to explicitly code an endpoint that supports that exact sequence.&lt;/p&gt;

&lt;p&gt;With a CLI, the agent just falls back on standard bash utilities it already knows by heart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jira search jql &lt;span class="s2"&gt;"assignee = currentUser()"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.[].key'&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I don't have to write custom API endpoints for edge-case queries. The terminal is the toolkit.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Debugging via shell history&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When an MCP agent breaks, debugging sucks. You have to hunt through daemon logs, look at JSON-RPC transport streams, and figure out what the state was when it died.&lt;/p&gt;

&lt;p&gt;When a CLI agent breaks, it’s beautiful. I open my terminal, press the up arrow to look at the shell history, copy the exact command string the agent tried to run, and replay it myself.&lt;/p&gt;

&lt;p&gt;To keep things secure, I added "Kubernetes-style" local context management (jira context set --project PROJ). It saves the default project to a local file on disk, giving the agent a hard, inspectable blast radius.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Tool: @888aaen/jira-cli
&lt;/h3&gt;

&lt;p&gt;If you want to try how it feels by yourself, you can it install the cli with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @888aaen/jira-cli
npx skills@latest add AndersSpringborg/jira-agent-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and use it your own agent harness.&lt;/p&gt;

&lt;p&gt;(The second command installs a skill file for your agent harness so it knows how to drive the binary out of the box).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AndersSpringborg/jira-agent-cli" rel="noopener noreferrer"&gt;The repo is here AndersSpringborg/jira-agent-cli&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where do you stand?
&lt;/h2&gt;

&lt;p&gt;We are split on this internally. One side thinks CLIs are a temporary stopgap until MCP context management gets smarter. The other side thinks running daemons for basic API tasks is over-engineering.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are you building CLIs or standing up MCP servers for your internal workflows?&lt;/li&gt;
&lt;li&gt;How are you dealing with token bloating from massive MCP tool lists?&lt;/li&gt;
&lt;li&gt;Is anyone using a hybrid setup—like CLIs for local hacking and MCP for production?&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>cli</category>
      <category>mcp</category>
      <category>showdev</category>
    </item>
    <item>
      <title>A Beginner's Guide to Mobile Development in React Native with Expo</title>
      <dc:creator>Anders Aaen Springborg</dc:creator>
      <pubDate>Wed, 23 Mar 2022 15:34:06 +0000</pubDate>
      <link>https://dev.to/itminds/a-beginners-guide-to-mobile-development-in-react-native-with-expo-4f2o</link>
      <guid>https://dev.to/itminds/a-beginners-guide-to-mobile-development-in-react-native-with-expo-4f2o</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;This is a guide getting you through setting up a React Native project. However, this guide won't go in details with React, so if you're new to React, I recommend you to check out this &lt;a href="https://beta.reactjs.org/" rel="noopener noreferrer"&gt;getting started with react guide.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/IT-Minds/first-mobile-app/tree/main" rel="noopener noreferrer"&gt;Here is a link for what your code should look like, when you are done.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  React Native and Expo
&lt;/h2&gt;

&lt;p&gt;React Native is a framework for writing cross-platform native apps. &lt;/p&gt;

&lt;p&gt;Expo is a set of tools and services built around React Native and native platforms that help you develop, build and deploy iOS and Android apps from the same JavaScript/TypeScript codebase. The alternative would be to build each app in xCode and Android studio, which is very cumbersome.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;You need to have &lt;a href="https://nodejs.org/en/download/" rel="noopener noreferrer"&gt;node and npm installed&lt;/a&gt;, and &lt;a href="https://classic.yarnpkg.com/en/docs/install#mac-stable" rel="noopener noreferrer"&gt;yarn&lt;/a&gt; is optional, but recommended.&lt;/p&gt;

&lt;p&gt;Then we have to install Expo, through npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install the command line tools&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--global&lt;/span&gt; expo-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we're ready to make a project. If you installed yarn, write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;expo init first-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or with npm&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;expo init first-app &lt;span class="nt"&gt;--npm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here, you will be prompted with a few options for your project. I recommend choosing a managed workflow as this enables us to release the app in Expo, without an Apple developer account for iOS. I chose the template "blank (typescript)", as can be seen in the picture below. If you're new, you could also use the "tab" template. This has built-in navigation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6st9i4kdksc3721ouyb7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6st9i4kdksc3721ouyb7.png" alt="Init expo app" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You now have a project. In your terminal, you can navigate to the project's directory with 'cd first-app'. Your project structure should look like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3zm4excvr0ynziwouhne.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3zm4excvr0ynziwouhne.png" alt="File structure" width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you can run the project by writing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it will look something like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmsfw5uoswjecam322oh9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmsfw5uoswjecam322oh9.png" alt="App template iPhone" width="800" height="778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can either press w, to see your app in your browser, or you can scan the QR code which redirects you to download an app called &lt;a href="https://expo.dev/client" rel="noopener noreferrer"&gt;Expo go&lt;/a&gt;. This allows you to view the app while you develop it, which is something I would recommend. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl370yjyi80gfritav8r6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl370yjyi80gfritav8r6.png" alt="Initial app" width="800" height="1494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You now have a running app in React Native. In the next section, we are going to look at how native APIs work.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Native APIs
&lt;/h2&gt;

&lt;p&gt;As we choose a "managed workflow", we're building everything with Expo. This comes with some &lt;a href="https://docs.expo.dev/introduction/why-not-expo/" rel="noopener noreferrer"&gt;limitations&lt;/a&gt;. If you need a native API which isn't on the &lt;a href="https://docs.expo.dev/versions/latest/" rel="noopener noreferrer"&gt;list of supported APIs&lt;/a&gt; (there is 100+ native APIs), you can switch to a bare workflow in which you can write your own native code. &lt;br&gt;
Below is a comparison between a managed and bare workflow: &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yk3bvoeroi2ayfzq73f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yk3bvoeroi2ayfzq73f.png" alt="Managed and bare workflow comparison" width="799" height="403"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing native APIs
&lt;/h3&gt;

&lt;p&gt;As an example, let's make a page that shows our battery percentage and GPS location.&lt;/p&gt;

&lt;p&gt;Let's start with a &lt;a href="https://docs.expo.dev/versions/v44.0.0/sdk/battery" rel="noopener noreferrer"&gt;battery&lt;/a&gt; component. We install it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;expo &lt;span class="nb"&gt;install &lt;/span&gt;expo-battery
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First off, we'll work on showing the battery percentage. We need the API 'getPowerStateAsync'. We'll call when a component mount, and voilá - we have the phone's battery percentage:&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBattery&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&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;Battery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBatteryLevelAsync&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setBattery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&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;We can show it in our view 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;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;View&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&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;Battery &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;battery&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;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;StatusBar&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;black&lt;/span&gt;&lt;span class="dl"&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;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;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrt12szsca44mq34sk2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrt12szsca44mq34sk2i.png" alt="Battery 42%" width="800" height="1494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's make a component that looks at the power mode of a phone. Imagine that you have a power-hungry feature which you want to disable when in low power mode (like animation).&lt;br&gt;
We can get the power state from the same API, 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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;lowPoweredState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLowPoweredState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&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;Battery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPowerStateAsync&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bs&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setLowPoweredState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lowPowerMode&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;We can now carry out some conditional rendering, based on the power state:&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lowPoweredState&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&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;Getting info from your phone...&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="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;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Battery state: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;lowPoweredState&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i am a static text replacement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I AM A POWER HUNGRY ANIMATION&lt;/span&gt;&lt;span class="dl"&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;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fft4z9v54ilim0xcifac8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fft4z9v54ilim0xcifac8.png" alt="Rendering based on power state" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To stay up to date, when the phone changed from a low powered state to a normal one, we can add a listener in useEffects 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;batteryModeSubscriber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Battery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLowPowerModeListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setLowPoweredState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lowPowerMode&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;return &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;batteryModeSubscriber&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our app will now always render based on the power state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publishing our app
&lt;/h2&gt;

&lt;p&gt;Normally, you think of publishing an app to App Store and Google Play store. In order to do this, you need an &lt;a href="https://developer.apple.com/programs/" rel="noopener noreferrer"&gt;Apple developer account&lt;/a&gt;(100$ yearly subscription) or a &lt;a href="https://play.google.com/apps/publish/signup" rel="noopener noreferrer"&gt;Google Play developer account&lt;/a&gt;(25$ one time fee) account. You can read more about building and releasing your app &lt;a href="https://docs.expo.dev/build/setup/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  You're an app developer
&lt;/h2&gt;

&lt;p&gt;You have now started on your first React Native app in Expo. This is the same tool which is used for creating apps like Facebook, Instagram, Coinbase, shopify, Tesla, Uber Eats and many more. You can read more on Expo here: &lt;a href="https://docs.expo.dev/" rel="noopener noreferrer"&gt;https://docs.expo.dev/&lt;/a&gt; or check out an open source app here: &lt;a href="https://github.com/withspectrum/spectrum" rel="noopener noreferrer"&gt;https://github.com/withspectrum/spectrum&lt;/a&gt;&lt;br&gt;
and checkout an enterprise boilerplate here: &lt;a href="https://github.com/infinitered/ignite" rel="noopener noreferrer"&gt;https://github.com/infinitered/ignite&lt;/a&gt;&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>expo</category>
      <category>typescript</category>
      <category>mobile</category>
    </item>
  </channel>
</rss>
