<?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: Vikrant Negi</title>
    <description>The latest articles on DEV Community by Vikrant Negi (@vikrantnegi).</description>
    <link>https://dev.to/vikrantnegi</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%2F59047%2F5f75c582-d590-4f39-adb5-22f143c232f3.jpg</url>
      <title>DEV Community: Vikrant Negi</title>
      <link>https://dev.to/vikrantnegi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vikrantnegi"/>
    <language>en</language>
    <item>
      <title>Why LLMs Can't Count Letters (And How They Fake It)</title>
      <dc:creator>Vikrant Negi</dc:creator>
      <pubDate>Tue, 23 Jun 2026 17:13:16 +0000</pubDate>
      <link>https://dev.to/vikrantnegi/why-llms-cant-count-letters-and-how-they-fake-it-3j9k</link>
      <guid>https://dev.to/vikrantnegi/why-llms-cant-count-letters-and-how-they-fake-it-3j9k</guid>
      <description>&lt;p&gt;You've probably noticed this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask a language model to count the letters in "strawberry" and it'll confidently give you the wrong answer.&lt;/li&gt;
&lt;li&gt;Ask it to rhyme "entrepreneur" and it fumbles.&lt;/li&gt;
&lt;li&gt;Ask it to fix a typo in "teh quick brown fox" and it handles it without blinking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same model. Wildly different results. Why?&lt;/p&gt;

&lt;p&gt;The answer isn't "the model is bad at spelling." It's in how these models actually read text, and it's not what most people assume. Once you see the mechanism, you can predict which of these tasks a model will nail and which it'll botch, before you even run it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The model never sees your text
&lt;/h2&gt;

&lt;p&gt;When you type a message into an LLM, the model doesn't receive a string. It receives a sequence of integers.&lt;/p&gt;

&lt;p&gt;Before your input ever touches the neural network, it passes through a &lt;strong&gt;tokenizer&lt;/strong&gt;: a separate component that converts raw text into token IDs. The string &lt;code&gt;"strawberry"&lt;/code&gt; might become &lt;code&gt;[496, 19772]&lt;/code&gt;. That's what the model works with.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F62w5iwmkifoe7hrqbecn.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F62w5iwmkifoe7hrqbecn.png" alt="The model never sees your text: a tokenizer converts the string to integers before the network runs" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tokenizer is trained separately, before the LLM itself, and then frozen. The model never updates it. It just inherits whatever mapping the tokenizer learned. So the very first thing that happens to your prompt is a lossy translation the model has no say in.&lt;/p&gt;

&lt;h2&gt;
  
  
  How that mapping gets decided: BPE
&lt;/h2&gt;

&lt;p&gt;The algorithm most modern LLMs use is called &lt;strong&gt;Byte Pair Encoding (BPE)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's the mechanism in one sentence: BPE starts with individual characters as the vocabulary, then repeatedly merges the most frequently co-occurring pair of tokens in the training corpus, until it hits a target vocabulary size.&lt;/p&gt;

&lt;p&gt;So it starts with the characters: &lt;code&gt;s, t, r, a, w, b, e, r, r, y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then it notices which pairs show up together constantly and merges them: &lt;code&gt;s·t·r·a·w&lt;/code&gt; collapses into &lt;code&gt;straw&lt;/code&gt;, &lt;code&gt;b·e·r·r·y&lt;/code&gt; collapses into &lt;code&gt;berry&lt;/code&gt;. And so on, until the vocabulary stabilizes at a target size (GPT-4 uses ~100,000 tokens).&lt;/p&gt;

&lt;p&gt;The result: &lt;code&gt;"strawberry"&lt;/code&gt; might tokenize as &lt;code&gt;["straw", "berry"]&lt;/code&gt;, not because those are linguistically meaningful units, but because those byte sequences were frequent enough in training data to survive the merges.&lt;/p&gt;

&lt;p&gt;This is the key intuition: &lt;strong&gt;the splits track frequency, not grammar.&lt;/strong&gt; Common words like &lt;code&gt;"the"&lt;/code&gt; become a single token. Rare or technical words get shredded into pieces. A word like &lt;code&gt;"thransformer"&lt;/code&gt; (a typo) might become 4 or 5 tokens the model has never seen grouped that way.&lt;/p&gt;

&lt;h2&gt;
  
  
  The information that gets thrown away
&lt;/h2&gt;

&lt;p&gt;Here's the thing that matters: once a sequence of characters becomes a token ID, &lt;strong&gt;the characters are gone&lt;/strong&gt;.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffb0tg4mk3qmncg4s1yni.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffb0tg4mk3qmncg4s1yni.png" alt="Once it's a token ID the characters are gone: " width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The model sees &lt;code&gt;19772&lt;/code&gt; (or whatever integer maps to &lt;code&gt;"berry"&lt;/code&gt;). It does not see &lt;code&gt;b&lt;/code&gt;, &lt;code&gt;e&lt;/code&gt;, &lt;code&gt;r&lt;/code&gt;, &lt;code&gt;r&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;. There's no "look inside the token" operation. No character-level access. The sub-token structure is destroyed at tokenization and never passed forward.&lt;/p&gt;

&lt;p&gt;This is why counting letters is hard. When you ask "how many R's in 'strawberry'?", the model has to reconstruct character-level information from statistical patterns in training data, even though &lt;code&gt;strawberry&lt;/code&gt; is just two opaque integers to it. It might have seen this exact question answered correctly often enough to get it right. It might not. There's no reliable mechanism, just pattern matching over a destroyed signal.&lt;/p&gt;

&lt;p&gt;Same reason rhyming is unreliable. Rhymes are about sound patterns at the character level. The model has no direct access to those. It's working from memory of what it's seen rhymed before, not from actual phoneme analysis.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick gut-check:&lt;/strong&gt; before reading on, predict it yourself. Spelling a word backwards, easy or hard for an LLM? (Hard. Same reason as counting letters: it requires character-level access the token ID doesn't carry.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  So how does it handle typos?
&lt;/h2&gt;

&lt;p&gt;This is the interesting part, and the apparent contradiction.&lt;/p&gt;

&lt;p&gt;If the model has no character-level access, how does &lt;code&gt;"teh quick brown fox"&lt;/code&gt; get correctly interpreted as &lt;code&gt;"the quick brown fox"&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;The answer is attention.&lt;/p&gt;

&lt;p&gt;The model attends to every token in relation to every other token in the sequence. &lt;code&gt;"teh"&lt;/code&gt;, even though it has a different integer ID than &lt;code&gt;"the"&lt;/code&gt;, appears surrounded by the same context tokens: &lt;code&gt;"quick"&lt;/code&gt;, &lt;code&gt;"brown"&lt;/code&gt;, &lt;code&gt;"fox"&lt;/code&gt;. The model has seen &lt;code&gt;"the"&lt;/code&gt; in exactly that context billions of times during training. The attention mechanism builds a contextual representation of &lt;code&gt;"teh"&lt;/code&gt; that ends up in the same neighborhood as &lt;code&gt;"the"&lt;/code&gt; in the model's internal space.&lt;/p&gt;

&lt;p&gt;It's not correcting the typo. It's representing the token based on what surrounds it, and that representation ends up semantically equivalent.&lt;/p&gt;

&lt;p&gt;This works because &lt;code&gt;"teh"&lt;/code&gt; is a common typo. It appears frequently enough in training data, in the same contexts as &lt;code&gt;"the"&lt;/code&gt;, that the model has learned to bridge them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this breaks down
&lt;/h2&gt;

&lt;p&gt;Apply the same logic and you can predict where it'll fail. Three places it gets shaky:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A misspelled rare technical word&lt;/strong&gt;, like &lt;code&gt;"thransformer"&lt;/code&gt; instead of &lt;code&gt;"transformer"&lt;/code&gt;, is much harder to recover. The correct word appears less frequently in training data to begin with, and the broken form has even less signal. Attention can try, but the weights aren't there to make a confident bridge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A misspelling in an ambiguous context&lt;/strong&gt;, where multiple words could fit, is also risky. The context constraint that makes &lt;code&gt;"teh"&lt;/code&gt; obvious doesn't apply when the surrounding tokens don't narrow things down.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anything that needs precise character-level reasoning&lt;/strong&gt;, like counting letters, detecting palindromes, generating anagram lists, or strict rhyming, is fundamentally unreliable. Not because the model is dumb, but because the information was structurally discarded before the model ever ran.&lt;/li&gt;
&lt;/ul&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg9zup535z0n2808q4sb5.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg9zup535z0n2808q4sb5.png" alt="The same mechanism predicts where recovery fails: common forms bridge, rare ones don't" width="799" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The mental model worth keeping
&lt;/h2&gt;

&lt;p&gt;BPE and attention are complementary by design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BPE&lt;/strong&gt; trades character structure for compression efficiency. Fewer tokens means shorter sequences, which means cheaper and faster inference.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attention&lt;/strong&gt; partially compensates by using context to recover meaning that the token IDs alone don't carry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system works well for what language is mostly made of: common words, common patterns, common errors. It degrades gracefully, not catastrophically, on the edges.&lt;/p&gt;

&lt;p&gt;But it's worth knowing where those edges are. Next time a model struggles with something that seems trivially easy (count the letters, spell this word backwards, does this rhyme with that), it's not a reasoning failure. It's a tokenization constraint that no amount of compute fixes.&lt;/p&gt;

&lt;p&gt;The information was thrown away before the model ever woke up.&lt;/p&gt;




&lt;h3&gt;
  
  
  Go deeper
&lt;/h3&gt;

&lt;p&gt;Tokenization is step one of the transformer pipeline. If you want the whole stack (embeddings, positional encoding, attention internals (Q/K/V), the feed-forward network, the residual stream, and the next-token loop), 0xkato wrote an excellent from-the-ground-up walkthrough: &lt;a href="https://0xkato.xyz/how-llms-actually-work/" rel="noopener noreferrer"&gt;&lt;strong&gt;How LLMs Actually Work&lt;/strong&gt;&lt;/a&gt;. It picks up right where this post leaves off.&lt;/p&gt;

&lt;p&gt;Find me on &lt;a href="https://x.com/vikrant_negi" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>llm</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Six Lines, Zero API Calls: Running LLMs On-Device in React Native</title>
      <dc:creator>Vikrant Negi</dc:creator>
      <pubDate>Mon, 22 Jun 2026 04:49:24 +0000</pubDate>
      <link>https://dev.to/vikrantnegi/six-lines-zero-api-calls-running-llms-on-device-in-react-native-3ahl</link>
      <guid>https://dev.to/vikrantnegi/six-lines-zero-api-calls-running-llms-on-device-in-react-native-3ahl</guid>
      <description>&lt;p&gt;Every AI feature I've worked on has done the same quiet thing: collect the user's text, send it to someone else's server, pay per token, and pray the network holds. That's fine until it isn't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your user is on a flight, with no network and a dead feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It's a journaling app, where "we send your private thoughts to a third party" is a hard no.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finance notices the OpenAI bill climbing in a straight line with usage.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's another option most React Native devs still treat as exotic: run the model on the device. No API call, no network, no per-token cost. The first time I wired this into an offline text-enhancement tool with Expo, the surprise wasn't that it worked. It's that the actual model code was about six lines. The hard parts were everywhere except the model.&lt;/p&gt;

&lt;p&gt;This is a walkthrough of react-native-executorch (by Software Mansion, the Reanimated and Gesture Handler folks), built on Meta's ExecuTorch runtime. We'll build a working local chat screen, but more importantly I'll show you the traps. The ones that cost me an afternoon each. The ones an AI-generated tutorial will confidently get wrong because the API changed underneath it.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/software-mansion" rel="noopener noreferrer"&gt;
        software-mansion
      &lt;/a&gt; / &lt;a href="https://github.com/software-mansion/react-native-executorch" rel="noopener noreferrer"&gt;
        react-native-executorch
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Declarative way to run AI models in React Native on device, powered by ExecuTorch.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/software-mansion/react-native-executorch/blob/main/docs/static/img/logo-hero.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fsoftware-mansion%2Freact-native-executorch%2Fraw%2Fmain%2Fdocs%2Fstatic%2Fimg%2Flogo-hero.svg" alt="RNE Logo" width="25%"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;React Native ExecuTorch
  &lt;/h1&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;a href="https://swm-delivery.com/www/delivery/ck-slug.php?zoneid=zone-gh-react-native-executorch-1&amp;amp;n=1" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b11f833d3fe69e1c913c0c492a40066b4b9a76b3963e85542dad5291a8bf4bd9/68747470733a2f2f73776d2d64656c69766572792e636f6d2f7777772f696d616765732f7a6f6e652d67682d72656163742d6e61746976652d6578656375746f7263682d313f6e3d31"&gt;&lt;/a&gt;
  &lt;a href="https://swm-delivery.com/www/delivery/ck-slug.php?zoneid=zone-gh-react-native-executorch-2&amp;amp;n=1" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/d441cafe1c6ab8bedc87399a4954779be942eff21f83810be52065651387678c/68747470733a2f2f73776d2d64656c69766572792e636f6d2f7777772f696d616765732f7a6f6e652d67682d72656163742d6e61746976652d6578656375746f7263682d323f6e3d31"&gt;&lt;/a&gt;
  &lt;a href="https://swm-delivery.com/www/delivery/ck-slug.php?zoneid=zone-gh-react-native-executorch-3&amp;amp;n=1" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/016f6595dfd55a0a21ce5ed40caaa40ecabf3c6c87c911c3563375e8a9782ce9/68747470733a2f2f73776d2d64656c69766572792e636f6d2f7777772f696d616765732f7a6f6e652d67682d72656163742d6e61746976652d6578656375746f7263682d333f6e3d31"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/software-mansion/react-native-executorch/graphs/contributors" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/4efe273b5f42656fb7aea5280b7b03c48f2aa7726ce862e8a2f9e75fa83e5ae3/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6e7472696275746f72732f736f6674776172652d6d616e73696f6e2f72656163742d6e61746976652d6578656375746f7263683f7374796c653d666f722d7468652d626164676526636f6c6f723d303030303842" alt="GitHub - Contributors"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/software-mansion/react-native-executorch/stargazers" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7505fab2e945a6132bb269eb140aabe32a29ff8d014e5c0fd6b8346a6ef5e87d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f736f6674776172652d6d616e73696f6e2f72656163742d6e61746976652d6578656375746f7263683f7374796c653d666f722d7468652d626164676526636f6c6f723d303030303842" alt="GitHub - Stars"&gt;&lt;/a&gt;
  &lt;a href="https://discord.gg/ZGqqY55qkP" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e51047a22e3dac98689c685272191724fab79d9f4998d0b26eba5891c5914ff3/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d4a6f696e25323055732d3030303038423f6c6f676f3d646973636f7264266c6f676f436f6c6f723d7768697465267374796c653d666f722d7468652d6261646765" alt="Join our Discord community"&gt;&lt;/a&gt;
  &lt;a href="https://docs.swmansion.com/react-native-executorch/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/514f990b395918ac034db1a87a1fd6cb036ad08bb728d2ab4d39e099a33ff322/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446f63756d656e746174696f6e2d3030303038423f6c6f676f3d676f6f676c65646f6373266c6f676f436f6c6f723d7768697465267374796c653d666f722d7468652d6261646765" alt="Documentation"&gt;&lt;/a&gt;
  &lt;a href="https://swmansion.com/contact" rel="nofollow noopener noreferrer"&gt;
    &lt;img src="https://camo.githubusercontent.com/3540cdadfdbfa8813bbead5b113ddf4a4415cecd7d29d75fa4ffa36e53484d4e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4869726525323055732d3030303038423f6c6f676f3d7265616374266c6f676f436f6c6f723d776869746526636f6c6f723d6461726b677265656e267374796c653d666f722d7468652d6261646765" alt="Hire Us"&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;
  &lt;a href="https://github.com/software-mansion/react-native-executorch/blob/main/README.md" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2efd8fcd3ca563644070f28ba0203388afb9a28adbf20bcb098cf996fa7513c6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f454e2d3030303038423f6c6f676f3d266c6f676f436f6c6f723d776869746526636f6c6f723d303030303842267374796c653d666f722d7468652d6261646765" alt="README"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/software-mansion/react-native-executorch/blob/main/readmes/README_es.md" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/6a0e34c718bed2cc7f3d02be3b22e096a340a36c5138d08f7bed140edf583bc0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f45532d3030303038423f6c6f676f3d266c6f676f436f6c6f723d776869746526636f6c6f723d303030303842267374796c653d666f722d7468652d6261646765" alt="README ES"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/software-mansion/react-native-executorch/blob/main/readmes/README_fr.md" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/47d87a459c057539cd67ebdd44c0d30d1bfaea0c7e5449c50a97785a26f3dbc0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f46522d3030303038423f6c6f676f3d266c6f676f436f6c6f723d776869746526636f6c6f723d303030303842267374796c653d666f722d7468652d6261646765" alt="README FR"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/software-mansion/react-native-executorch/blob/main/readmes/README_cn.md" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1bf5a490bd9770557c07173e89c3da1e002a505ca9285c0b16e46bb65455e8f1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f434e2d3030303038423f6c6f676f3d266c6f676f436f6c6f723d776869746526636f6c6f723d303030303842267374796c653d666f722d7468652d6261646765" alt="README CN"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/software-mansion/react-native-executorch/blob/main/readmes/README_pt.md" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/ec5c3bd410eff0518fbebdaf4dae5b5145311ec61b3486cfe13f3305116b999a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f50542d3030303038423f6c6f676f3d266c6f676f436f6c6f723d776869746526636f6c6f723d303030303842267374796c653d666f722d7468652d6261646765" alt="README PT"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/software-mansion/react-native-executorch/blob/main/readmes/README_in.md" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/3259d0d1cb6844ca44d98c8f61c24fc781fddc0ad98b522ed3d2c090a51e5d04/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f494e2d3030303038423f6c6f676f3d266c6f676f436f6c6f723d776869746526636f6c6f723d303030303842267374796c653d666f722d7468652d6261646765" alt="README IN"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React Native ExecuTorch&lt;/strong&gt; provides a declarative way to run AI models on-device using React Native, powered by &lt;strong&gt;ExecuTorch&lt;/strong&gt; 🚀. It offers out-of-the-box support for a wide range of LLMs, computer vision models, and more. Visit our &lt;a href="https://huggingface.co/software-mansion" rel="nofollow noopener noreferrer"&gt;HuggingFace&lt;/a&gt; page to explore these models.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://executorch.ai" rel="nofollow noopener noreferrer"&gt;&lt;strong&gt;ExecuTorch&lt;/strong&gt;&lt;/a&gt;, developed by Meta, is a novel framework allowing AI model execution on devices like mobile phones or microcontrollers.&lt;/p&gt;

&lt;p&gt;React Native ExecuTorch bridges the gap between React Native and native platform capabilities, enabling developers to efficiently run local AI models on mobile devices. This can be achieved without the need for extensive expertise in native programming or machine learning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/react-native-executorch" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1ddd5685fbf1df14105b0c36acb16cb135706580fa380eec58ec9eba6855b12c/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f72656163742d6e61746976652d6578656375746f7263683f636f6c6f723d303030303842" alt="npm version"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/react-native-executorch" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8f2c87e453d85efb9a0c7d3c6c73d35cd4c985cbcd53376863e6b72de22c3f0b/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f72656163742d6e61746976652d6578656375746f7263682f6578656375746f7263682d6e696768746c793f6c6162656c3d6e696768746c7926636f6c6f723d303030303842" alt="npm nightly"&gt;&lt;/a&gt;
&lt;a href="https://github.com/software-mansion/react-native-executorch/actions/workflows/ci.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/software-mansion/react-native-executorch/actions/workflows/ci.yml/badge.svg" alt="CI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;strong&gt;Table of Contents&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/software-mansion/react-native-executorch#supported-versions" rel="noopener noreferrer"&gt;Supported Versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/software-mansion/react-native-executorch#real-world-example" rel="noopener noreferrer"&gt;Real-world Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/software-mansion/react-native-executorch#quickstart---running-lfm25" rel="noopener noreferrer"&gt;Quickstart - Running LFM2.5&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/software-mansion/react-native-executorch#one-installation" rel="noopener noreferrer"&gt;1️⃣ Installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/software-mansion/react-native-executorch#two-setup--initialization" rel="noopener noreferrer"&gt;2️⃣ Setup &amp;amp; Initialization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/software-mansion/react-native-executorch#three-run-the-model" rel="noopener noreferrer"&gt;3️⃣ Run the Model!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/software-mansion/react-native-executorch#demo-apps" rel="noopener noreferrer"&gt;Demo Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/software-mansion/react-native-executorch#ready-made-models" rel="noopener noreferrer"&gt;Ready-made Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/software-mansion/react-native-executorch#documentation" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/software-mansion/react-native-executorch#license" rel="noopener noreferrer"&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/software-mansion/react-native-executorch#whats-next" rel="noopener noreferrer"&gt;What's Next?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/software-mansion/react-native-executorch#react-native-executorch-is-created-by-software-mansion" rel="noopener noreferrer"&gt;React Native ExecuTorch is created by Software Mansion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Supported Versions&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;The minimal supported version are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;iOS…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/software-mansion/react-native-executorch" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  The mental model
&lt;/h2&gt;

&lt;p&gt;Before any code, one idea that saves a lot of confusion: the LLM is one part of your app, not the app itself. The library gives you the model and nothing else. Everything around it is still your job.&lt;/p&gt;

&lt;p&gt;It helps to picture three things working together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Your normal app code&lt;/strong&gt; is predictable. Same input, same output, every time: the buttons, the list, the navigation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The model&lt;/strong&gt; is not. Give it the same prompt twice and you'll get slightly different answers, because it generates text by predicting likely next words, not by looking facts up. That's also why it sometimes states wrong things with total confidence. It isn't a defect you can patch, it's how the thing works, so plan for it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The person reading the output&lt;/strong&gt; is the final check. They decide what to trust and what to ignore.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;react-native-executorch owns only the middle piece. It hands you a stream of words and a few status flags. It does not manage your chat UI, decide when to run the model, or judge whether the answer is any good. Those are yours to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;New Architecture only.&lt;/strong&gt; The library does not support the old RN architecture. If your app is still on it, that's your first migration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expo SDK 54+&lt;/strong&gt; if you're on Expo (which I'd recommend). Older SDKs break on the file-system APIs the library now depends on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A custom dev build, not Expo Go.&lt;/strong&gt; This relies on native modules. Expo Go will not load it. This trips up &lt;em&gt;everyone&lt;/em&gt; the first time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A real iOS device for release builds.&lt;/strong&gt; Because ExecuTorch runs natively, you can't produce an iOS &lt;em&gt;release&lt;/em&gt; build targeting the simulator. Debug on the sim is fine; release testing needs hardware.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last pair isn't optional advice, it's the difference between "why won't this run" and a working build. Write them on a sticky note.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Installation is two steps: install the core package, then add a resource fetcher adapter.&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;react-native-executorch

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then a &lt;strong&gt;resource fetcher adapter&lt;/strong&gt;. These are platform-specific, so install the one that matches your project.&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;# Expo projects&lt;/span&gt;

npm &lt;span class="nb"&gt;install &lt;/span&gt;react-native-executorch-expo-resource-fetcher expo-file-system expo-asset

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# Bare React Native&lt;/span&gt;

npm &lt;span class="nb"&gt;install &lt;/span&gt;react-native-executorch-bare-resource-fetcher @dr.pogodin/react-native-fs @kesha-antonov/react-native-background-downloader

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Before you call any other API&lt;/strong&gt;, you must initialize ExecuTorch with that adapter, once, at your app's entry point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.tsx (or index.js), top level, runs once&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initExecutorch&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="s2"&gt;react-native-executorch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ExpoResourceFetcher&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="s2"&gt;react-native-executorch-expo-resource-fetcher&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;initExecutorch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;resourceFetcher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ExpoResourceFetcher&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skip this and the first model you load throws &lt;code&gt;ResourceFetcherAdapterNotInitialized&lt;/code&gt;. It's the most common setup mistake, and an easy one to miss because &lt;code&gt;initExecutorch&lt;/code&gt; lives at your entry point, far from where you actually call &lt;code&gt;useLLM&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One more, if you plan to bundle a model with the app via &lt;code&gt;require()&lt;/code&gt; instead of downloading it. Add the binary extensions to Metro:&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="c1"&gt;// metro.config.js&lt;/span&gt;

&lt;span class="nx"&gt;defaultConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assetExts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// exported model&lt;/span&gt;

&lt;span class="nx"&gt;defaultConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assetExts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// tokenizer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Loading a model
&lt;/h2&gt;

&lt;p&gt;Here's the whole "load an LLM" surface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;models&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useLLM&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="s2"&gt;react-native-executorch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Chat&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;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLLM&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lfm2_5_1_2b_instruct&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&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;code&gt;models.llm.*&lt;/code&gt; is a factory of pre-exported, ready-to-run models. One factory call gives the runtime everything it needs, already bundled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the model itself, in ExecuTorch's &lt;code&gt;.pte&lt;/code&gt; format, already converted&lt;/li&gt;
&lt;li&gt;the matching tokenizer&lt;/li&gt;
&lt;li&gt;the tokenizer config&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://huggingface.co/software-mansion" rel="noopener noreferrer"&gt;Software Mansion hosts the full lineup on HuggingFace&lt;/a&gt;, so you point at a model and the library handles fetching and wiring up the rest. No manual file juggling.&lt;/p&gt;

&lt;p&gt;I'm using LFM2.5 1.2B here because it's the library's own default and small enough to behave on mid-range hardware. You've got real choices though. The bundled lineup includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Text models:&lt;/strong&gt; Qwen 3 (0.6B / 1.7B / 4B), Llama 3.2 (1B / 3B), Phi 4 Mini, SmolLM 2, Hammer 2.1&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vision-capable:&lt;/strong&gt; Gemma 4 and LFM2.5-VL&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why I'd start small:&lt;/strong&gt; a 4B model is noticeably smarter and noticeably more likely to crash with an out-of-memory error on a budget Android. Pick the smallest model that clears your quality bar, then size up only if you must.&lt;/p&gt;

&lt;p&gt;The hook gives you state to drive your UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;llm.downloadProgress&lt;/code&gt;: 0 to 1 while the model downloads on first launch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;llm.isReady&lt;/code&gt;: flips true when it's loaded and usable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;llm.error&lt;/code&gt;: populated if anything blows up&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;llm.isGenerating&lt;/code&gt;: true while tokens are streaming&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;llm.response&lt;/code&gt;: the generated text, updated &lt;em&gt;token by token&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wiring the chat
&lt;/h2&gt;

&lt;p&gt;There are two ways to use this hook, and the docs name them well: &lt;strong&gt;functional&lt;/strong&gt; vs &lt;strong&gt;managed&lt;/strong&gt;. The distinction matters, so don't skim it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functional: you own the state
&lt;/h3&gt;

&lt;p&gt;You pass the full message array every time, you keep the history, you get a token stream back. Nothing is remembered for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;models&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useLLM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Message&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="s2"&gt;react-native-executorch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;View&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Button&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="s2"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Chat&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;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLLM&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lfm2_5_1_2b_instruct&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;handleGenerate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are a concise, helpful assistant.&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="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Explain a closure in one sentence.&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="c1"&gt;// resolves to the full string; llm.response updates live as it streams&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;final&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;done:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;final&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isReady&lt;/span&gt;&lt;span class="p"&gt;)&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="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;Loading model… &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;downloadProgress&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="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;);&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="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;Button&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Generate"&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="nx"&gt;handleGenerate&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;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&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;View&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the shape of &lt;code&gt;generate&lt;/code&gt;: it both returns a promise &lt;em&gt;and&lt;/em&gt; streams into &lt;code&gt;llm.response&lt;/code&gt;. So you render &lt;code&gt;llm.response&lt;/code&gt; for the live typewriter effect, and &lt;code&gt;await&lt;/code&gt; the return value when you need the finished string for, say, saving to a DB. Same call, two consumption patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managed: the library owns the state
&lt;/h3&gt;

&lt;p&gt;If you're building an actual back-and-forth chat, you don't want to hand-roll the history array. &lt;code&gt;sendMessage&lt;/code&gt; plus &lt;code&gt;messageHistory&lt;/code&gt; plus &lt;code&gt;configure&lt;/code&gt; does it for you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;useEffect&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="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useLLM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_SYSTEM_PROMPT&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="s2"&gt;react-native-executorch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ManagedChat&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;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLLM&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lfm2_5_1_2b_instruct&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;configure&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;llm&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="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;chatConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;DEFAULT_SYSTEM_PROMPT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; Keep answers short.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;

      &lt;span class="na"&gt;generationConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="na"&gt;topP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.9&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;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;configure&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;send&lt;/span&gt; &lt;span class="o"&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;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Who are you?&lt;/span&gt;&lt;span class="dl"&gt;"&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="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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messageHistory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&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;Text&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&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;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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;))&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;Button&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Send"&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="nx"&gt;send&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isReady&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;configure&lt;/code&gt; only affects the managed path. &lt;code&gt;chatConfig&lt;/code&gt; and &lt;code&gt;toolsConfig&lt;/code&gt; do nothing to &lt;code&gt;generate()&lt;/code&gt;. That's a subtle footgun: set a system prompt in &lt;code&gt;configure&lt;/code&gt;, then call &lt;code&gt;generate&lt;/code&gt; and wonder why it's ignored. Mode and config have to match.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My take:&lt;/strong&gt; use managed for chat, functional for one-shot transforms (summarize this, rewrite that, extract JSON from this). The text-enhancement tool I mentioned was pure functional. There's no conversation, just &lt;em&gt;input string to improved string&lt;/em&gt;, and managed state would've been overhead I'd have to fight.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reality check
&lt;/h2&gt;

&lt;p&gt;This is the section a docs-paraphrase can't write, so here's the honest list of what actually bit me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Dismounting mid-generation crashes the app.&lt;/strong&gt; Hard crash, not a warning. If the user navigates away while tokens are still streaming, you go down. The fix is to interrupt and wait:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before unmount / on a stop button&lt;/span&gt;

&lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;interrupt&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// then wait until llm.isGenerating === false before tearing down&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wire a stop button to &lt;code&gt;interrupt()&lt;/code&gt; and gate &lt;code&gt;isGenerating&lt;/code&gt; into your navigation guards. I learned this the way everyone does, with a back-button press during a long answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. First launch downloads a model. A big one.&lt;/strong&gt; These files run from roughly 700MB to over a gigabyte. The hosted models stream down on first use and cache in your app's documents directory, but if you don't render &lt;code&gt;downloadProgress&lt;/code&gt;, the user stares at a dead screen and force-quits. Build the loading UX &lt;em&gt;first&lt;/em&gt;, not last. And consider letting users pick a model, or bundle a small one for offline-from-install.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. RAM, not CPU, is your ceiling.&lt;/strong&gt; Crashes on cheaper devices are almost always out-of-memory, not slowness. Use quantized models. If you're testing on an Android emulator and it dies, bump the emulator's RAM before you blame your code. I wasted real time debugging "my" bug that was just a starved emulator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Expo Go will never work.&lt;/strong&gt; Said it above, saying it again, because you &lt;em&gt;will&lt;/em&gt; forget once and spend ten minutes confused. Native modules mean a custom dev build.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. One model runner at a time.&lt;/strong&gt; The architecture is built around a single active model instance. Don't try to stand up two &lt;code&gt;useLLM&lt;/code&gt; components side by side and expect both to run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Token batching exists for a reason.&lt;/strong&gt; A fast model can push 60+ tokens/sec, and if every token triggers a React re-render, your UI jank-fest begins. The library batches token emissions (default around 10 tokens or 80ms, whichever first). If generation feels choppy or your list stutters, tune &lt;code&gt;outputTokenBatchSize&lt;/code&gt; and &lt;code&gt;batchTimeInterval&lt;/code&gt; in &lt;code&gt;generationConfig&lt;/code&gt; rather than reaching for a &lt;code&gt;FlatList&lt;/code&gt; rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking it further
&lt;/h2&gt;

&lt;p&gt;Once the basic loop works, the library has more than chat:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tool calling.&lt;/strong&gt; Define functions the model can invoke (check weather, toggle a setting, hit a local API). You give it &lt;code&gt;tools&lt;/code&gt; plus an &lt;code&gt;executeToolCallback&lt;/code&gt;, and in managed mode it parses and runs the calls for you. Use a model whose chat template actually supports it. Hammer 2.1 is purpose-built for function calling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Structured output.&lt;/strong&gt; Need clean JSON instead of prose? There's a helper that turns a schema (plain JSON Schema or Zod) into formatting instructions, plus a validator to fix and check the result. This is how you'd build an offline "extract fields from this text" feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vision and audio.&lt;/strong&gt; Gemma 4 and LFM2.5-VL take a &lt;code&gt;capabilities&lt;/code&gt; array and accept an &lt;code&gt;imagePath&lt;/code&gt; or audio buffer on &lt;code&gt;sendMessage&lt;/code&gt;. On-device OCR into an LLM is a genuinely good offline-translation pattern.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RAG.&lt;/strong&gt; There's a companion &lt;code&gt;@react-native-rag/executorch&lt;/code&gt; package that plugs this LLM (and on-device embeddings) into a vector store for fully local retrieval-augmented generation. If your "model is one component" instinct is itching, that's the package that proves the point.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;Get the basic loop running, then start making it real. A sensible order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validate on real hardware first.&lt;/strong&gt; Clone the repo, run &lt;code&gt;examples/llm&lt;/code&gt; on an actual phone (not the simulator), and watch the first-launch download happen. The number that matters is cold-start time on a mid-range device, and it should drive your model choice more than any benchmark table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Study a real, shipped app.&lt;/strong&gt; The minimal example gets you running; a production app shows you the parts the docs skip. &lt;a href="https://github.com/software-mansion-labs/private-mind" rel="noopener noreferrer"&gt;Private Mind&lt;/a&gt; is Software Mansion's open-source, fully offline AI chatbot built on this library (it's live on the App Store and Play Store). Clone it and poke around: model downloading and management, on-device benchmarking, chat history, and custom assistant presets are all in there to learn from.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Check the benchmark pages before you commit to a model.&lt;/strong&gt; The docs publish real inference-time, memory, and model-size numbers per model and device. Pick from those, not from vibes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build the loading screen before the chat screen.&lt;/strong&gt; On-device AI lives or dies on that first impression, and it's the one thing the model code can't do for you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lazy-load with &lt;code&gt;preventLoad&lt;/code&gt;.&lt;/strong&gt; Every hook takes a &lt;code&gt;preventLoad&lt;/code&gt; flag so a model doesn't download or eat RAM until the user actually opens that feature. On a multi-feature app, this is the difference between a 1GB cold install and a fast one.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once it runs, the fun part is what you build on top. A few possibilities the library makes surprisingly easy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hybrid privacy: redact on-device, then go to the cloud.&lt;/strong&gt; &lt;code&gt;usePrivacyFilter&lt;/code&gt; is a local model that finds personal info (names, emails, phone numbers, addresses, even API keys) in text without it ever leaving the phone. Scrub that text locally, then send the safe version to a bigger cloud model. You get GPT-class quality without handing over the sensitive bits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A fully offline voice assistant.&lt;/strong&gt; Chain speech-to-text (Whisper is built in), then the LLM, then text-to-speech. Speak, get a spoken answer, no network anywhere in the loop. The library even supports streaming LLM output straight into speech as it generates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Point-the-camera answers.&lt;/strong&gt; Run on-device OCR on a photo of a sign, menu, or document, feed the extracted text to the LLM, and you've got an offline translator or document Q&amp;amp;A tool. Like a private, no-signal version of Google Lens.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Answers from the user's own notes.&lt;/strong&gt; The companion &lt;code&gt;@react-native-rag/executorch&lt;/code&gt; package wires the model and on-device embeddings into a local vector store, so the model can answer questions grounded in the user's documents, fully offline.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these is the same core idea pointed at a different problem: the model is one piece, and the product is the experience you wrap around it.&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;Docs: &lt;a href="https://docs.swmansion.com/react-native-executorch" rel="noopener noreferrer"&gt;docs.swmansion.com/react-native-executorch&lt;/a&gt; · &lt;/li&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/software-mansion/react-native-executorch" rel="noopener noreferrer"&gt;software-mansion/react-native-executorch&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>reactnative</category>
      <category>ai</category>
      <category>expo</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How Graphify Stopped My Team from Burning Thousands of Tokens Per Query</title>
      <dc:creator>Vikrant Negi</dc:creator>
      <pubDate>Sun, 21 Jun 2026 11:26:47 +0000</pubDate>
      <link>https://dev.to/vikrantnegi/how-graphify-stopped-my-team-from-burning-through-cursors-context-window-2d32</link>
      <guid>https://dev.to/vikrantnegi/how-graphify-stopped-my-team-from-burning-through-cursors-context-window-2d32</guid>
      <description>&lt;p&gt;Every time I asked Cursor about our auth flow, it would open 8-12 files, read through each one, and burn through tokens before even starting to answer. For a React Native codebase maintained by 6 developers, this adds up fast.&lt;/p&gt;

&lt;p&gt;I lead a front-end team building React Native apps. Cursor is our primary IDE. And while Cursor is great at understanding code, the way it retrieves context — by grepping and reading raw files sequentially — doesn't scale well on larger projects.&lt;/p&gt;

&lt;p&gt;Then I found &lt;a href="https://github.com/safishamsi/graphify" rel="noopener noreferrer"&gt;Graphify&lt;/a&gt;, and it fundamentally changed how our AI assistant interacts with our codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Graphify actually does
&lt;/h2&gt;

&lt;p&gt;Before I get to the setup, it's worth understanding the mechanism — because it's not just another Cursor plugin.&lt;/p&gt;

&lt;p&gt;Graphify pre-processes your entire project into a &lt;strong&gt;knowledge graph&lt;/strong&gt;. Think of it as a map of your codebase where every function, class, module, and concept becomes a node, and every relationship between them becomes an edge. When Cursor needs to answer a question, instead of reading 47 files to understand a flow, it runs &lt;code&gt;graphify query "auth flow"&lt;/code&gt; — a scoped subgraph lookup that returns only the relevant nodes and connections.&lt;/p&gt;

&lt;p&gt;The important part: &lt;strong&gt;code extraction happens entirely locally&lt;/strong&gt; via tree-sitter AST parsing. No API calls, no code leaving your machine. You only hit an LLM when processing docs, PDFs, or images. For a pure code project (which most React Native apps are), the extraction cost is basically zero.&lt;/p&gt;

&lt;p&gt;The output is three files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;graph.json&lt;/code&gt; — the full graph (the core artifact your assistant queries)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;graph.html&lt;/code&gt; — an interactive visualization you can explore in a browser&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GRAPH_REPORT.md&lt;/code&gt; — an architecture summary with god nodes, surprising connections, and suggested questions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That report alone is worth the setup. It finds connections between modules you didn't realize existed and surfaces the most-connected concepts in your project — the things everything flows through.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Graphify for Cursor
&lt;/h2&gt;

&lt;p&gt;I'm on an M1 MacBook Pro. Here's the exact setup that worked for me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;uv  &lt;span class="c"&gt;# if you don't have it already&lt;/span&gt;
uv tool &lt;span class="nb"&gt;install &lt;/span&gt;graphifyy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important: use &lt;code&gt;uv tool install&lt;/code&gt;, not &lt;code&gt;pip install&lt;/code&gt;.&lt;/strong&gt; On M1 Macs, pip can break Python path resolution because Graphify resolves the Python binary at runtime from a cached path. &lt;code&gt;uv&lt;/code&gt; isolates the environment and avoids this entirely. I learned this the hard way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build the graph
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;your-project
graphify extract &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First run takes a few minutes depending on codebase size. Since our projects are all code (no PDFs/docs), the entire extraction runs locally on tree-sitter — no API key needed for this step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install the Cursor integration
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;This writes a &lt;code&gt;.cursor/rules/graphify.mdc&lt;/code&gt; file with &lt;code&gt;alwaysApply: true&lt;/code&gt;. If you've worked with Cursor's rule system, you know what this means — it gets injected into every conversation automatically, telling Cursor to prefer &lt;code&gt;graphify query&lt;/code&gt; over reading raw source files.&lt;/p&gt;

&lt;p&gt;Quick note for anyone working with &lt;code&gt;.mdc&lt;/code&gt; files: a rule with &lt;code&gt;alwaysApply: false&lt;/code&gt; and no &lt;code&gt;globs&lt;/code&gt; and no &lt;code&gt;description&lt;/code&gt; will never auto-apply — it becomes manual &lt;code&gt;@&lt;/code&gt;-mention only. Graphify sets &lt;code&gt;alwaysApply: true&lt;/code&gt;, which is the correct move for a global project context rule.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set up the git hook
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;This installs a &lt;code&gt;post-commit&lt;/code&gt; hook. Every time anyone commits, it auto-rebuilds the graph using tree-sitter — fully local, takes seconds. It also sets up a git merge driver so if two devs commit graph updates in parallel, &lt;code&gt;graph.json&lt;/code&gt; gets union-merged automatically instead of leaving conflict markers.&lt;/p&gt;

&lt;p&gt;After this, you basically forget Graphify is running. The graph stays current with every commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rolling this out to a team
&lt;/h2&gt;

&lt;p&gt;This is where I had the most questions before adopting it, so let me cover the practical stuff.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to commit
&lt;/h3&gt;

&lt;p&gt;Add these to your repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graphify-out/
├── graph.json          # the core artifact
├── graph.html          # interactive visualization
├── GRAPH_REPORT.md     # architecture summary
├── manifest.json       # tracks extracted files (uses relative paths — portable)
└── cache/              # optional — commit for faster rebuilds

.cursor/rules/graphify.mdc    # the Cursor integration rule
.graphifyignore               # if you create one
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this to &lt;code&gt;.gitignore&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graphify-out/cost.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;cost.json&lt;/code&gt; tracks Graphify's own LLM API spend during extraction — not tokens saved in Cursor. It's local accounting, not a shared artifact.&lt;/p&gt;

&lt;h3&gt;
  
  
  Impact on teammates who don't use Graphify
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Zero.&lt;/strong&gt; This matters — Graphify is purely additive.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;graphify-out/&lt;/code&gt; folder is just inert data files. No build process depends on them, no CI breaks without them. The &lt;code&gt;.mdc&lt;/code&gt; file only affects Cursor users who have that rule active. If a dev without Graphify installed triggers the &lt;code&gt;post-commit&lt;/code&gt; hook, it fails silently (binary not found) and the commit goes through normally.&lt;/p&gt;

&lt;p&gt;You can adopt this incrementally. Install it yourself, commit &lt;code&gt;graphify-out/&lt;/code&gt;, and other devs benefit from the graph whenever they install Graphify later. No coordination needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommended team workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initial setup on &lt;code&gt;main&lt;/code&gt;&lt;/strong&gt; — do the first &lt;code&gt;graphify extract .&lt;/code&gt; on main and commit &lt;code&gt;graphify-out/&lt;/code&gt;. This becomes the shared baseline everyone pulls.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature branches update automatically&lt;/strong&gt; — the git hook rebuilds incrementally after every commit on any branch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On merge to main&lt;/strong&gt; — the graph from the feature branch comes with it. The merge driver handles concurrent updates.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One edge case: if someone runs a long-lived feature branch without the hook installed, their &lt;code&gt;graph.json&lt;/code&gt; will drift. A manual &lt;code&gt;graphify extract . --update&lt;/code&gt; before raising the MR resyncs it. I've considered adding this to our MR checklist, but honestly the hook handles 99% of cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  What can go wrong
&lt;/h2&gt;

&lt;p&gt;A few things I ran into or anticipated:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The M1 pip issue.&lt;/strong&gt; Already mentioned above — use &lt;code&gt;uv tool install&lt;/code&gt;, not pip. Wasted about 20 minutes debugging path resolution before figuring this out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can you actually measure token savings?&lt;/strong&gt; Honestly, not directly. Cursor doesn't expose per-conversation token usage. What you &lt;em&gt;can&lt;/em&gt; observe: response latency drops (graph queries are faster than multi-file reads), context window pressure reduces (fewer "context limit reached" moments), and Graphify logs every query at &lt;code&gt;~/.cache/graphify-queries.log&lt;/code&gt; with nodes returned and duration — so you get a sense of how targeted the retrieval is.&lt;/p&gt;

&lt;p&gt;The rough mental model: without Graphify, Cursor answering "how does auth connect to the API layer?" reads 8-12 files. A typical React Native file is ~200-400 tokens. That's ~3000 tokens just for context loading, before the answer. With Graphify, it reads a scoped subgraph — a fraction of that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;cost.json&lt;/code&gt; is not "tokens saved."&lt;/strong&gt; I initially confused this. &lt;code&gt;cost.json&lt;/code&gt; tracks what Graphify itself spent on LLM calls during extraction. For a code-only project, this is near zero. It has nothing to do with what Cursor saves in conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Graph drift on branch switches.&lt;/strong&gt; If you install the &lt;code&gt;post-commit&lt;/code&gt; hook but not the &lt;code&gt;post-checkout&lt;/code&gt; hook, switching branches won't rebuild the graph. The latest version of Graphify supports &lt;code&gt;post-checkout&lt;/code&gt; hooks too — check if &lt;code&gt;graphify hook install&lt;/code&gt; sets both up for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently
&lt;/h2&gt;

&lt;p&gt;If I were setting this up again:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run the initial extraction on a clean main branch first.&lt;/strong&gt; I initially ran it on a feature branch and had to redo it when I realized the team needed the baseline on main.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check &lt;code&gt;GRAPH_REPORT.md&lt;/code&gt; before sharing with the team.&lt;/strong&gt; It surfaces god nodes and surprising connections — some of which might reveal architectural issues you'd rather address before making the graph a shared artifact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skip committing &lt;code&gt;cache/&lt;/code&gt; initially.&lt;/strong&gt; It speeds up rebuilds but adds repo size. Start without it and add later if rebuild times become annoying.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Who should use this
&lt;/h2&gt;

&lt;p&gt;Graphify makes the most difference when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your codebase has &lt;strong&gt;50+ files&lt;/strong&gt; and multiple modules that interact&lt;/li&gt;
&lt;li&gt;You use Cursor (or Claude Code, Codex, Gemini CLI — it supports 10+ assistants)&lt;/li&gt;
&lt;li&gt;You're on a team and tired of your AI assistant not "knowing" the codebase between sessions&lt;/li&gt;
&lt;li&gt;You do code reviews and need to quickly understand how a change connects to the rest of the system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For small projects with 5-6 files, the graph adds structural clarity but the token savings are minimal — the files already fit in a context window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;uv
uv tool &lt;span class="nb"&gt;install &lt;/span&gt;graphifyy
&lt;span class="nb"&gt;cd &lt;/span&gt;your-project
graphify extract &lt;span class="nb"&gt;.&lt;/span&gt;
graphify cursor &lt;span class="nb"&gt;install&lt;/span&gt;  &lt;span class="c"&gt;# or the equivalent for your IDE&lt;/span&gt;
graphify hook &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's 5 commands to set up. The graph builds, your assistant starts using it, and the hook keeps it current. No config files to write, no services to run.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://github.com/safishamsi/graphify" rel="noopener noreferrer"&gt;Graphify repo&lt;/a&gt; for the full docs. If you're on Cursor specifically, the &lt;code&gt;.mdc&lt;/code&gt; integration is the smoothest path — it just works.&lt;/p&gt;

&lt;p&gt;If you've been feeling like Cursor "forgets" your codebase every conversation, or burns through context reading files it shouldn't need — Graphify is worth the 10 minutes to set up. It was for me.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm a React Native tech lead exploring AI-assisted development workflows. Find me on &lt;a href="https://twitter.com/vikrant_negi" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://github.com/vikrantnegi" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cursor</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>This is how earned money by blogging on Dev</title>
      <dc:creator>Vikrant Negi</dc:creator>
      <pubDate>Tue, 30 Jun 2020 11:40:52 +0000</pubDate>
      <link>https://dev.to/vikrantnegi/this-is-how-earned-money-by-blogging-on-dev-5bep</link>
      <guid>https://dev.to/vikrantnegi/this-is-how-earned-money-by-blogging-on-dev-5bep</guid>
      <description>&lt;p&gt;Making money by writing blogs in not new, many people do it for the living. I've also written few paid articles but most of the times, but mostly I write articles for sharing my knowledge, learning new things and help others to learn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back Story
&lt;/h2&gt;

&lt;p&gt;Recently, I wrote an article on DEV titled &lt;strong&gt;Become a VS Code Ninja with these Extensions and Tools [2020]&lt;/strong&gt;. The article was very well received in the DEV community and was an overnight success. The article got hundreds of reactions and views within few hours.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/vikrantnegi" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nqA2bTi6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://media.dev.to/cdn-cgi/image/width%3D150%2Cheight%3D150%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto/https%253A%252F%252Fdev-to-uploads.s3.amazonaws.com%252Fuploads%252Fuser%252Fprofile_image%252F59047%252F5f75c582-d590-4f39-adb5-22f143c232f3.jpg" alt="vikrantnegi"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/vikrantnegi/become-a-vs-code-ninja-with-these-extensions-and-tools-2020-1119" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Become a VS Code Ninja with these Extensions and Tools [2020]&lt;/h2&gt;
      &lt;h3&gt;Vikrant Negi ・ Jun 26 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#codenewbie&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#vscode&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Here is a screenshot of how many views I've received so far on my post (Jun 26 - Jun 30).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fioen21uf8k7dhsltf4d6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fioen21uf8k7dhsltf4d6.png" alt="Article Stats" width="800" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the next day, I received a mail from uphold about the funds being transferred into my account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm6si68os9umj820asc11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm6si68os9umj820asc11.png" alt="Payment Received Screen Shot" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first, I was surprised since I never thought that I would actually be getting paid for writing on DEV. &lt;/p&gt;

&lt;p&gt;Although, the money received was not that much but, the feeling of getting paid and appreciated for your hard work is beyond imagination.&lt;/p&gt;

&lt;h2&gt;
  
  
  How did I get paid?
&lt;/h2&gt;

&lt;p&gt;Did you know the Dev recently got Web Monetized?&lt;/p&gt;

&lt;p&gt;Web Monetization is a standard that provides content creators with an alternative solution to get paid for the content they share on the web. When a user visits a monetized web page, their browser (if it supports Web Monetization) may send micropayments to the site.&lt;/p&gt;

&lt;p&gt;Read more about Web Monetization on DEV in following post:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/devteam" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SsFI-Xwo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://media.dev.to/cdn-cgi/image/width%3D150%2Cheight%3D150%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto/https%253A%252F%252Fdev-to-uploads.s3.amazonaws.com%252Fuploads%252Forganization%252Fprofile_image%252F1%252Fd908a186-5651-4a5a-9f76-15200bc6801f.jpg" alt="The DEV Team" width="150" height="150"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GMRzL-jB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://media.dev.to/cdn-cgi/image/width%3D150%2Cheight%3D150%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto/https%253A%252F%252Fdev-to-uploads.s3.amazonaws.com%252Fuploads%252Fuser%252Fprofile_image%252F1075%252F1c1975ce-97e8-401f-b99f-1ea88f9cae3e.jpeg" alt="" width="150" height="150"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/devteam/dev-is-now-web-monetized-21db" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;DEV is now Web Monetized&lt;/h2&gt;
      &lt;h3&gt;Peter Kim Frank for The DEV Team ・ Jun 10 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webmonetization&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#gftwhackathon&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#coil&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#meta&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;You can now web-monetize your DEV posts. You will receive micropayments for time spent reading your posts directly. So the more people read your posts the more money you will make.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I enable it for my DEV account?
&lt;/h2&gt;

&lt;p&gt;In order to start generating micro-payments with Web Monetization on your DEV content, just following these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up a wallet (here are a &lt;a href="https://webmonetization.org/docs/ilp-wallets"&gt;few options&lt;/a&gt;). Dev recommends UpHold.&lt;/li&gt;
&lt;li&gt;Once your wallet is set up, you'll receive a Payment Pointer address. If signed up for uphold you can find your Payment Pointer address &lt;a href="https://webmonetization.org/docs/uphold#find-your-payment-pointer"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Go to your DEV &lt;a href="https://dev.to/settings/misc"&gt;account settings&lt;/a&gt; and add your Payment Pointer to the Web Monetization section&lt;/li&gt;
&lt;li&gt;That's it. You'll now receive a micro-payment every time a monetized browsers visit your your profile page and posts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more on how to web-monetize your DEV posts go to the following DEV post:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/devteam" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SsFI-Xwo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://media.dev.to/cdn-cgi/image/width%3D150%2Cheight%3D150%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto/https%253A%252F%252Fdev-to-uploads.s3.amazonaws.com%252Fuploads%252Forganization%252Fprofile_image%252F1%252Fd908a186-5651-4a5a-9f76-15200bc6801f.jpg" alt="The DEV Team" width="150" height="150"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LBrAYN44--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://media.dev.to/cdn-cgi/image/width%3D150%2Cheight%3D150%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto/https%253A%252F%252Fdev-to-uploads.s3.amazonaws.com%252Fuploads%252Fuser%252Fprofile_image%252F1%252Ff451a206-11c8-4e3d-8936-143d0a7e65bb.png" alt="" width="150" height="150"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/devteam/you-can-now-web-monetize-your-dev-posts-but-don-t-get-your-hopes-up-too-quickly-goc" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;You can now web-monetize your DEV posts! (But don't get your hopes up too quickly)&lt;/h2&gt;
      &lt;h3&gt;Ben Halpern for The DEV Team ・ Jun 10 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webmonetization&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#gftwhackathon&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#coil&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#meta&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Future is bright on DEV
&lt;/h2&gt;

&lt;p&gt;Earnings at this point is going to be quite small, but there’s a bright future ahead as more people and platforms begin to adopt this standard. As large percentage of DEV authors will have enabled their own payment pointer, monetized browsers will be able to directly reward their work.&lt;/p&gt;

&lt;p&gt;Happy coding! 🙏 and Happy monetizing 🤑&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;p&gt;Yay!! I received another payment mail from the uphold. 🤑&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Follow me on Twitter for more hidden gems &lt;a href="https://twitter.com/vikrant_negi"&gt;@vikrant_negi&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;Cover image credit - Photo by &lt;a href="https://unsplash.com/@sharonmccutcheon?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Sharon McCutcheon&lt;/a&gt; on Unsplash&lt;/small&gt;&lt;/p&gt;

</description>
      <category>webmonetization</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Become a VS Code Ninja with these Extensions and Tools [2020]</title>
      <dc:creator>Vikrant Negi</dc:creator>
      <pubDate>Fri, 26 Jun 2020 19:17:40 +0000</pubDate>
      <link>https://dev.to/vikrantnegi/become-a-vs-code-ninja-with-these-extensions-and-tools-2020-1119</link>
      <guid>https://dev.to/vikrantnegi/become-a-vs-code-ninja-with-these-extensions-and-tools-2020-1119</guid>
      <description>&lt;p&gt;VS Code is undoubtedly the best editor out there especially when it comes to writing javascript. It is fast, feature rich and has huge pool of extensions available which greatly enhances developer experience.&lt;/p&gt;

&lt;p&gt;I've been using VS Code for the past 4 years and over these years I came across many these extensions that I would like to share with you. I'm so addicted to these extensions that my developer life would be incomplete without them.&lt;/p&gt;

&lt;p&gt;Here is a list of my VS Code extensions:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=atomiks.moonlight"&gt;Moonlight Theme&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I've a habit of changing themes quite often and this is the current theme that I'm using these days. Colors are not very light and are easy on eyes both during day and night.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gq6e5DsM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/atomiks/moonlight-vscode-theme/master/preview.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gq6e5DsM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/atomiks/moonlight-vscode-theme/master/preview.png" alt="Moonlight Theme" width="800" height="733"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-rename-tag"&gt;Auto Rename Tag&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Automatically rename paired HTML/XML tag, same as Visual Studio IDE does.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eWea0-We--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://raw.githubusercontent.com/formulahendry/vscode-auto-rename-tag/master/images/usage.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eWea0-We--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://raw.githubusercontent.com/formulahendry/vscode-auto-rename-tag/master/images/usage.gif" alt="Auto Rename Tag" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=christian-kohler.path-intellisense"&gt;Path Intellisense&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Visual Studio Code plugin that autocompletes filenames. Very helpful in React projects when importing components from different folders.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/iaHeUiDeTUZuo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/iaHeUiDeTUZuo.gif" alt="Path Intellisense" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=mrmlnc.vscode-scss"&gt;SCSS IntelliSense&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Advanced autocompletion and refactoring support for SCSS. Must have for front-end developers that use Sass.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fszt3wxhfngzeiqcneiwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fszt3wxhfngzeiqcneiwg.png" alt="SCSS IntelliSense" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=JakeWilson.vscode-placeholder-images"&gt;Placeholder Images&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Generate and insert placeholder images into your HTML. Easy to find placeholders images directly in the VS Code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cNh8O_k2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://raw.githubusercontent.com/Jakobud/vscode-placeholder-images/master/images/example.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cNh8O_k2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://raw.githubusercontent.com/Jakobud/vscode-placeholder-images/master/images/example.gif" alt="Placeholder Images" width="692" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer"&gt;Live Server&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Launch a development local Server with live reload feature for static &amp;amp; dynamic pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q_KwLl8P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://raw.githubusercontent.com/ritwickdey/vscode-live-server/master/images/Screenshot/vscode-live-server-animated-demo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q_KwLl8P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://raw.githubusercontent.com/ritwickdey/vscode-live-server/master/images/Screenshot/vscode-live-server-animated-demo.gif" alt="Live Server" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode"&gt;Prettier - Code formatter&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Code formatter using prettier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7ya6yprr6rmlvualclgs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7ya6yprr6rmlvualclgs.png" alt="Prettier - Code formatter" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=xabikos.ReactSnippets"&gt;Reactjs code snippets&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Code snippets for Reactjs development in ES6 syntax.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sqhZ9fAy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://raw.githubusercontent.com/xabikos/vscode-react/master/images/component.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sqhZ9fAy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://raw.githubusercontent.com/xabikos/vscode-react/master/images/component.gif" alt="Reactjs code snippets" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync"&gt;Settings Sync&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Must have extension in my opinion, it synchronize all your VS Code Settings, Snippets, Themes, File Icons, Launch, Keybindings, Workspaces and Extensions Across Multiple Machines Using GitHub Gist.&lt;/p&gt;

&lt;p&gt;Very helpful in case you change your development machine and want to import all your previous VS Code data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhws0lt2izval51kh1kn2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhws0lt2izval51kh1kn2.png" alt="Settings Sync" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=aaron-bond.better-comments"&gt;Better Comments&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Improve your code commenting by annotating with alert, informational, TODOs, and more!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zm9m8obi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/aaron-bond/better-comments/master/images/better-comments.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zm9m8obi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/aaron-bond/better-comments/master/images/better-comments.PNG" alt="Better Comments" width="459" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer"&gt;Bracket Pair Colorizer&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A customizable extension for colorizing matching brackets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--risYyGHZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/CoenraadS/BracketPair/master/images/example.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--risYyGHZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/CoenraadS/BracketPair/master/images/example.png" alt="Bracket Pair Colorizer" width="625" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker"&gt;Code Spell Checker&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you are like me who can write a single word without mistake this extension is a must have. Checks your code for spell errors and provide suggestions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gqd8Ec5p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://raw.githubusercontent.com/streetsidesoftware/vscode-spell-checker/master/packages/client/images/suggestions.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gqd8Ec5p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://raw.githubusercontent.com/streetsidesoftware/vscode-spell-checker/master/packages/client/images/suggestions.gif" alt="Code Spell Checker" width="736" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint"&gt;ESLint&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Integrates ESLint JavaScript into VS Code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fedxtlpjek3j7o9yalchy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fedxtlpjek3j7o9yalchy.png" alt="ESLint" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost"&gt;Import Cost&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Display import/require package size in the editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YRxJvnXi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://file-wkbcnlcvbn.now.sh/import-cost.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YRxJvnXi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://file-wkbcnlcvbn.now.sh/import-cost.gif" alt="Import Cost" width="800" height="139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=WallabyJs.quokka-vscode"&gt;Quokka.js&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Live Scratchpad for JavaScript. Write Javascript and see your outputs in the editor itself. Also has a Interactive Examples which are useful for both experienced developers (as references) and for new developers (to learn).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P50dZQdF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://quokkajs.com/assets/img/main-video.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P50dZQdF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://quokkajs.com/assets/img/main-video.gif" alt="Quokka.js" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=TabNine.tabnine-vscode"&gt;TabNine&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Another must have extension. TabNine is a all-language autocompleter — which uses machine learning to help you write code faster.&lt;/p&gt;

&lt;p&gt;This is a Dark Magic extension, after installing and using it for sometime it gives very accurate suggestions which leave you awestruck.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm1syjq6v8wdxid9kwe9v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm1syjq6v8wdxid9kwe9v.png" alt="TabNine" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=jpoissonnier.vscode-styled-components"&gt;vscode-styled-components&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Syntax highlighting and IntelliSense for styled-components.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zlN5hSIW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/styled-components/vscode-styled-components/master/demo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zlN5hSIW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/styled-components/vscode-styled-components/master/demo.png" alt="vscode-styled-components" width="600" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode"&gt;Visual Studio IntelliCode&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The Visual Studio IntelliCode extension provides AI-assisted development features for Python, TypeScript/JavaScript and Java developers in Visual Studio Code, with insights based on understanding your code context combined with machine learning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HJcmXlgG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://docs.microsoft.com/en-us/visualstudio/intellicode/media/python-intellicode.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HJcmXlgG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://docs.microsoft.com/en-us/visualstudio/intellicode/media/python-intellicode.gif" alt="Visual Studio IntelliCode" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Bonus
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/sozercan/OpenInCode"&gt;OpenInCode&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;📂 Finder toolbar app to open current folder in Visual Studio Code&lt;/p&gt;

&lt;h1&gt;
  
  
  Closing
&lt;/h1&gt;

&lt;p&gt;I'll keep updating this list with new extensions that I find. Feel free to suggest the extensions that I might have missing. I would love to know what new extensions developers are using.&lt;/p&gt;

&lt;p&gt;I've also created a git repo with the VS Code extensions and settings that I frequently use. Find the repo &lt;a href="https://github.com/vikrantnegi/vscode-personal-preference-setting"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;Cover image credit - Photo by &lt;a href="https://unsplash.com/@flowforfrank?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Ferenc Almasi&lt;/a&gt; on Unsplash&lt;/small&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>vscode</category>
    </item>
    <item>
      <title>Build Facebook-Like Placeholder Loaders in React Native</title>
      <dc:creator>Vikrant Negi</dc:creator>
      <pubDate>Thu, 20 Feb 2020 07:07:22 +0000</pubDate>
      <link>https://dev.to/vikrantnegi/build-facebook-like-placeholder-loaders-in-react-native-20d4</link>
      <guid>https://dev.to/vikrantnegi/build-facebook-like-placeholder-loaders-in-react-native-20d4</guid>
      <description>&lt;p&gt;A good user experience is what separates a awesome app from a regular one. Users expect their apps to be blazing fast since no one enjoys waiting. When building mobile apps, we often use loaders, progress bars, loading indicators to tell users when something is happening or loading.&lt;/p&gt;

&lt;p&gt;The latest trend is to show placeholder/skeleton screens as loaders. This pattern of using placeholder improves the user's perceived experience when waiting for something to load. You might have seen these kinds of loaders in apps like Facebook and Netflix.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YarQEIfc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6ugpxa5n6qri5hbpm1a0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YarQEIfc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6ugpxa5n6qri5hbpm1a0.gif" alt="Netflix Placeholder Loader"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Loaders in React Native
&lt;/h2&gt;

&lt;p&gt;In most cases, using the good Ol' &lt;a href="https://facebook.github.io/react-native/docs/activityindicator"&gt;&lt;code&gt;ActivityIndicator&lt;/code&gt;&lt;/a&gt; along with React Native modal would suffice. However, as a user and as a developer, I find them to be too mundane and old fashioned.&lt;/p&gt;

&lt;p&gt;To make these loaders interesting, I created a React Native package that uses Airbnb's Lottie and &lt;a href="https://facebook.github.io/react-native/docs/modal#docsNav"&gt;Modals&lt;/a&gt; to create beautiful animated loaders. If you want to read more more on how to use it read &lt;a href="https://medium.com/better-programming/how-to-create-a-beautifully-animated-loader-in-react-native-21da37a8f6b0"&gt;this&lt;/a&gt; article.&lt;/p&gt;

&lt;p&gt;In this article we will be learn how to implement placeholder screens using &lt;a href="https://github.com/mfrachet/rn-placeholder"&gt;rn-placeholder&lt;/a&gt; library. We will also use Google Books API to fetch some books data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow this tutorial, please make sure you have the following installed on your local development environment and have access to the services mentioned below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/"&gt;Node.js&lt;/a&gt; (&amp;gt;=8.x.x) with npm/yarn installed.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.expo.io/versions/latest/workflow/expo-cli/?"&gt;expo-cli&lt;/a&gt; (&amp;gt;=3.0.4)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make sure to update &lt;code&gt;expo-cli&lt;/code&gt; if you haven't updated in a while since &lt;code&gt;expo&lt;/code&gt; releases are quickly out of date.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Let's set up a new Expo project using expo-cli.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;expo init placeholderLoading
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Choose blank template and hit &lt;code&gt;Enter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Then it will ask to name the project, type &lt;code&gt;Placeholder Loading&lt;/code&gt; and hit &lt;code&gt;Enter&lt;/code&gt; again.&lt;/li&gt;
&lt;li&gt;Lastly, it will ask you to press &lt;code&gt;Y&lt;/code&gt; to install dependencies with &lt;code&gt;yarn&lt;/code&gt; or &lt;code&gt;n&lt;/code&gt; to install dependencies with &lt;code&gt;npm&lt;/code&gt;. Press &lt;code&gt;y&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will create a new React Native app using expo-cli.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running App and Installing Dependencies
&lt;/h2&gt;

&lt;p&gt;Go into the project directory that we just created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;placeholderLoading
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To run the project type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Press &lt;code&gt;i&lt;/code&gt; to run the iOS Simulator. This will automatically run the iOS Simulator even if it's not opened.&lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;a&lt;/code&gt; to run the Android Emulator. Note that the emulator must be installed and started already before typing a otherwise it will throw an error in the terminal.&lt;/p&gt;

&lt;p&gt;You can also run the app in your device by installing &lt;code&gt;expo&lt;/code&gt; app from the app store and then scanning the QR code.&lt;/p&gt;

&lt;p&gt;Now, install &lt;code&gt;rn-placeholder&lt;/code&gt; and &lt;code&gt;react-native-responsive-dimensions&lt;/code&gt; packages&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add rn-placeholder react-native-responsive-dimensions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;rn-placeholder&lt;/code&gt; will help us display some placeholder stuff before rendering our text or media content.&lt;br&gt;
And, &lt;code&gt;react-native-responsive-dimensions&lt;/code&gt; will provide us with responsive height and width that automatically adjust themselves based on the screen size of the device.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating Components
&lt;/h2&gt;

&lt;p&gt;Now we'll create two components &lt;code&gt;BookCardComponent&lt;/code&gt; and &lt;code&gt;BookCardPlaceholderComponent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is the code for &lt;code&gt;BookCardComponent&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BookCardComponent&lt;/span&gt; &lt;span class="o"&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onPress&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&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;shadow&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TouchableOpacity&lt;/span&gt;
        &lt;span class="nx"&gt;onPress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
          &lt;span class="na"&gt;flexDirection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;row&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
        &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt;
          &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
            &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;responsiveHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;responsiveWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;marginRight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
          &lt;span class="p"&gt;}}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Image&lt;/span&gt;
            &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
            &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
              &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;resizeMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contain&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}}&lt;/span&gt;
            &lt;span class="nx"&gt;imageStyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
          &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt;
          &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
            &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
          &lt;span class="p"&gt;}}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&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;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;
            &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
            &lt;span class="nx"&gt;numberOfLines&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;ellipsizeMode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tail&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/TouchableOpacity&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;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;Code for &lt;code&gt;BookCardPlaceholderComponent&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BookCardPlaceholderComponent&lt;/span&gt; &lt;span class="o"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Placeholder&lt;/span&gt;
    &lt;span class="nx"&gt;Animation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ShineOverlay&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
      &lt;span class="na"&gt;marginVertical&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;marginHorizontal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
    &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="nx"&gt;Left&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PlaceholderMedia&lt;/span&gt;
        &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{[&lt;/span&gt;
          &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;responsiveWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;responsiveHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&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="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PlaceholderLine&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;responsiveHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PlaceholderLine&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;responsiveHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PlaceholderLine&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Placeholder&lt;/span&gt;&lt;span class="err"&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;The &lt;code&gt;BookCardPlaceholderComponent&lt;/code&gt; will be rendered initially until we received data from the Google Books API and after receive data we'll use the &lt;code&gt;BookCardComponent&lt;/code&gt; for rendering the books data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update App.js
&lt;/h2&gt;

&lt;p&gt;We'll be using React &lt;a href="https://reactjs.org/docs/hooks-intro.html"&gt;Hooks&lt;/a&gt; in this tutorial but you can easily convert it for classes.&lt;/p&gt;

&lt;p&gt;Add the following code to your &lt;code&gt;App.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&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;books&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBooks&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="p"&gt;([...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;fill&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;isDataFetched&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDataFetched&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="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.googleapis.com/books/v1/volumes/?maxResults=30&amp;amp;q=danbrown&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="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseJson&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;items&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;responseJson&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;booksList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="na"&gt;volumeInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imageLinks&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bookId&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;book&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="nx"&gt;bookId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageLinks&lt;/span&gt;
              &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;imageLinks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt;
              &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.ibb.co/YLC0nQQ/not-found.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authors&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/,/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&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="nx"&gt;setBooks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;booksList&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;setDataFetched&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&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="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;renderBookComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;item&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bookId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;item&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;BookCardComponent&lt;/span&gt;
        &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;bookId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;authors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;renderX&lt;/span&gt; &lt;span class="o"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FlatList&lt;/span&gt;
      &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;renderItem&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;renderBookComponent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;keyExtractor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bookId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;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;renderPlaceholders&lt;/span&gt; &lt;span class="o"&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;books&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BookCardPlaceholder&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;SafeAreaView&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&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="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;isDataFetched&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;renderX&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;renderPlaceholders&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/SafeAreaView&lt;/span&gt;&lt;span class="err"&gt;&amp;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;First, we setup some initial state using &lt;code&gt;useState&lt;/code&gt; hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&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;books&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBooks&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="p"&gt;([...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;fill&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;isDataFetched&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDataFetched&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="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;books&lt;/code&gt; state we'll update all the books that we'll receive from the API and for the initial state we created an array of empty 10 objects.&lt;/p&gt;

&lt;p&gt;We also initialized &lt;code&gt;isDataFetched&lt;/code&gt; state and set its initial value &lt;code&gt;false&lt;/code&gt;. It will be used to track the status of the data received from the API. When we received the data and done with the data manipulation, we'll set its value to &lt;code&gt;true&lt;/code&gt; by using &lt;code&gt;setDataFetched&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the next step, we'll use &lt;code&gt;useEffect&lt;/code&gt; hook to call the Google Books API and update our respective states with the data received.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.googleapis.com/books/v1/volumes/?maxResults=30&amp;amp;q=danbrown&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="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseJson&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;items&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;responseJson&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;booksList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="na"&gt;volumeInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imageLinks&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bookId&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;book&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="nx"&gt;bookId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageLinks&lt;/span&gt;
            &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;imageLinks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt;
            &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.ibb.co/YLC0nQQ/not-found.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authors&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/,/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&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="nx"&gt;setBooks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;booksList&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;setDataFetched&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&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="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;Now, in the return we'll make use of the &lt;code&gt;isDataFetched&lt;/code&gt; state to conditionally render the components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;isDataFetched&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;renderX&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;renderPlaceholders&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 &lt;code&gt;renderX()&lt;/code&gt; we'll return a &lt;code&gt;FlatList&lt;/code&gt; which will render the list of Books using &lt;code&gt;renderBookComponent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;renderPlaceholders()&lt;/code&gt; we'll render &lt;code&gt;BookCardPlaceholder&lt;/code&gt; using the map function. This is what the users will see during the data fetching.&lt;/p&gt;

&lt;p&gt;So during the data fetching &lt;code&gt;BookCardPlaceholder&lt;/code&gt; will be rendered and when the data is fetched successfully &lt;code&gt;BookCardComponent&lt;/code&gt; will be rendered by the &lt;code&gt;FlatList&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is how the final app looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eFFyL2UZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xsfi84sddsahuaim0jcr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eFFyL2UZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xsfi84sddsahuaim0jcr.gif" alt="Finished app demo gif"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;We have successfully created a React Native app that uses &lt;code&gt;rn-placeholder&lt;/code&gt; to show placeholder as loaders during data fetching just like facebook, Netflix and other popular apps.&lt;/p&gt;

&lt;p&gt;This is just a simple implementation of placeholders screens as loaders. You can customize these placeholder components according to your need or app theme.&lt;/p&gt;

&lt;p&gt;Find the source code in the Github repo &lt;a href="https://github.com/vikrantnegi/react-native-placeholder-loading"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;p&gt;I've also created a Open source Book Searching React Native app in which I used these placeholder components as loaders. Feel free to have a look at its source code &lt;a href="https://github.com/vikrantnegi/RN-Book-Search"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>reactnativeloaders</category>
      <category>facebookplaceholderloaders</category>
      <category>netflixloaders</category>
    </item>
    <item>
      <title>Creating a Multi-Language App in React Native</title>
      <dc:creator>Vikrant Negi</dc:creator>
      <pubDate>Mon, 08 Jul 2019 17:12:46 +0000</pubDate>
      <link>https://dev.to/vikrantnegi/creating-a-multi-language-app-in-react-native-1joj</link>
      <guid>https://dev.to/vikrantnegi/creating-a-multi-language-app-in-react-native-1joj</guid>
      <description>&lt;p&gt;Language has always been an essential part of any business. As the business grows it becomes important for the business to expand in different countries and regions. To achieve success in these local regions it is important to provide localization.&lt;/p&gt;

&lt;p&gt;When it comes to the mobile app, the conditions are no different. As the app users expand to different countries, it becomes important to provide the users with the ability to use the app in their native languages.&lt;/p&gt;

&lt;p&gt;In this article, we are going to build a React Native app that supports multi-language using &lt;a href="https://github.com/react-native-community/react-native-localize"&gt;react-native-localize&lt;/a&gt; package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;This tutorial requires basic knowledge of React Native. To set up your development machine, follow the official guide &lt;a href="https://facebook.github.io/react-native/docs/0.59/getting-started"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To make sure we are on the same page, following are the versions used in this tutorial -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node v10.15.0&lt;/li&gt;
&lt;li&gt;npm 6.4.1&lt;/li&gt;
&lt;li&gt;yarn 1.16.0&lt;/li&gt;
&lt;li&gt;react-native 0.59.9&lt;/li&gt;
&lt;li&gt;react-native-localize 1.1.3&lt;/li&gt;
&lt;li&gt;i18n-js 3.3.0&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;We'll be building a React Native app which will support &lt;strong&gt;English&lt;/strong&gt;, &lt;strong&gt;French&lt;/strong&gt; and &lt;strong&gt;Arabic&lt;/strong&gt; language.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to have a look at the source code right away, here is the Github &lt;a href="https://github.com/vikrantnegi/react-native-multi-language-app"&gt;link&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To create a new project using &lt;code&gt;react-native-cli&lt;/code&gt;, type the following in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;react-native init multiLanguage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;multiLanguage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Add required libraries
&lt;/h4&gt;

&lt;p&gt;Install &lt;code&gt;react-native-localize&lt;/code&gt; by typing the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add react-native-localize
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and then link it using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;react-native &lt;span class="nb"&gt;link &lt;/span&gt;react-native-localize
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you face any error during installation, check the installation instructions &lt;a href="https://github.com/react-native-community/react-native-localize#setup"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;react-native-localize&lt;/code&gt; lib gives you access to a lot of localization related device constants, but does not come with an i18n lib.&lt;/p&gt;

&lt;p&gt;We'll use &lt;a href="https://github.com/fnando/i18n-js"&gt;&lt;code&gt;I18n.js&lt;/code&gt;&lt;/a&gt; to provide a I18n translations on the JavaScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add i18n-js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since &lt;code&gt;i18n-js&lt;/code&gt; does not seem to provides any cache / memoization we'll use &lt;code&gt;lodash.memoize&lt;/code&gt; for the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add lodash.memoize
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Add Translations
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;translations&lt;/code&gt; directory inside &lt;code&gt;src&lt;/code&gt; and then create, three JSON files as below for each language.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;en.json&lt;/code&gt; for English&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fr.json&lt;/code&gt; for French&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ar.json&lt;/code&gt; for Arabic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Inside these files will be JSON object with keys and values.&lt;/p&gt;

&lt;p&gt;Key will the be same for each language and will be used in the app to display text.&lt;/p&gt;

&lt;p&gt;The value will be the actual translation that we want to show to the user and will be different for each language.&lt;/p&gt;

&lt;p&gt;For English:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&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;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For French:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&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;Salut le Monde!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For Arabic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&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;أهلاً بالعالم&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Similarly, you can add more key-value pairs for every text that will be used in the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add Main Code
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;App.js&lt;/code&gt; file and the following imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;RNLocalize&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native-localize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;i18n&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i18n-js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;memoize&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lodash.memoize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Use for caching/memoize for better performance&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;I18nManager&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SafeAreaView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;ScrollView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;View&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="s2"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After that, we'll add some helper functions and constants that we'll use later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;translationGetters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// lazy requires (metro bundler does not support symlinks)&lt;/span&gt;
  &lt;span class="na"&gt;ar&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;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/translations/ar.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;en&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;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/translations/en.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;fr&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;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/translations/fr.json&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;translate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;memoize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&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;i18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&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;config&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&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;setI18nConfig&lt;/span&gt; &lt;span class="o"&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="c1"&gt;// fallback if no available language fits&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;languageTag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isRTL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;languageTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isRTL&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;RNLocalize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findBestAvailableLanguage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;translationGetters&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// clear translation cache&lt;/span&gt;
  &lt;span class="nx"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// update layout direction&lt;/span&gt;
  &lt;span class="nx"&gt;I18nManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forceRTL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isRTL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// set i18n-js config&lt;/span&gt;
  &lt;span class="nx"&gt;i18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;translations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;languageTag&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;translationGetters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;languageTag&lt;/span&gt;&lt;span class="p"&gt;]()&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;i18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;languageTag&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;Now, we'll create our &lt;code&gt;App&lt;/code&gt; class component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&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="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;setI18nConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// set initial config&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;RNLocalize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&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;handleLocalizationChange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;componentWillUnmount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;RNLocalize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&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;handleLocalizationChange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;handleLocalizationChange&lt;/span&gt; &lt;span class="o"&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="nx"&gt;setI18nConfig&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;forceUpdate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;SafeAreaView&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&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;safeArea&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&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;value&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;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/SafeAreaView&lt;/span&gt;&lt;span class="err"&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;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;safeArea&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&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 our constructor method, we called &lt;code&gt;setI18nConfig()&lt;/code&gt; which will set the initial configuration.&lt;/p&gt;

&lt;p&gt;Then in &lt;code&gt;componentDidMount()&lt;/code&gt; we'll add an event listener which will listen for any changes and call &lt;code&gt;handleLocalizationChange()&lt;/code&gt; if any changes occur.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;handleLocalizationChange()&lt;/code&gt; method does two things one is that it fires &lt;code&gt;setI18nConfig()&lt;/code&gt; and &lt;code&gt;forceUpdate()&lt;/code&gt;. This is necessary for Android devices as the component needs to be re-render for the changes to be visible.&lt;/p&gt;

&lt;p&gt;We will remove the listener in &lt;code&gt;componentWillUnmount()&lt;/code&gt; lifecycle method.&lt;/p&gt;

&lt;p&gt;Finally, in &lt;code&gt;render()&lt;/code&gt; we'll print out &lt;code&gt;hello&lt;/code&gt; by using &lt;code&gt;translate()&lt;/code&gt; and passing our &lt;code&gt;key&lt;/code&gt; as a parameter into it. It will then automatically figure out the language and the text that needs to be shown for that language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the App
&lt;/h2&gt;

&lt;p&gt;Now its time to see our if the translations are working.&lt;/p&gt;

&lt;p&gt;Run your app in simulator or emulator by typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;react-native run-ios
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;react-native run-android
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It should be something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gMyDmYLF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/cdi7x7lta93kbzjo0t80.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gMyDmYLF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/cdi7x7lta93kbzjo0t80.png" alt="Hello World English"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, change your device language setting to French and open your app again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Bhd_OcQS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/smekwd55qpvnlgvewzzo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Bhd_OcQS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/smekwd55qpvnlgvewzzo.png" alt="Hello World French"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, you can change your language setting to Arabic and see hello in Arabic.&lt;/p&gt;

&lt;p&gt;So far so great.&lt;/p&gt;

&lt;p&gt;But what happens if I choose some random language whose translation is not added in the app? What language will it fall back to?&lt;/p&gt;

&lt;p&gt;Well as it turns out the goal of &lt;code&gt;findBestAvailableLanguage&lt;/code&gt; is to return the best available translation. So It will look at your language preference setting to figure out the fallback language.&lt;/p&gt;

&lt;p&gt;If you go to the &lt;strong&gt;Language &amp;amp; Region&lt;/strong&gt; setting in your iOS simulator you can see the preference order of the languages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_kMTzGUN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jwd7qsj50g2rcff925r0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_kMTzGUN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/jwd7qsj50g2rcff925r0.png" alt="Language Preference Setting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the language chosen is not in the preferred language &lt;code&gt;findBestAvailableLanguage&lt;/code&gt; returns &lt;code&gt;undefined&lt;/code&gt; (so the retained value will be your &lt;a href="https://github.com/vikrantnegi/react-native-multi-language-app/blob/master/App.js#L25"&gt;fallback&lt;/a&gt;) because none of the user's preferred languages are available in your translations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;react-native-localize&lt;/code&gt; has API that can provides access to lot localization related device constants. Be sure to check out the full APIs available in the &lt;a href="https://github.com/react-native-community/react-native-localize#api"&gt;docs&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Adding multi-language support is that easy. You can now use react-native-localize to easily provide multiple language support in your app which can help in increasing user's app usage.&lt;/p&gt;

&lt;p&gt;Find the source code in the Github repo &lt;a href="https://github.com/vikrantnegi/react-native-multi-language-app"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally published on &lt;a href="https://medium.com/better-programming/creating-a-multi-language-app-in-react-native-9828b138c274"&gt;Medium&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you like this article, go ahead and show some love and share.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>reactnativelocalize</category>
      <category>i18n</category>
      <category>multilangugae</category>
    </item>
    <item>
      <title>React Native, Local, Scheduled, Push Notification With Firebase</title>
      <dc:creator>Vikrant Negi</dc:creator>
      <pubDate>Thu, 04 Jul 2019 13:30:15 +0000</pubDate>
      <link>https://dev.to/vikrantnegi/react-native-local-scheduled-push-notification-with-firebase-37gf</link>
      <guid>https://dev.to/vikrantnegi/react-native-local-scheduled-push-notification-with-firebase-37gf</guid>
      <description>&lt;p&gt;With ever going increase in app usage, the app developers try to find new ways to keep their user engaged with their apps. Push notifications are one way to keep your users engaged and informed.&lt;/p&gt;

&lt;p&gt;Push notifications are the communications channel used by apps to drive user re-engagement and retention. Push notification technology has come a long way from being a single messages delivery system to a rich and interactive medium.&lt;/p&gt;

&lt;p&gt;There are two types of notifications, remote and local notifications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remote Notifications
&lt;/h3&gt;

&lt;p&gt;With remote notifications, you use one of your company’s servers to push data to user devices via the Apple Push Notification service or FCM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local Notifications
&lt;/h3&gt;

&lt;p&gt;Both Android and IOS support the ability to trigger notifications from your application locally. These can either be displayed immediately, or scheduled to be displayed at a later date.&lt;/p&gt;

&lt;p&gt;In this article we will be using local notifications feature to send daily a reminder to the user at a particular time every day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;This tutorial requires basic knowledge of React Native. To set up your development machine, follow the official guide &lt;a href="https://facebook.github.io/react-native/docs/0.59/getting-started" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To implement push notifications in React Native application, we are going to use the &lt;a href="https://github.com/invertase/react-native-firebase" rel="noopener noreferrer"&gt;react-native-firebase&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;React Native Firebase has Notifications module that supports for both remote (FCM) and local notifications.&lt;/p&gt;

&lt;p&gt;To make sure we are on the same page, the following are the versions used in this tutorial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node v10.15.0&lt;/li&gt;
&lt;li&gt;npm 6.4.1&lt;/li&gt;
&lt;li&gt;yarn 1.16.0&lt;/li&gt;
&lt;li&gt;react-native 0.59.9&lt;/li&gt;
&lt;li&gt;react-native-firebase 5.2.3&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;To create a new project using &lt;code&gt;react-native-cli&lt;/code&gt;, type the following in terminal:&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="nv"&gt;$ &lt;/span&gt;react-native init localReminders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;localReminders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Install React Native Firebase
&lt;/h4&gt;

&lt;p&gt;Install &lt;code&gt;react-native-firebase&lt;/code&gt; by following installation instructions &lt;a href="https://rnfirebase.io/docs/v5.x.x/installation/initial-setup" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Make sure you have completed both iOS and Android setup.&lt;/p&gt;

&lt;h4&gt;
  
  
  Install Modules
&lt;/h4&gt;

&lt;p&gt;React Native Firebase only provides your application with access to Core features.&lt;/p&gt;

&lt;p&gt;To user notification in our react native app, we'll need to also install the &lt;strong&gt;Cloud Messaging&lt;/strong&gt; and &lt;strong&gt;Notifications&lt;/strong&gt; modules.&lt;/p&gt;

&lt;p&gt;Install &lt;strong&gt;Cloud Messaging&lt;/strong&gt; by following the instructions &lt;a href="https://rnfirebase.io/docs/v5.x.x/messaging/ios" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Install &lt;strong&gt;Notifications&lt;/strong&gt; by following the instructions &lt;a href="https://rnfirebase.io/docs/v5.x.x/notifications/ios" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Again, make sure you followed the steps for both iOS and Android.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial code setup
&lt;/h2&gt;

&lt;p&gt;In your &lt;code&gt;App.js&lt;/code&gt; file add these imports:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Alert&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="s2"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native-firebase&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Dashboard&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/Dashboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an empty &lt;code&gt;Dashboard.js&lt;/code&gt; file in your &lt;code&gt;src&lt;/code&gt; folder. We'll fill this with code in later part of the tutorial.&lt;/p&gt;

&lt;p&gt;Now create a &lt;code&gt;class&lt;/code&gt; component called &lt;code&gt;App&lt;/code&gt; as follow:&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&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="c1"&gt;// Create notification channel required for Android devices&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;createNotificationChannel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Ask notification permission and add notification listener&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;checkPermission&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;createNotificationChannel&lt;/span&gt; &lt;span class="o"&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="nx"&gt;checkPermission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Dashboard&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;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've created a few helper methods in this class component that we called on &lt;code&gt;componentDidMount()&lt;/code&gt; lifecycle method. In render, we'll return the &lt;code&gt;Dashboard&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Let's review and add code to these methods and see what they do and why do we need them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Android Notification Channel
&lt;/h2&gt;

&lt;p&gt;As of Android 8.0 (API Level 26), notifications must specify a Notification Channel or they will not appear.&lt;/p&gt;

&lt;p&gt;To allow React Native Firebase to work seamlessly across all versions of Android, you will need to create a channel before you can display a notification. This block of code can be re-run multiple times, so it is safe to do it each time your application starts.&lt;/p&gt;

&lt;p&gt;To create this notification channel we created a custom helper method &lt;code&gt;createNotificationChannel()&lt;/code&gt;. Update it with the following:&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;createNotificationChannel&lt;/span&gt; &lt;span class="o"&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="c1"&gt;// Build a android notification channel&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Android&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reminder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// channelId&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Reminders Channel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// channel name&lt;/span&gt;
    &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Android&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Importance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;High&lt;/span&gt; &lt;span class="c1"&gt;// channel importance&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Used for getting reminder notification&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// channel description&lt;/span&gt;

  &lt;span class="c1"&gt;// Create the android notification channel&lt;/span&gt;
  &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;android&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;channel&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;Android channel accept three parameters &lt;code&gt;channelId&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;importance&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For full reference documentation, please see &lt;a href="https://rnfirebase.io/docs/v5.x.x/notifications/reference/AndroidChannel" rel="noopener noreferrer"&gt;&lt;strong&gt;AndroidChannel&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://rnfirebase.io/docs/v5.x.x/notifications/reference/AndroidNotifications" rel="noopener noreferrer"&gt;&lt;strong&gt;AndroidNotifications&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notification Permission and Listener
&lt;/h2&gt;

&lt;p&gt;Before we can send any notification we need to make sure we have the notification permission and then, when we have that permission we can add a notification listener. This notification listener will listen for any notification and return us with the &lt;code&gt;notification&lt;/code&gt; when received.&lt;/p&gt;

&lt;p&gt;Update your &lt;code&gt;checkPermission()&lt;/code&gt; method with the following:&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;checkPermission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;messaging&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;hasPermission&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="nx"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// We've the permission&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;notificationListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;notification&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Display your notification&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;displayNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notification&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// user doesn't have permission&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;messaging&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;requestPermission&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Alert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unable to access the Notification permission. Please enable the Notification Permission from the settings&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;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the notification listener receives a notification, we call &lt;code&gt;displayNotification()&lt;/code&gt; method with the &lt;code&gt;notification&lt;/code&gt; received which will display the notification.&lt;/p&gt;

&lt;p&gt;We can now receive and show the notification. Now its time to schedule a local notification which will fire at some point in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dashboard Screen
&lt;/h2&gt;

&lt;p&gt;We are going to create a &lt;strong&gt;Dashboard&lt;/strong&gt; screen which will have a switch to enable and disable notifications and a time picker to set time to receive notifications. It will look something like below.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnv5ophowh6o4yxuh6l1.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnv5ophowh6o4yxuh6l1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make this UI Screen we'll add few third party helper libraries.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://react-native-training.github.io/react-native-elements/" rel="noopener noreferrer"&gt;react-native-elements&lt;/a&gt; - UI component library&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://momentjs.com/" rel="noopener noreferrer"&gt;moment&lt;/a&gt; - Handling Date Object&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/mmazzarolo/react-native-modal-datetime-picker" rel="noopener noreferrer"&gt;react-native-modal-datetime-picker&lt;/a&gt; - A React-Native datetime-picker for Android and iOS&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's start with adding the required imports:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SafeAreaView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;View&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="s2"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ListItem&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="s2"&gt;react-native-elements&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native-firebase&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;DateTimePicker&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native-modal-datetime-picker&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;moment&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;moment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we'll create and default export &lt;code&gt;Dashboard&lt;/code&gt; class component.&lt;/p&gt;

&lt;p&gt;Now, add some local states:&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;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;enableNotification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;isDateTimePickerVisible&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;notificationTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;hour&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;17&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;Now we want to set reminder as soon as user lands on the dashboard, so we'll create and call a &lt;code&gt;setReminder()&lt;/code&gt; method on &lt;code&gt;componentDidMount()&lt;/code&gt; lifecycle method:&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="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="nf"&gt;setReminder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;setReminder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;notificationTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;enableNotification&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="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="nx"&gt;enableNotification&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// schedule notification&lt;/span&gt;
    &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;scheduleNotification&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;buildNotification&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fireDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;notificationTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;repeatInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;day&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&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 &lt;code&gt;setReminder()&lt;/code&gt; method first we use &lt;code&gt;notificationTime&lt;/code&gt; and &lt;code&gt;enableNotification&lt;/code&gt; state.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;enableNotification&lt;/code&gt; is true we schedule the notification using &lt;a href="https://rnfirebase.io/docs/v5.x.x/notifications/reference/Notifications#scheduleNotification" rel="noopener noreferrer"&gt;&lt;code&gt;scheduleNotification()&lt;/code&gt;&lt;/a&gt; method.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;scheduleNotification()&lt;/code&gt; has two parameters, &lt;code&gt;notification&lt;/code&gt; and &lt;code&gt;schedule&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;notification&lt;/code&gt; we'll call another custom method &lt;code&gt;buildNotification()&lt;/code&gt; which will return notification and, in &lt;code&gt;schedule&lt;/code&gt; we'll pass an object with &lt;code&gt;fireDate&lt;/code&gt;, &lt;code&gt;repeatInterval&lt;/code&gt; and &lt;code&gt;exact&lt;/code&gt; keys.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;fireDate&lt;/code&gt; is the date when the notification should first be shown, in milliseconds. For &lt;code&gt;repeatInterval&lt;/code&gt; we'll use &lt;code&gt;day&lt;/code&gt;, as we want the notification to be shown everyday. The &lt;code&gt;exact&lt;/code&gt; option is Android only and it denotes if the &lt;code&gt;fireDate&lt;/code&gt; should be respected exactly, i.e. for reminders, or if it can deviate slightly to save battery.&lt;/p&gt;

&lt;p&gt;In else we'll just return &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, we'll add &lt;code&gt;buildNotification()&lt;/code&gt; method which will build a notification when a notification is received:&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;buildNotification&lt;/span&gt; &lt;span class="o"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OS&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;android&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;Daily Reminder&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="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setNotificationId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Any random ID&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Title of the notification&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is a notification&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// body of notification&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;android&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setPriority&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Android&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Priority&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;High&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// set priority in Android&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;android&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setChannelId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reminder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// should be the same when creating channel for Android&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;android&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAutoCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// To remove notification when tapped on it&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;notification&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;Let's add some helper method for the notification &lt;code&gt;switch&lt;/code&gt; and time picker. These will be used by their respective components to set local states which will then later be used:&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;enableNotification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&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;enableNotification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;showDateTimePicker&lt;/span&gt; &lt;span class="o"&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="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;isDateTimePickerVisible&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;hideDateTimePicker&lt;/span&gt; &lt;span class="o"&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="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;isDateTimePickerVisible&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;handleDatePicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;date&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;hideDateTimePicker&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;notificationTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&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;Finally, the &lt;code&gt;render()&lt;/code&gt; which we'll return the UI of the dashboard:&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="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;enableNotification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isDateTimePickerVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;notificationTime&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="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;lt;&lt;/span&gt;&lt;span class="nx"&gt;SafeAreaView&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&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="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&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;cardTitleView&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&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;cardTitle&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;Add&lt;/span&gt; &lt;span class="nx"&gt;Reminder&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListItem&lt;/span&gt;
        &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Notification&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;bottomDivider&lt;/span&gt;
        &lt;span class="nx"&gt;titleStyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&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;titleStyle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;onValueChange&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;enableNotification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;enableNotification&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListItem&lt;/span&gt;
        &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Time&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;titleStyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&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;titleStyle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;onPress&lt;/span&gt;&lt;span class="o"&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;showDateTimePicker&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;rightElement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.7&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;moment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notificationTime&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;      &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DateTimePicker&lt;/span&gt;
        &lt;span class="nx"&gt;isVisible&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isDateTimePickerVisible&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;onConfirm&lt;/span&gt;&lt;span class="o"&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;handleDatePicked&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;onCancel&lt;/span&gt;&lt;span class="o"&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;hideDateTimePicker&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;time&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// show only time picker&lt;/span&gt;
        &lt;span class="nx"&gt;is24Hour&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notificationTime&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="nx"&gt;titleIOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pick your Notification time&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/SafeAreaView&lt;/span&gt;&lt;span class="err"&gt;&amp;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;Time to sprinkle in some styles to make UI more appealing.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#EEEFF0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;cardTitleView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;paddingHorizontal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;paddingTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;paddingBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;cardTitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#585858&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fontWeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;600&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;titleStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#585858&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. We are done with development. In the next section, we'll test it out in an iOS simulator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the app
&lt;/h2&gt;

&lt;p&gt;Test the app by enabling notification and setting time 1 min in the future.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwsdsu81n6vud8uw3g36.gif" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwsdsu81n6vud8uw3g36.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Sometimes the notification may not show at the exact time. Please wait for a whole minute for notification to appear.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;We can now schedule daily local push notification in our React Native app for both iOS and Android.&lt;/p&gt;

&lt;p&gt;Apart from firebase, there are other libraries you can use to implement local push notification like &lt;a href="https://github.com/zo0r/react-native-push-notification" rel="noopener noreferrer"&gt;react-native-push-notification&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is the Github repo &lt;a href="https://github.com/vikrantnegi/local-reminders" rel="noopener noreferrer"&gt;local-reminders&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally published on &lt;a href="https://medium.com/better-programming/react-native-local-scheduled-push-notification-with-firebase-8c775b71c35c" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;PS: Cover image by &lt;a href="https://unsplash.com/@jamie452?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Jamie Street&lt;/a&gt; on Unsplash&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>firebase</category>
      <category>pushnotification</category>
      <category>localpushnotification</category>
    </item>
    <item>
      <title>React Native Location Tracking</title>
      <dc:creator>Vikrant Negi</dc:creator>
      <pubDate>Mon, 21 May 2018 18:09:06 +0000</pubDate>
      <link>https://dev.to/vikrantnegi/react-native-location-tracking-32o7</link>
      <guid>https://dev.to/vikrantnegi/react-native-location-tracking-32o7</guid>
      <description>&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwvylez1sszgpo1qvez1.gif" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwvylez1sszgpo1qvez1.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’ve been working with React Native you must have used or heard about react-native-maps. React native maps is a react native package that provide Google Maps API for React Native. Using static google maps is very common but today we are going to use one of the widely used feature of google maps, location tracking using React native.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Find the project repo &lt;a href="https://github.com/vikrantnegi/react-native-location-tracking" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Start by creating a React Native project and name it whatever you want. I’m using the react-native-cli but &lt;a href="https://github.com/react-community/create-react-native-app" rel="noopener noreferrer"&gt;create-react-native-app&lt;/a&gt; should also work just fine.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;react-native init locationTracking&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing react-native-maps
&lt;/h2&gt;

&lt;p&gt;First, download the library from npm:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install react-native-maps --save&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Installing react-native-maps requires adding code to native iOS and Android files. Follow the installation instructions provided by the react-native-maps. After installation make sure that the project builds successfully before moving forward.&lt;/p&gt;

&lt;p&gt;Installing react-native-maps is not a simple task. If you are doing it for the first time I would suggest going through the &lt;a href="https://github.com/react-community/react-native-maps/blob/master/docs/installation.md" rel="noopener noreferrer"&gt;installation&lt;/a&gt; instructions carefully. Believe me this will be the toughest task of this tutorial. Use google if you face any errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using react-native-maps
&lt;/h2&gt;

&lt;p&gt;Great, now that you’ve successfully installed the react-native-maps. Let’s move to the juicy part, where the real magic happens.&lt;br&gt;
Let first set some initial states that will be used for this project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;constructor(props) {
  super(props);
  this.state = {
    latitude: LATITUDE,
    longitude: LONGITUDE,
    routeCoordinates: [],
    distanceTravelled: 0,
    prevLatLng: {},
    coordinate: new AnimatedRegion({
     latitude: LATITUDE,
     longitude: LONGITUDE
    })
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ll use these states later in the app, the only thing of interest here is the new &lt;code&gt;AnimatedRegion&lt;/code&gt; which will help us to animate our markers when the location updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch for location changes
&lt;/h2&gt;

&lt;p&gt;Now we’ll need to get the location coordinates every time the user moves. Google maps geolocation API has &lt;code&gt;watchPosition&lt;/code&gt; method which will hep us get the location coordinates whenever they gets changed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;componentDidMount() {
  this.watchID = navigator.geolocation.watchPosition(
    position =&amp;gt; {
      const { coordinate, routeCoordinates, distanceTravelled } =   this.state;
      const { latitude, longitude } = position.coords;

      const newCoordinate = {
        latitude,
        longitude
      };
      if (Platform.OS === "android") {
        if (this.marker) {
          this.marker._component.animateMarkerToCoordinate(
            newCoordinate,
            500
          );
         }
       } else {
         coordinate.timing(newCoordinate).start();
       }
       this.setState({
         latitude,
         longitude,
         routeCoordinates: routeCoordinates.concat([newCoordinate]),
         distanceTravelled:
         distanceTravelled + this.calcDistance(newCoordinate),
         prevLatLng: newCoordinate
       });
     },
     error =&amp;gt; console.log(error),
     { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The watchPosition gives us the information about user’s location whenever it get’s changed. We then use ES6 &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment" rel="noopener noreferrer"&gt;Destructuring&lt;/a&gt; to get latitude &amp;amp; longitude from the position.coords. Also, we’ll get coordinate, routeCoordinates &amp;amp; distanceTravelled from initial state.&lt;/p&gt;

&lt;p&gt;We’ll than create newCoordinate variable that will store these new updated location coordinates that we received from position.coords. Now that we have got the updates coordinates we’ll animate the marker to these new coordinates. Both Android and iOS have different way of handling this so we’ll use &lt;a href="https://facebook.github.io/react-native/docs/platform-specific-code.html" rel="noopener noreferrer"&gt;Platform Specific Code&lt;/a&gt; to handle this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (Platform.OS === "android") {
  if (this.marker) {
  this.marker._component.animateMarkerToCoordinate(
    newCoordinate,
    500
   );
  }
} else {
  coordinate.timing(newCoordinate).start();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now its time to update our initial states with the new one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.setState({
  latitude,
  longitude,
  routeCoordinates: routeCoordinates.concat([newCoordinate]),
  distanceTravelled: distanceTravelled + this.calcDistance(newCoordinate),
  prevLatLng: newCoordinate
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Calculating Distance Travelled
&lt;/h2&gt;

&lt;p&gt;We have used distanceTravelled state variable to store the distance travelled by the user. To calculate this distance we’ll create a new function calcDistance that will take newLatLng as parameter and prevLatLng as state variable and will return distance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;calcDistance = newLatLng =&amp;gt; {
  const { prevLatLng } = this.state;
  return haversine(prevLatLng, newLatLng) || 0;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at this function you maybe wondering when did calculating the distance got so complex. Apparently due to the curvature of the earth calculating distance with the help of latitude and longitude is not so straightforward. Earth has got some curves.&lt;/p&gt;

&lt;p&gt;To calculate the distance using latitude and longitude we need to use &lt;a href="https://en.wikipedia.org/wiki/Haversine_formula" rel="noopener noreferrer"&gt;Haversine&lt;/a&gt; formula. If you are like me who struggles with mathematics 😅, there is a hope in the form of a haversine npm package that can help us calculate distance using latitude and longitude. Install haversine npm package using the following command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install haversine&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Rendering MapView
&lt;/h2&gt;

&lt;p&gt;Since  component need region prop which accepts an object with location coordinates. We are going to create a function that returns all necessary information needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getMapRegion = () =&amp;gt; ({
  latitude: this.state.latitude,
  longitude: this.state.longitude,
  latitudeDelta: LATITUDE_DELTA,
  longitudeDelta: LONGITUDE_DELTA
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we’ve all the information need to render the map.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;MapView
  style={styles.map}
  showUserLocation
  followUserLocation
  loadingEnabled
  region={this.getMapRegion()}
&amp;gt;
  &amp;lt;Polyline coordinates={this.state.routeCoordinates} strokeWidth={5} /&amp;gt;
  &amp;lt;Marker.Animated
    ref={marker =&amp;gt; {
      this.marker = marker;
    }}
    coordinate={this.state.coordinate}
  /&amp;gt;
&amp;lt;/MapView&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ve also used the Google Maps Polyline to draw the path as the user moves. Polyline has acoordinate props which accepts an array of coordinates which we can get from our routeCoordinates. We’ve also set the strokeWidth to so we can see the path clearly.&lt;/p&gt;

&lt;p&gt;Next to show the Animated marker we’ll use Marker.Animated component to show marker at user current position. It has coordinate props which will get the coordinate object from the state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show Distance Travelled
&lt;/h2&gt;

&lt;p&gt;Finally to show the distance travelled by the user we’ll set up a View with the proper styling applied.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;View style={styles.buttonContainer}&amp;gt;
  &amp;lt;TouchableOpacity style={[styles.bubble, styles.button]}&amp;gt;
    &amp;lt;Text style={styles.bottomBarContent}&amp;gt;
      {parseFloat(this.state.distanceTravelled).toFixed(2)} km
    &amp;lt;/Text&amp;gt;
  &amp;lt;/TouchableOpacity&amp;gt;
&amp;lt;/View&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Now that we’ve all the necessary pieces in place we can finally run our app.&lt;/p&gt;

&lt;p&gt;To test the app on iOS simulator we’ll use the location mode available in iOS simulators. After running the app go to &lt;code&gt;Debug&lt;/code&gt; &amp;gt; &lt;code&gt;Location&lt;/code&gt; &amp;gt; &lt;code&gt;Freeway Drive&lt;/code&gt; setting in simulator to turn on this feature. Doing so should result in something similar as below.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwvylez1sszgpo1qvez1.gif" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwvylez1sszgpo1qvez1.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Android, it’s not that straightforward as Android emulators doesn’t have any in built feature to test the dynamic location changes. To test it, either you can manually change your position by walking some distance or you can use 3rd party mock location apps. I was able to test this using &lt;a href="https://play.google.com/store/apps/details?id=com.theappninjas.gpsjoystick&amp;amp;hl=en_IN" rel="noopener noreferrer"&gt;GPS Joystick&lt;/a&gt; app on Android.&lt;/p&gt;

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

&lt;p&gt;We have successfully created a React Native app that tracks an user location and draws the path. It can also calculate the distance travelled by the user.&lt;/p&gt;

&lt;p&gt;I’ve skipped the styles and some other boilerplate code needed for this app but you can find that in the github repo &lt;a href="https://github.com/vikrantnegi/react-native-location-tracking" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope this helps you to understand the Google maps API. Maybe you can take inspiration from this to build something amazing. Please feel free to leave any feedback, I’m always looking for better solutions!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally published on &lt;a href="https://medium.com/@vikrantnegi/react-native-location-tracking-14ab2c9e2db8" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>reactnative</category>
      <category>react</category>
      <category>googlemaps</category>
      <category>locationtracking</category>
    </item>
  </channel>
</rss>
