<?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>Forem: Emily Xiong</title>
    <description>The latest articles on Forem by Emily Xiong (@xiongemi).</description>
    <link>https://forem.com/xiongemi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F239081%2F97e1b5d0-3d6d-44a7-ae9e-f94a07b6f78f.jpeg</url>
      <title>Forem: Emily Xiong</title>
      <link>https://forem.com/xiongemi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/xiongemi"/>
    <language>en</language>
    <item>
      <title>Google Cloud Group DevFest Toronto 2025 - The Most Chaotic Conference I've Ever Been To</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Sun, 16 Nov 2025 01:30:43 +0000</pubDate>
      <link>https://forem.com/xiongemi/google-cloud-group-devfest-toronto-2025-the-most-chaotic-conference-ive-ever-been-to-2348</link>
      <guid>https://forem.com/xiongemi/google-cloud-group-devfest-toronto-2025-the-most-chaotic-conference-ive-ever-been-to-2348</guid>
      <description>&lt;p&gt;Today I went to the Google Cloud Group DevFest 2025, and to be very honest, this might be one of the most &lt;strong&gt;CHAOTIC&lt;/strong&gt; conferences I’ve ever attended.&lt;/p&gt;

&lt;p&gt;Tickets were only around $40 per person, which is definitely on the cheaper side for conferences, and I understand that running an event is hard. Things happen. Hiccups are normal.&lt;/p&gt;

&lt;p&gt;But this conference had every type of hiccup. I think I saw the entire bingo card.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔥 Chaos Outside the Venue
&lt;/h2&gt;

&lt;p&gt;The event took place at the Sheraton in downtown Toronto. Before we even got inside, there were pro-Palestine protesters outside, handing flyers to attendees. That already set a pretty tense mood.&lt;/p&gt;

&lt;p&gt;Then, less than five minutes into the first talk, an attendee — who was also part of the protest — stood up and loudly accused Google of committing genocide. The opening keynote was interrupted almost immediately.&lt;/p&gt;

&lt;p&gt;It was unfortunate, and it definitely derailed the flow.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Chaos Inside the Venue
&lt;/h2&gt;

&lt;p&gt;Once the talks resumed, the technical issues started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Projectors not working&lt;/li&gt;
&lt;li&gt;Audio glitches&lt;/li&gt;
&lt;li&gt;Video not loading&lt;/li&gt;
&lt;li&gt;Microphones cutting out&lt;/li&gt;
&lt;li&gt;Laptops running out of battery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It truly felt like every few minutes something went wrong.&lt;br&gt;
And I’ve been to a lot of AI and dev events in Toronto — this was the highest number of hiccups I’ve seen in one day.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 The Content: More Inspiration Than Developer
&lt;/h2&gt;

&lt;p&gt;Since this event is called DevFest, I expected more technical content — something more “nitty-gritty” about developer tools or developer experience. I use Gemini CLI daily to vibe-code, so I already know the power of these tools.&lt;/p&gt;

&lt;p&gt;But most talks felt more like inspirational speeches geared toward the general public, not developers. There weren’t many real demos or deep dives. And one talk suddenly pivoted into blockchain, showing a slide that said “&lt;strong&gt;&lt;em&gt;AI + Blockchain + Cloud&lt;/em&gt;&lt;/strong&gt;”, but without explaining any real practical use case. It honestly felt like buzzword soup.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎓 A Lot of Students and Job Hunters
&lt;/h2&gt;

&lt;p&gt;Another thing I noticed: the crowd was filled with students and job seekers.&lt;br&gt;
Which makes sense — tickets were cheap, and the job market in tech is rough right now.&lt;/p&gt;

&lt;p&gt;I was job hunting earlier this year, and I know how hard it is in this economy. Everyone is hustling, trying to network, trying to catch opportunities wherever they can. So I really felt for them.&lt;/p&gt;

&lt;p&gt;But it also made the event feel less like a hardcore developer conference and more like a general-interest community event — more inspirational, less technical.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Overall, DevFest 2025 ended up being an interesting experience, but not in the way I expected. Between the protests, interruptions, technical problems, and the high-level content, it didn’t feel very developer-focused.&lt;/p&gt;

&lt;p&gt;Am I glad I went?&lt;br&gt;
Yes — it was definitely memorable.&lt;/p&gt;

&lt;p&gt;Would I go again next year?&lt;br&gt;
Probably not.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My Field Guide to Toronto Tech Bros</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Fri, 19 Sep 2025 03:43:26 +0000</pubDate>
      <link>https://forem.com/xiongemi/field-guide-to-toronto-tech-bros-2kkf</link>
      <guid>https://forem.com/xiongemi/field-guide-to-toronto-tech-bros-2kkf</guid>
      <description>&lt;p&gt;I’ve been meaning to write this blog for a long time.&lt;/p&gt;

&lt;p&gt;I went to a lot of in-person tech meetup events in Toronto — and honestly, I usually have a fantastic experience. I met incredible people, had deep conversations, and built some great connections.&lt;/p&gt;

&lt;p&gt;But… you can’t go to so many big tech events without running into at least a few Tech Bros.&lt;/p&gt;

&lt;p&gt;I don’t mean that as an insult. Some of them were probably just having an off day, and I’m sure they’re perfectly nice in other contexts. But some of these encounters were so surreal, I can’t not share them.&lt;/p&gt;

&lt;p&gt;So here’s my field guide to the Tech Bros of Toronto — six types I personally met this year.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Egotistical Startup Founder
&lt;/h2&gt;

&lt;p&gt;I get it: you need a certain personality to be a startup founder. You have to be confident, maybe even a little bit egotistical.&lt;/p&gt;

&lt;p&gt;At one event, I met a group of founders — the COO, CEO, and CTO of a startup. Their business model sounded a little convoluted, so naturally I asked a few follow-up questions.&lt;/p&gt;

&lt;p&gt;Before I could get far, the CEO stopped me and asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Are you an investor? Are you interested in investing in our company?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I said no — because I’m just a developer at the “bottom of the food chain,” not a VC — he literally walked away.&lt;/p&gt;

&lt;p&gt;At tech conferences, my favorite thing is to stop at startup booths and listen to pitches. I find them pretty inspiring. At a large conference, I stopped at a startup booth. The founder was glued to his phone, no demo set up, no laptop out. When I asked what his company did, he shrugged and said he had already gotten funding, and he was only there because the VC asked him to show up.&lt;/p&gt;

&lt;p&gt;He wasn’t networking. He wasn’t pitching. He just didn’t want to be there.&lt;/p&gt;

&lt;p&gt;That conference is pretty big, and I know from other startups that it is not cheap to rent a booth. There were other startups eager to pitch and get the most value out of the money. To him, it felt like: “I got my money. Career journey over.”&lt;/p&gt;

&lt;p&gt;Statistically, about 90% of startups fail. But every founder I meet seems absolutely sure they’re part of the lucky 10%. And honestly — I wish them the best of luck.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Judgmental Tech Bro
&lt;/h2&gt;

&lt;p&gt;Then there are the ones who size you up in the first ten seconds and decide whether you’re worth talking to.&lt;/p&gt;

&lt;p&gt;When I was job hunting, I went to a meetup and asked someone if their company was hiring. I barely finished my introduction before he said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I don’t think you’re qualified.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even if he was right, who says that to a stranger? He didn’t want to talk to me because he thought I was unemployed and not worth making a connection with.&lt;/p&gt;

&lt;p&gt;At a career fair, another guy opened our conversation with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I’m a senior developer. Don’t worry, I’m not here to take your job.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Maybe he assumed I was a new grad because I look young — but I actually have work experience. And trust me, I was not worried at all. These guys just can’t resist gatekeeping.&lt;/p&gt;

&lt;p&gt;The Judgmental Tech Bros are quick to assume, quick to dismiss, and quick to put you in a box.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The Finance-Obsessed Tech Bro
&lt;/h2&gt;

&lt;p&gt;There are people who think because they have a job and you don’t, they are better than you. Then there’s a different breed: the ones who treat casual networking like &lt;em&gt;Shark Tank.&lt;/em&gt; And there are also people who think because their company’s valuation is higher than your company’s valuation, they are better than you.&lt;/p&gt;

&lt;p&gt;At one event, I introduced myself and mentioned I worked at a VC-backed startup. The first question I got back was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“What’s the funding stage of your company? How much did you raise in the last round?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I had to Google that information. After I told him the figure, his reaction was just:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Not bad.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And honestly, my first thought was:&lt;/p&gt;

&lt;p&gt;Who the hell remembers their company’s valuation?&lt;/p&gt;

&lt;p&gt;I’m a developer. The company’s bank account has nothing to do with me. I don’t get a cut of that Series A/B/C/D/E funding.&lt;/p&gt;

&lt;p&gt;But these Finance-Obsessed Tech Bros talk in millions and billions, act like their company’s valuation is their own net worth — and they want to measure you based on your company’s numbers too.&lt;/p&gt;

&lt;p&gt;It’s such a weird flex.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The Know-It-All Tech Bro
&lt;/h2&gt;

&lt;p&gt;Tech is huge. Nobody can know it all. But some people think they do.&lt;/p&gt;

&lt;p&gt;At one event, we were supposed to pitch startup or app ideas to the people around us. I shared mine — and the guy next to me, who I had just met, immediately shut me down:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“That’s too complicated.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No discussion. No curiosity. Just instant dismissal.&lt;/p&gt;

&lt;p&gt;Then he pitched his idea, which was so simple I could probably build it in an afternoon using AI tools.&lt;/p&gt;

&lt;p&gt;Maybe he was early in his career and didn’t know what he didn’t know. But I’m at the stage in life where I’m too tired to argue.&lt;/p&gt;

&lt;p&gt;I quietly moved to another seat. Sometimes protecting your peace is better than proving your point.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. The AI-Doombro
&lt;/h2&gt;

&lt;p&gt;AI is definitely the future — and I’m not in denial about that. I’m a front-end developer, and maybe someday, when AGI arrives, my job will be automated away.&lt;/p&gt;

&lt;p&gt;But that day isn’t today.&lt;/p&gt;

&lt;p&gt;At one event, I met an AI engineer and his friend. I introduced myself and told them I was a front-end developer.&lt;/p&gt;

&lt;p&gt;And they just could not stop laughing. I’m not exaggerating — they laughed for about a full minute, right in my face.&lt;/p&gt;

&lt;p&gt;When I asked, “Why are you laughing?” he said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Do you think there will be front-end developers in the future?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Maybe he’s right. But the way he said it — laughing at my entire profession — made the moment feel weirdly mean.&lt;/p&gt;

&lt;p&gt;Maybe there won’t be front-end developers in the future, but I still need to make a living in the near future.&lt;/p&gt;

&lt;p&gt;Even if AI is coming for our jobs someday, that doesn’t mean the work we do today is worthless.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. The Opportunistic Tech Bro
&lt;/h2&gt;

&lt;p&gt;I was job hunting and went to an event organized by a large enterprise that had plenty of job opportunities. I met a fellow attendee who was also job hunting. He seemed like he had an interesting background, and I genuinely wanted to network and learn more about his experience.&lt;/p&gt;

&lt;p&gt;But halfway through, a corporate co-op from the host company walked in — and he dismissed me, walking straight over to network with the co-op student instead.&lt;/p&gt;

&lt;p&gt;I respect the hustle. I get it — we’re all there to maximize our chances. But it still felt a little bad to be dropped mid-conversation just because I wasn’t “useful” enough in that moment.&lt;/p&gt;




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

&lt;p&gt;So there you have it — my field guide to the six types of Tech Bros I met this year.&lt;/p&gt;

&lt;p&gt;Sometimes I wish I was making these stories up — that these characters were just over-the-top stereotypes invented for comedy. But they’re not. These people really do exist.&lt;/p&gt;

&lt;p&gt;Maybe they’re just confident. Maybe they’re “on top of the world.” Or maybe they’re just judgmental. Who am I to judge them?&lt;/p&gt;

&lt;p&gt;Tech bros used to be a stereotype for nerds - the hoodie-wearing, pizza-eating, socially awkward coder type. But now they're starting to feel more like finance bros- focused on valuations, funding rounds, and personal status.&lt;/p&gt;

&lt;p&gt;And maybe that's just what happens when an industry gets big. You get all kinds of people, including the ones who act like this.&lt;/p&gt;

&lt;p&gt;At the end of the day, running into a few Tech Bros didn’t ruin any in-person meetup events for me. I still love to attend different meetups, socialize with people, and get inspired. I still met amazing people and had great conversations.&lt;/p&gt;

&lt;p&gt;But these encounters reminded me that tech is as diverse as the humans in it — for better or worse.&lt;/p&gt;

</description>
      <category>techbros</category>
      <category>toronto</category>
      <category>torontotechwekk</category>
      <category>programming</category>
    </item>
    <item>
      <title>Add Cypress, Playwright, and Storybook to Nx Expo Apps</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Mon, 19 Feb 2024 21:18:25 +0000</pubDate>
      <link>https://forem.com/nx/add-cypress-playwright-and-storybook-to-nx-expo-apps-2ob1</link>
      <guid>https://forem.com/nx/add-cypress-playwright-and-storybook-to-nx-expo-apps-2ob1</guid>
      <description>&lt;p&gt;Expo has first-class support for building full-stack websites with React, so I can leverage that to add &lt;a href="https://nx.dev/nx-api/cypress" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;/&lt;a href="https://nx.dev/nx-api/playwright" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; for E2E testing and add the &lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; for UI components.&lt;/p&gt;

&lt;p&gt;In this blog, I am going to add &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;, &lt;a href="https://nx.dev/nx-api/playwright" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;, and &lt;a href="https://nx.dev/nx-api/storybook" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; to my &lt;a href="https://nx.dev/nx-api/expo" rel="noopener noreferrer"&gt;Nx Expo&lt;/a&gt; app:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/xiongemi" rel="noopener noreferrer"&gt;
        xiongemi
      &lt;/a&gt; / &lt;a href="https://github.com/xiongemi/nx-expo-monorepo" rel="noopener noreferrer"&gt;
        nx-expo-monorepo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      a repo showing 2 apps created by @nx/expo
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;NxExpoMonorepo&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;This workspace is created using &lt;a href="https://nx.dev/packages/expo" rel="nofollow noopener noreferrer"&gt;@nx/expo&lt;/a&gt; (&lt;a href="https://nx.dev" rel="nofollow noopener noreferrer"&gt;Nx&lt;/a&gt; and &lt;a href="https://expo.io/" rel="nofollow noopener noreferrer"&gt;Expo&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nx.dev" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fnrwl%2Fnx%2Fmaster%2Fimages%2Fnx-logo.png" width="45"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;✨ &lt;strong&gt;This workspace has been generated by &lt;a href="https://nx.dev" rel="nofollow noopener noreferrer"&gt;Nx, a Smart, fast and extensible build system.&lt;/a&gt;&lt;/strong&gt; ✨&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Workspace structure&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;It contains 2 apps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cats and its e2e (cypress/playwright)&lt;/li&gt;
&lt;li&gt;dogs and its e2e (cypress/playwright)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;4 libs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;models&lt;/li&gt;
&lt;li&gt;queries: &lt;a href="https://react-query.tanstack.com/" rel="nofollow noopener noreferrer"&gt;tanstack react-query&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;states: redux state management&lt;/li&gt;
&lt;li&gt;ui&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xiongemi/nx-expo-monorepo/blob/main/screenshots/cats.png?raw=true"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fxiongemi%2Fnx-expo-monorepo%2Fraw%2Fmain%2Fscreenshots%2Fcats.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xiongemi/nx-expo-monorepo/blob/main/screenshots/dogs.png?raw=true"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fxiongemi%2Fnx-expo-monorepo%2Fraw%2Fmain%2Fscreenshots%2Fdogs.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Commands&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nx start cats&lt;/code&gt; to start the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx start dogs&lt;/code&gt; to start the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx build cats&lt;/code&gt; to build the cats app using EAS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx build dogs&lt;/code&gt; to build the dogs app using EAS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx test cats&lt;/code&gt; to test the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx test dogs&lt;/code&gt; to test the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx lint cats&lt;/code&gt; to lint the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx lint dogs&lt;/code&gt; to lint the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run deploy&lt;/code&gt; to deploy the cats app to github page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx e2e cats-cypress&lt;/code&gt; to run cypress e2e tests on cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx e2e cats-playwright&lt;/code&gt; to…&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/xiongemi/nx-expo-monorepo" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;It is an app that shows a random fact about cats:&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%2F3aiggy817vkpdxoep26c.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%2F3aiggy817vkpdxoep26c.png" alt="My example Nx Expo app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is &lt;a href="https://nx.dev/nx-api/expo" rel="noopener noreferrer"&gt;@nx/expo&lt;/a&gt;? Nx is a build system that helps you maintain and scale monorepos, both locally and on CI. @nx/expo contains generators for managing Expo applications and libraries within an Nx workspace.&lt;/p&gt;

&lt;p&gt;I am going to go through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  How to add &lt;a href="https://nx.dev/nx-api/cypress" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  How to add &lt;a href="https://nx.dev/nx-api/playwright" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  How to add &lt;a href="https://nx.dev/nx-api/storybook" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Add Cypress
&lt;/h2&gt;

&lt;p&gt;In this section, I am going to go through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  When I already have an existing Nx Workspace, how do I add the Expo and Cypress projects?&lt;/li&gt;
&lt;li&gt;  When I already have an existing Nx Expo app, how do I add the Cypress tests to my app?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Add a new Expo App in an Nx Workspace
&lt;/h3&gt;

&lt;p&gt;In any Nx workspace, I can install &lt;code&gt;@nx/expo&lt;/code&gt; by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx add @nx/expo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now when I generate a new Expo app, I can simply use &lt;a href="https://nx.dev/nx-api/expo/generators/application" rel="noopener noreferrer"&gt;@nx/expo:application generator&lt;/a&gt; with the flag &lt;code&gt;--e2eTestRunner=cyperss&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx generate @nx/expo:app &lt;span class="nt"&gt;--e2eTestRunner&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cypress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It should create the expo app and its Cypress e2e tests. I can run &lt;code&gt;npx nx run &amp;lt;your-app-name&amp;gt;-e2e:e2e&lt;/code&gt; to run the Cypress e2e tests.&lt;/p&gt;
&lt;h3&gt;
  
  
  Add Cypress to an Existing Nx Expo App
&lt;/h3&gt;

&lt;p&gt;Before I start, I need to make sure I can serve my Expo app for the web view. In this example, in my &lt;code&gt;apps/cats/project.json&lt;/code&gt;, I got a serve target defined:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   "serve": {  
      "executor": "@nx/expo:serve",  
      "options": {  
        "port": 8081  
      }  
    },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So I can run the command &lt;code&gt;npx nx run cats:serve&lt;/code&gt; to serve the app on &lt;a href="http://localhost:8081/" rel="noopener noreferrer"&gt;http://localhost:8081/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh52u18np8xqbz33c7cfu.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%2Fh52u18np8xqbz33c7cfu.png" alt="Cats in Web View"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can also use &lt;a href="https://nx.dev/nx-api/expo#how-nxexpo-infers-tasks" rel="noopener noreferrer"&gt;@nx/expo inferred tasks&lt;/a&gt; without having a serve target in project.json. In &lt;code&gt;.env&lt;/code&gt; file, set &lt;code&gt;NX_ADD_PLUGINS=true&lt;/code&gt;; then run the command&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx add @nx/expo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then I can still run the serve command &lt;code&gt;npx nx run &amp;lt;your expo project&amp;gt;:serve&lt;/code&gt; without a serve target defined.&lt;/p&gt;

&lt;p&gt;Then I can set up the cypress e2e project against the web app.&lt;/p&gt;

&lt;p&gt;First, I need to install &lt;code&gt;@nx/cypress&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx add @nx/cypress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Second, I create a project.json for my Cypress project. In this example, I create a project.json at &lt;code&gt;apps/cats-cypress/project.json&lt;/code&gt;, I name the project &lt;code&gt;cats-cypress&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cats-cypress"&lt;/span&gt;&lt;span class="w"&gt;  
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Third, run the below command to generate Cypress configuration:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx generate @nx/cypress:configuration &lt;span class="nt"&gt;--project&lt;/span&gt; cats-cypress &lt;span class="nt"&gt;--devServerTarget&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cats:serve &lt;span class="nt"&gt;--baseUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:8081 &lt;span class="nt"&gt;--verbose&lt;/span&gt; &lt;span class="nt"&gt;--bundler&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Since the serve command is &lt;code&gt;npx nx run cats:serve&lt;/code&gt;, so the flag is &lt;code&gt;--devServerTarget&lt;/code&gt; is &lt;code&gt;cats:serve&lt;/code&gt;. Also, the &lt;code&gt;--baseUrl&lt;/code&gt; is &lt;code&gt;http://localhost:8081&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It should generate &lt;code&gt;cypress.config.ts&lt;/code&gt; and a sample test:&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%2Fybfhq6behvubn1hhjtqs.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%2Fybfhq6behvubn1hhjtqs.png" alt="Cypress Project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can run the Cypress test using the below command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx run cats-cypress:e2e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Add Cypress Tests
&lt;/h3&gt;

&lt;p&gt;I change the example tests:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Now I can run the command &lt;code&gt;npx nx run cats-cypress:e2e&lt;/code&gt; and it should pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 2 passing (867ms)  


  (Results)  

  ┌────────────────────────────────────────────────────────────────────────────────────────────────┐  
  │ Tests:        2                                                                                │  
  │ Passing:      2                                                                                │  
  │ Failing:      0                                                                                │  
  │ Pending:      0                                                                                │  
  │ Skipped:      0                                                                                │  
  │ Screenshots:  0                                                                                │  
  │ Video:        false                                                                            │  
  │ Duration:     0 seconds                                                                        │  
  │ Spec Ran:     app.cy.ts                                                                        │  
  └────────────────────────────────────────────────────────────────────────────────────────────────┘  


\===================================================================================  

  (Run Finished)  


       Spec                                              Tests  Passing  Failing  Pending  Skipped    
  ┌────────────────────────────────────────────────────────────────────────────────────────────────┐  
  │ ✔  app.cy.ts                                869ms        2        2        -        -        - │  
  └────────────────────────────────────────────────────────────────────────────────────────────────┘  
    ✔  All specs passed!                        869ms        2        2        -        -        -    


 —————————————————————————————————————————————————————————————————————————————————  

 &amp;gt;  NX   Successfully ran target e2e for project cats-cypress (15s)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Add Playwright
&lt;/h2&gt;

&lt;p&gt;Alternatively, I can use Playwright to e2e test.&lt;/p&gt;

&lt;p&gt;In this section, I am going to go through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  When I already have an existing Nx Workspace, how do I add the Expo and Playwright projects?&lt;/li&gt;
&lt;li&gt;  When I already have an existing Nx Expo app, how do I add the Playwright tests to my app?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Add a new Expo App in an Nx Workspace
&lt;/h3&gt;

&lt;p&gt;In any Nx workspace, I can install &lt;code&gt;@nx/expo&lt;/code&gt; by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx add @nx/expo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when I generate a new Expo app, I can simply use &lt;a href="https://nx.dev/nx-api/expo/generators/application" rel="noopener noreferrer"&gt;@nx/expo:application generator&lt;/a&gt; with the flag &lt;code&gt;--e2eTestRunner=playwright&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx generate @nx/expo:app &lt;span class="nt"&gt;--e2eTestRunner&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;playwright
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should create the expo app and its Playwright e2e tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Playwright to an Existing Nx Expo App
&lt;/h3&gt;

&lt;p&gt;Similarly to Cypress steps, before I start, I need to make sure I can serve my Expo app for the web view. In this example, in my &lt;code&gt;apps/cats/project.json&lt;/code&gt;, I got a serve target defined:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   "serve": {  
      "executor": "@nx/expo:serve",  
      "options": {  
        "port": 8081  
      }  
    },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, I need to install &lt;code&gt;@nx/playwright&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx add @nx/playwright
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second, I create a project.json for my Playwright project. In this example, I create a project.json at &lt;code&gt;apps/cats-playwright/project.json&lt;/code&gt;, I name the project &lt;code&gt;cats-playwright&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cats-playwright"&lt;/span&gt;&lt;span class="w"&gt;  
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Third, run the below command to generate Cypress configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx g @nx/playwright:configuration &lt;span class="nt"&gt;--project&lt;/span&gt; cats-playwright &lt;span class="nt"&gt;--webServerCommand&lt;/span&gt; &lt;span class="s2"&gt;"nx run cats:serve"&lt;/span&gt; &lt;span class="nt"&gt;--webServerAddress&lt;/span&gt; http://localhost:8081
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the serve command is &lt;code&gt;npx nx run cats:serve&lt;/code&gt;, so the flag is &lt;code&gt;--webServerCommand&lt;/code&gt; is &lt;code&gt;nx run cats:serve&lt;/code&gt;. Also, the &lt;code&gt;--webServerAddress&lt;/code&gt; is &lt;code&gt;[http://localhost:8081](http://localhost:8081.)&lt;/code&gt;&lt;a href="http://localhost:8081." rel="noopener noreferrer"&gt;.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It should generate &lt;code&gt;playwright.config.ts&lt;/code&gt; and a sample test file:&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%2Fmiro.medium.com%2Fv2%2F1%2AtwF-sWslGutXfCX7IjpYyQ.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%2Fmiro.medium.com%2Fv2%2F1%2AtwF-sWslGutXfCX7IjpYyQ.png" alt="playwright test"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this example, I change the example test at &lt;code&gt;apps/cats-playwright/e2e/example.spec.ts&lt;/code&gt; to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;has title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&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;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&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;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

  &lt;span class="c1"&gt;// Expect h1 to contain a substring.  &lt;/span&gt;
  &lt;span class="nf"&gt;expect&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;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toContain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cat Facts&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;Run command &lt;code&gt;npx nx run cats-playwright:e2e&lt;/code&gt;, and the tests should pass:&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%2Fmiro.medium.com%2Fv2%2F1%2Aye3g01hteuWjs_hZEkCD_g.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%2Fmiro.medium.com%2Fv2%2F1%2Aye3g01hteuWjs_hZEkCD_g.png" alt="Playwright Report"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Add Storybook
&lt;/h2&gt;

&lt;p&gt;To add the storybook, simply run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx generate @nx/react:storybook-configuration &amp;lt;your expo app name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, I should see in the console output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx g @nx/react:storybook-configuration cats  

&amp;gt;  NX  Generating @nx/react:storybook-configuration  

✔ Do you want to set up Storybook interaction tests? (Y/n) · true  
✔ Automatically generate \*.stories.ts files for components declared in this project? (Y/n) · true  

✔ Configure a static file server for the storybook instance? (Y/n) · true  
UPDATE nx.json  
UPDATE package.json  
CREATE apps/cats/.storybook/main.ts  
CREATE apps/cats/.storybook/preview.ts  
CREATE apps/cats/tsconfig.storybook.json  
UPDATE apps/cats/tsconfig.app.json  
UPDATE apps/cats/tsconfig.json  
UPDATE apps/cats/project.json  
CREATE apps/cats/src/app/App.stories.tsx  
CREATE apps/cats/src/app/bookmarks/bookmarks.stories.tsx  
CREATE apps/cats/src/app/facts/facts.stories.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is it! In one single, it should generate the Storybook for me. Run the command to see Storybook in web view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx run &amp;lt;your-expo-app&amp;gt;:storybook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It interpolates my native UI components to web components and then creates the Storybook. How does it achieve that?&lt;/p&gt;

&lt;p&gt;In this example, it generates a file &lt;code&gt;apps/cats/.storybook/main.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StorybookConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/react-webpack5&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;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StorybookConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;stories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/lib/&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;*/&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;*.stories.@(js|jsx|ts|tsx|mdx)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
  &lt;span class="na"&gt;addons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;  
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/addon-essentials&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="s1"&gt;@storybook/addon-interactions&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="s1"&gt;@nx/react/plugins/storybook&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
  &lt;span class="na"&gt;framework&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/react-webpack5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;options&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="na"&gt;webpackFinal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &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="k"&gt;if &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;resolve&lt;/span&gt;&lt;span class="p"&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;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alias&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-web&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;  
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.web.tsx&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="s1"&gt;.web.ts&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="s1"&gt;.web.jsx&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="s1"&gt;.web.js&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;  
      &lt;span class="err"&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="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="p"&gt;};&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="c1"&gt;// To customize your webpack configuration you can use the webpackFinal field.  &lt;/span&gt;
&lt;span class="c1"&gt;// Check https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config  &lt;/span&gt;
&lt;span class="c1"&gt;// and https://nx.dev/recipes/storybook/custom-builder-configs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice there is a line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;      &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alias&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-web&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;It uses Webpack to bundle and alias react-native to react-native-web.&lt;/p&gt;

&lt;p&gt;When serving up my Storybook for the first time, I have some issues and problems preventing components from rendering. Below are the issues I run into and how I troubleshoot them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Troubleshooting
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Root Element
&lt;/h4&gt;

&lt;p&gt;“Full-screen React Native apps with a root &lt;code&gt;&amp;lt;ScrollView&amp;gt;&lt;/code&gt; may require the following styles inlined in the HTML document shell.” (&lt;a href="https://necolas.github.io/react-native-web/docs/setup/#root-element" rel="noopener noreferrer"&gt;https://necolas.github.io/react-native-web/docs/setup/#root-element&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In this example, I do have a root element, so I need to add styles to &lt;code&gt;apps/cats/.storybook/preview-head.html&lt;/code&gt; to make my root full height:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  
  &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;These&lt;/span&gt; &lt;span class="nt"&gt;styles&lt;/span&gt; &lt;span class="nt"&gt;make&lt;/span&gt; &lt;span class="nt"&gt;the&lt;/span&gt; &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="nt"&gt;full-height&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;  
  &lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  
  &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;These&lt;/span&gt; &lt;span class="nt"&gt;styles&lt;/span&gt; &lt;span class="nt"&gt;disable&lt;/span&gt; &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="nt"&gt;scrolling&lt;/span&gt; &lt;span class="nt"&gt;if&lt;/span&gt; &lt;span class="nt"&gt;you&lt;/span&gt; &lt;span class="nt"&gt;are&lt;/span&gt; &lt;span class="nt"&gt;using&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ScrollView&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;  
  &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;These&lt;/span&gt; &lt;span class="nt"&gt;styles&lt;/span&gt; &lt;span class="nt"&gt;make&lt;/span&gt; &lt;span class="nt"&gt;the&lt;/span&gt; &lt;span class="nt"&gt;root&lt;/span&gt; &lt;span class="nt"&gt;element&lt;/span&gt; &lt;span class="nt"&gt;full-height&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;  
  &lt;span class="nf"&gt;#storybook-root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Error: Couldn’t find a navigation object.
&lt;/h4&gt;

&lt;p&gt;Because I am using the library &lt;code&gt;@react-navigation/native&lt;/code&gt; and I use its hooks like &lt;code&gt;useNavigtion&lt;/code&gt; and &lt;code&gt;useRoute&lt;/code&gt; inside my component, I have this error:&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%2Fmiro.medium.com%2Fv2%2F1%2ApA8gWYSeqJMFE0N2azCzGw.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%2Fmiro.medium.com%2Fv2%2F1%2ApA8gWYSeqJMFE0N2azCzGw.png" alt="Error: Couldn’t find a navigation object"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The easiest way is just to mock this library and create a &lt;a href="https://storybook.js.org/docs/react/writing-stories/decorators" rel="noopener noreferrer"&gt;decorator&lt;/a&gt; for it. In this example, I create a Navigation Decorator at &lt;code&gt;apps/cats/.storybook/mocks/navigation-decorator.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;NavigationContainer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-navigation/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;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NavigationDecorator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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;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;NavigationContainer&lt;/span&gt; &lt;span class="nx"&gt;independent&lt;/span&gt;&lt;span class="o"&gt;=&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;story&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;/NavigationContainer&amp;gt; &lt;/span&gt;&lt;span class="err"&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;Then I can add this decoration to my story file. In this example, I add it to &lt;code&gt;apps/cats/src/app/bookmarks/bookmarks.stories.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StoryObj&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/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;Bookmarks&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./bookmarks&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;within&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/testing-library&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;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/jest&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;NavigationDecorator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../../.storybook/mocks/navigation-decorator&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;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bookmarks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;decorators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NavigationDecorator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;---- add the decorator here  &lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;  
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;meta&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;Story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StoryObj&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Bookmarks&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Primary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;args&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Heading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;  
  &lt;span class="na"&gt;play&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;canvasElement&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;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;within&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvasElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Welcome to Bookmarks!/gi&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&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;h4&gt;
  
  
  Error: Couldn’t find a route object.
&lt;/h4&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%2Fmiro.medium.com%2Fv2%2F1%2AN3fsp2NcQ1svggvJQRK0lQ.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%2Fmiro.medium.com%2Fv2%2F1%2AN3fsp2NcQ1svggvJQRK0lQ.png" alt="Error: Couldn’t find a route object."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This issue is similar to “Couldn’t find a navigation object”, it is also related to the library &lt;code&gt;@react-navigation/native&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It happens because my component is using the &lt;code&gt;useRoute&lt;/code&gt; hook and expecting certain routing parameters. I simply need to customize the mock &lt;code&gt;NavigationDecorator&lt;/code&gt; for my component. For example, below is a component that is expecting an id from the route parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRoute&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RouteProp&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&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="kr"&gt;string&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;&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can simply modify the mock &lt;code&gt;NavigationDecorator&lt;/code&gt; at &lt;code&gt;apps/cats/.storybook/mocks/navigation-decorator.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;NavigationContainer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-navigation/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;createNativeStackNavigator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-navigation/native-stack&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;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NavigationDecorator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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;Stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createNativeStackNavigator&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;NavigationContainer&lt;/span&gt; &lt;span class="nx"&gt;independent&lt;/span&gt;&lt;span class="o"&gt;=&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="o"&gt;&amp;gt;&lt;/span&gt;  
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Navigator&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;Stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Screen&lt;/span&gt;  
          &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MyStorybookScreen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  
          &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
          &lt;span class="nx"&gt;initialParams&lt;/span&gt;&lt;span class="o"&gt;=&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="mi"&gt;123&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;  
        &lt;span class="sr"&gt;/&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Stack.Navigator&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/NavigationContainer&amp;gt; &lt;/span&gt;&lt;span class="err"&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;h4&gt;
  
  
  Error: No QueryClient set, use QueryClientProvider to set one
&lt;/h4&gt;

&lt;p&gt;This happens because I use the library @tanstack/react-query. I need to create a decorator for &lt;code&gt;QueryClientProvider&lt;/code&gt;. At &lt;code&gt;apps/cats/.storybook/mocks/query-client-decorator.tsx&lt;/code&gt;, I create this decorator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;QueryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&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;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;QueryClientDecorator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&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;QueryClientProvider&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&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;story&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;/QueryClientProvider&amp;gt; &lt;/span&gt;&lt;span class="err"&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;QueryClientDecorator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, my story at &lt;code&gt;apps/cats/src/app/facts/facts.stories.tsx&lt;/code&gt; will become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StoryObj&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/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;Facts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./facts&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;within&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/testing-library&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;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/jest&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;NavigationDecorator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../../.storybook/mocks/navigation-decorator&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;QueryClientDecorator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../../.storybook/mocks/query-client-decorator&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;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Facts&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Facts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Facts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;decorators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NavigationDecorator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClientDecorator&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;---- add the QueryClientDecorator here  &lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;  
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;meta&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;Story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StoryObj&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Facts&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Primary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;args&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Heading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;  
  &lt;span class="na"&gt;play&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;canvasElement&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;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;within&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvasElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Welcome to Facts!/gi&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&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;h4&gt;
  
  
  Error: Unable to load react-native-vector-icons.
&lt;/h4&gt;

&lt;p&gt;I got this error when I tried to compile the storybook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You may need an additional loader to handle the result of these loaders.  
|   
|       return (  
&amp;gt;         &amp;lt;Text selectable={false} {...props}&amp;gt;  
|           {glyph}  
|           {children}  
 @ ./node\_modules/react-native-vector-icons/MaterialCommunityIcons.js 6:0-50 9:16-29  
 @ ./node\_modules/react-native-paper/lib/module/components/MaterialCommunityIcon.js 8:27-94  
 @ ./node\_modules/react-native-paper/lib/module/core/PaperProvider.js 3:0-72 73:12-33  
 @ ./node\_modules/react-native-paper/lib/module/index.js 4:0-59 4:0-59 5:0-64 5:0-64  
 @ ./apps/cats/src/app/App.tsx 1:717-760 1:1882-1892  
 @ ./apps/cats/src/app/ lazy ^\\.\\/.\*$ namespace object ./App.tsx ./App  
 @ ./storybook-stories.js 1:383-427  
 @ ./storybook-config-entry.js 1:171-216 1:1789-1797 1:1871-1985 1:1926-1984 1:1972-1980
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This happens because I use the library &lt;code&gt;react-native-paper&lt;/code&gt; which depends on &lt;code&gt;react-native-vector-icons&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In react-native-vector-icons, it &lt;code&gt;.js&lt;/code&gt; files contain &lt;code&gt;jsx&lt;/code&gt; code: &lt;code&gt;&amp;lt;Text selectable={false} {…props}&amp;gt;&lt;/code&gt;. To solve this, I need to load the &lt;code&gt;react-native-vector-icons&lt;/code&gt; library using babel-loader. In this example, I can add a rule to Storybook’s Webpack config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;        &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rules&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="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sr"&gt;.&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;js|jsx&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/react-native-vector-icons/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babel-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="na"&gt;presets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;  
              &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
              &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-react&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;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;automatic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
            &lt;span class="err"&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;Then I need to also load the font &lt;a href="https://github.com/oblador/react-native-vector-icons/blob/master/Fonts/MaterialCommunityIcons.ttf" rel="noopener noreferrer"&gt;MaterialCommunityIcons.ttf&lt;/a&gt; for Storybook:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Download the font from &lt;a href="https://github.com/oblador/react-native-vector-icons/blob/master/Fonts/MaterialCommunityIcons.ttf" rel="noopener noreferrer"&gt;https://github.com/oblador/react-native-vector-icons/blob/master/Fonts/MaterialCommunityIcons.ttf&lt;/a&gt; to &lt;code&gt;apps/cats/.storybook/public&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Add &lt;code&gt;staticDirs&lt;/code&gt; option to Storybook configuration at &lt;code&gt;apps/cats/.storybook/main.ts&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;staticDirs: \['./public'\],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Add the below style to &lt;code&gt;apps/cats/.storybook/preview-head.html&lt;/code&gt; to load the font:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  
  &lt;span class="k"&gt;@font-face&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'MaterialCommunityIcons'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nl"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url('/MaterialCommunityIcons.ttf')&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;'truetype'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Storybook configuration at &lt;code&gt;apps/cats/.storybook/main.ts&lt;/code&gt; will become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StorybookConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/react-webpack5&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;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StorybookConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;stories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/app/&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;*/&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;*.stories.@(js|jsx|ts|tsx|mdx)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
  &lt;span class="na"&gt;staticDirs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
  &lt;span class="na"&gt;addons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;  
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/addon-essentials&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="s1"&gt;@storybook/addon-interactions&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="s1"&gt;@nx/react/plugins/storybook&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
  &lt;span class="na"&gt;framework&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/react-webpack5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;options&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="na"&gt;webpackFinal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &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="k"&gt;if &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;resolve&lt;/span&gt;&lt;span class="p"&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;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alias&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-web&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;  
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.web.tsx&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="s1"&gt;.web.ts&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="s1"&gt;.web.jsx&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="s1"&gt;.web.js&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;  
      &lt;span class="err"&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="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&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="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rules&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="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sr"&gt;.&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;js|jsx&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/react-native-vector-icons/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babel-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="na"&gt;presets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;  
              &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-env&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
              &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@babel/preset-react&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;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;automatic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
            &lt;span class="err"&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="p"&gt;}&lt;/span&gt;  
    &lt;span class="k"&gt;return&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="p"&gt;};&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="c1"&gt;// To customize your webpack configuration you can use the webpackFinal field.  &lt;/span&gt;
&lt;span class="c1"&gt;// Check https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config  &lt;/span&gt;
&lt;span class="c1"&gt;// and https://nx.dev/recipes/storybook/custom-builder-configs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can see react-native-vector-icons are being loaded correctly for the Storybook.&lt;/p&gt;

&lt;p&gt;Now I can run &lt;code&gt;npx nx run cats:storybook&lt;/code&gt; and it should render the storybook for me.&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%2Fmiro.medium.com%2Fv2%2F1%2AfsIiNQYHderYggGQMmmZxg.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%2Fmiro.medium.com%2Fv2%2F1%2AfsIiNQYHderYggGQMmmZxg.png" alt="Storybook"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this article, you have learned how to add &lt;a href="https://nx.dev/nx-api/cypress" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;, &lt;a href="https://nx.dev/nx-api/playwright" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;, and &lt;a href="https://nx.dev/nx-api/storybook" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; to your Nx Expo app.&lt;/p&gt;

&lt;p&gt;With Nx, it will help you with your Expo development process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  🧠 &lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  👩‍💻 &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  💬 &lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;Nx Community Slack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  📹 &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  🚀 &lt;a href="https://nx.app/" rel="noopener noreferrer"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cypress</category>
      <category>playwright</category>
      <category>storybook</category>
      <category>expo</category>
    </item>
    <item>
      <title>Unit Testing Expo Apps With Jest</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Mon, 19 Feb 2024 19:11:00 +0000</pubDate>
      <link>https://forem.com/nx/unit-testing-expo-apps-with-jest-2c5a</link>
      <guid>https://forem.com/nx/unit-testing-expo-apps-with-jest-2c5a</guid>
      <description>&lt;p&gt;In my latest &lt;a href="https://dev.to/nx/step-by-step-guide-to-creating-an-expo-monorepo-with-nx-3b17"&gt;blog&lt;/a&gt;, I successfully navigated through the steps of setting up an Expo Monorepo with &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx&lt;/a&gt;. The next challenge? Testing! This blog dives into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Crafting effective unit tests for Expo components utilizing Jest&lt;/li&gt;
&lt;li&gt;  Addressing common issues encountered during unit testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/xiongemi" rel="noopener noreferrer"&gt;
        xiongemi
      &lt;/a&gt; / &lt;a href="https://github.com/xiongemi/nx-expo-monorepo" rel="noopener noreferrer"&gt;
        nx-expo-monorepo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      a repo showing 2 apps created by @nx/expo
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;NxExpoMonorepo&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;This workspace is created using &lt;a href="https://nx.dev/packages/expo" rel="nofollow noopener noreferrer"&gt;@nx/expo&lt;/a&gt; (&lt;a href="https://nx.dev" rel="nofollow noopener noreferrer"&gt;Nx&lt;/a&gt; and &lt;a href="https://expo.io/" rel="nofollow noopener noreferrer"&gt;Expo&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nx.dev" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fnrwl%2Fnx%2Fmaster%2Fimages%2Fnx-logo.png" width="45"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;✨ &lt;strong&gt;This workspace has been generated by &lt;a href="https://nx.dev" rel="nofollow noopener noreferrer"&gt;Nx, a Smart, fast and extensible build system.&lt;/a&gt;&lt;/strong&gt; ✨&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Workspace structure&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;It contains 2 apps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cats and its e2e (cypress/playwright)&lt;/li&gt;
&lt;li&gt;dogs and its e2e (cypress/playwright)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;4 libs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;models&lt;/li&gt;
&lt;li&gt;queries: &lt;a href="https://react-query.tanstack.com/" rel="nofollow noopener noreferrer"&gt;tanstack react-query&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;states: redux state management&lt;/li&gt;
&lt;li&gt;ui&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xiongemi/nx-expo-monorepo/blob/main/screenshots/cats.png?raw=true"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fxiongemi%2Fnx-expo-monorepo%2Fraw%2Fmain%2Fscreenshots%2Fcats.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xiongemi/nx-expo-monorepo/blob/main/screenshots/dogs.png?raw=true"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fxiongemi%2Fnx-expo-monorepo%2Fraw%2Fmain%2Fscreenshots%2Fdogs.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Commands&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nx start cats&lt;/code&gt; to start the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx start dogs&lt;/code&gt; to start the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx build cats&lt;/code&gt; to build the cats app using EAS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx build dogs&lt;/code&gt; to build the dogs app using EAS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx test cats&lt;/code&gt; to test the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx test dogs&lt;/code&gt; to test the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx lint cats&lt;/code&gt; to lint the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx lint dogs&lt;/code&gt; to lint the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run deploy&lt;/code&gt; to deploy the cats app to github page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx e2e cats-cypress&lt;/code&gt; to run cypress e2e tests on cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx e2e cats-playwright&lt;/code&gt; to…&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/xiongemi/nx-expo-monorepo" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


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

&lt;p&gt;Here’s my setup&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Testing framework: &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;jest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Testing library: &lt;a href="https://callstack.github.io/react-native-testing-library/" rel="noopener noreferrer"&gt;@testing-library/react-native&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Jest Preset: &lt;a href="https://www.npmjs.com/package/jest-expo" rel="noopener noreferrer"&gt;jest-expo&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Writing and Running Unit Tests
&lt;/h2&gt;

&lt;p&gt;When you use Nx, it not only configures and sets up Jest, but also creates a default unit test for every expo component that is being generated. Here’s what that looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/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;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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="nx"&gt;Loading&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should render successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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;root&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&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;Loading&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;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&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;To run all unit tests for a given project, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx &lt;span class="nb"&gt;test&lt;/span&gt; &amp;lt;project-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s the output of running this for my example app:&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%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A720%2Fformat%3Awebp%2F1%2AA-d1u9T8YhRwlP4ZLoACzA.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%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A720%2Fformat%3Awebp%2F1%2AA-d1u9T8YhRwlP4ZLoACzA.png" alt="terminal output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When it comes to writing tests, the &lt;a href="https://callstack.github.io/react-native-testing-library/docs/api-queries" rel="noopener noreferrer"&gt;React Native Testing Library&lt;/a&gt; is a game-changer for writing cleaner unit tests in React Native applications. Its intuitive query API simplifies the process of selecting elements within your components, making it straightforward to write more maintainable and readable tests. You mark elements with a &lt;code&gt;testID&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Headline&lt;/span&gt; &lt;span class="na"&gt;testID=&lt;/span&gt;&lt;span class="s"&gt;'title'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{film.title}&lt;span class="nt"&gt;&amp;lt;/Headline&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in the test file, you can use the function &lt;code&gt;getByTestId&lt;/code&gt; to query &lt;code&gt;testID&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;getByTestId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&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;your&lt;/span&gt; &lt;span class="nx"&gt;component&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;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toHaveTextContent&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find more options for querying elements on the official React Native Testing Library docs: &lt;a href="https://callstack.github.io/react-native-testing-library/docs/api-queries" rel="noopener noreferrer"&gt;https://callstack.github.io/react-native-testing-library/docs/api-queries&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting Common Issues When Writing Tests
&lt;/h2&gt;

&lt;p&gt;However, unit tests do not always pass. Here are some common errors I ran into and how to resolve them.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Error: AsyncStorage is null.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I am using the library &lt;code&gt;@react-native-async-storage/async-storage&lt;/code&gt;, and I got the below error when running unit testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; \[@RNC/AsyncStorage\]: NativeModule: AsyncStorage is null.  

    To fix this issue try these steps:  

      • Rebuild and restart the app.  

      • Run the packager with \`--reset-cache\` flag.  

      • If you are using CocoaPods on iOS, run \`pod install\` in the \`ios\` directory and then rebuild and re-run the app.  

      • If this happens while testing with Jest, check out docs how to integrate AsyncStorage with it: https://react-native-async-storage.github.io/async-storage/docs/advanced/jest  

    If none of these fix the issue, please open an issue on the Github repository: https://github.com/react-native-async-storage/async-storage/issues  

       5 | import { ReactQueryDevtools } from '@tanstack/react-query-devtools';  
       6 | import { Platform } from 'react-native';  
    &amp;gt;  7 | import AsyncStorage from '@react-native-async-storage/async-storage';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue is that &lt;code&gt;@react-native-async-storage/async-storage&lt;/code&gt; library can only be used in &lt;code&gt;NativeModule&lt;/code&gt;. Since unit testing with Jest only tests JS/TS file logic, I need to mock this library.&lt;/p&gt;

&lt;p&gt;In the app’s test-setup.ts file, add the below lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-native-async-storage/async-storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  
  &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-native-async-storage/async-storage/jest/async-storage-mock&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;h2&gt;
  
  
  Error: Could not find “store”
&lt;/h2&gt;

&lt;p&gt;I am using Redux for state management, and I got this error for my stateful components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Could not find "store" in the context of "Connect(Bookmarks)". Either wrap the root component in a &amp;lt;Provider&amp;gt;, or pass a custom React context provider to &amp;lt;Provider&amp;gt; and the corresponding React context consumer to Connect(Bookmarks) in connect options.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To fix this, the simple way is to mock a redux store. I need to install &lt;a href="https://github.com/reduxjs/redux-mock-store" rel="noopener noreferrer"&gt;redux-mock-store&lt;/a&gt; and its typing:&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="se"&gt;\#&lt;/span&gt; npm  
npm &lt;span class="nb"&gt;install &lt;/span&gt;redux-mock-store @types/redux-mock-store &lt;span class="nt"&gt;--save-dev&lt;/span&gt;  

&lt;span class="se"&gt;\#&lt;/span&gt; yarn  
yarn add redux-mock-store @types/redux-mock-store &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I can create a mock store using this library like the below code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MockStoreEnhanced&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux-mock-store&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;mockStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;configureStore&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;  

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MockStoreEnhanced&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&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;beforeEach&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;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mockStore&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;  
    &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&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;For example, one of my stateful components’ unit test will become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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="s1"&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;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/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;Provider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&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;configureStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MockStoreEnhanced&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux-mock-store&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;RootState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialRootState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nx-expo-monorepo/states/cat&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;Bookmarks&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./bookmarks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bookmarks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;configureStore&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RootState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;  

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MockStoreEnhanced&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RootState&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;beforeEach&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;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mockStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialRootState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;  

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should render successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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;container&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&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;Provider&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Bookmarks&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;/Provider&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="nf"&gt;expect&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="nf"&gt;toBeTruthy&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;The above code will apply the initial redux state to my components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error: No QueryClient set
&lt;/h3&gt;

&lt;p&gt;Because I use &lt;a href="https://tanstack.com/query/latest" rel="noopener noreferrer"&gt;TanStack Query&lt;/a&gt; , when I run unit tests, I have this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No QueryClient set, use QueryClientProvider to set one
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This error occurred because I used &lt;code&gt;useQuery&lt;/code&gt; from &lt;code&gt;@tanstack/react-query&lt;/code&gt; in my component; however, in this unit test, the context of this hook is not provided.&lt;/p&gt;

&lt;p&gt;To solve this, I can just mock the &lt;code&gt;useQuery&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="err"&gt;\&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;ReactQuery&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ReactQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;useQuery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mockImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
  &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;mockReturnValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;random cat fact&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;isLoading&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;isSuccess&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;refetch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;  
    &lt;span class="na"&gt;isFetching&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;isError&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="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Error: Couldn’t find a navigation object
&lt;/h3&gt;

&lt;p&gt;If you use &lt;code&gt;@react-navigation&lt;/code&gt; library for navigation, and inside your component, there are hooks from this library like &lt;code&gt;useNavigation&lt;/code&gt; and &lt;code&gt;useRoute&lt;/code&gt;, you are likely to get this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Couldn't find a navigation object. Is your component inside NavigationContainer?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix this, I need to mock the &lt;code&gt;@react-nativgation/native&lt;/code&gt; library. In the app’s test-setup.ts file, I need to add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-navigation/native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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="na"&gt;useNavigation&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="p"&gt;({&lt;/span&gt;  
      &lt;span class="na"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;  
      &lt;span class="na"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;  
      &lt;span class="na"&gt;setOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="p"&gt;}),&lt;/span&gt;  
    &lt;span class="na"&gt;useRoute&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="p"&gt;({&lt;/span&gt;  
      &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123&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;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  SyntaxError: Unexpected token ‘export’
&lt;/h3&gt;

&lt;p&gt;I got this error when using a library with ECMAScript Module (ESM), such as &lt;code&gt;[udid](https://github.com/uuidjs/uuid)&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; /Users/emilyxiong/Code/nx-expo-monorepo/node\_modules/uuid/dist/esm-browser/index.js:1  
    ({"Object.&amp;lt;anonymous&amp;gt;":function(module,exports,require,\_\_dirname,\_\_filename,jest){export { default as v1 } from './v1.js';  
                                                                                      ^^^^^^  

    SyntaxError: Unexpected token 'export'  

       5 | import { connect } from 'react-redux';  
       6 | import 'react-native-get-random-values';  
    &amp;gt;  7 | import { v4 as uuidv4 } from 'uuid';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jest does not work with ESM out of the box. The simple solution is to map this library to the CommonJS version of this library.&lt;/p&gt;

&lt;p&gt;In the app’s &lt;code&gt;jest.config.ts&lt;/code&gt;, there should be an option called &lt;code&gt;moduleNameMapper&lt;/code&gt;. The library I used is called &lt;code&gt;uuid&lt;/code&gt;, so I need to add the map &lt;code&gt;uuid: require.resolve(‘uuid’)&lt;/code&gt; under &lt;code&gt;moduleNameMapper&lt;/code&gt;. So when the code encounters imports from &lt;code&gt;uuid&lt;/code&gt; library, it will resolve the CommonJS version of it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;moduleNameMapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uuid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, I can also mock this library in the test files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;v4&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;uuidv4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uuid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uuid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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="na"&gt;v4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Error: Jest encountered an unexpected token
&lt;/h2&gt;

&lt;p&gt;I got this error when I was importing from a library such as &lt;a href="https://github.com/oblador/react-native-vector-icons" rel="noopener noreferrer"&gt;react-native-vector-icons&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; console.error  
      Jest encountered an unexpected token  

      Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.  

      Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.  

      By default "node\_modules" folder is ignored by transformers.  

      Here's what you can do:  
       • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.  
       • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript  
       • To have some of your "node\_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.  
       • If you need a custom transformation specify a "transform" option in your config.  
       • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.  

      You'll find more details and examples of these config options in the docs:  
      https://jestjs.io/docs/configuration  
      For information about custom transformations, see:  
      https://jestjs.io/docs/code-transformation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To fix this, add this library name to &lt;code&gt;transformIgnorePatterns&lt;/code&gt; in the app's jest.config.ts.&lt;/p&gt;

&lt;p&gt;What is &lt;code&gt;transformIgnorePatterns&lt;/code&gt;? The &lt;code&gt;transformIgnorePatterns&lt;/code&gt; allows developers to specify which files shall be transformed by Babel. &lt;code&gt;transformIgnorePatterns&lt;/code&gt; is an array of regexp pattern strings that should be matched against all source file paths before the transformation. If the file path matches any patterns, it will not be transformed by Babel.&lt;/p&gt;

&lt;p&gt;By default, Jest will ignore all the files under node_modules and only transform the files under the project’s src.&lt;/p&gt;

&lt;p&gt;However, some libraries such as &lt;code&gt;react-native-paper&lt;/code&gt; or &lt;code&gt;react-native-svg&lt;/code&gt;, the library files are in &lt;code&gt;.ts&lt;/code&gt; or &lt;code&gt;.tsx&lt;/code&gt;. These files are not compiled to &lt;code&gt;js&lt;/code&gt;. So I need to add these libraries' names to &lt;code&gt;transformIgnorePatterns&lt;/code&gt;, so these libraries will be transformed by Babel along with my project. source file. The default generated &lt;code&gt;jest.config.js&lt;/code&gt; already has:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;transformIgnorePatterns: \[  
    'node\_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.\*|@expo-google-fonts/.\*|react-navigation|@react-navigation/.\*|@unimodules/.\*|unimodules|sentry-expo|native-base|react-native-svg)',  
\]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I have an error related to a library with an unexpected token, I need to check whether they are compiled or not.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If this library source files are already transformed to &lt;code&gt;.js&lt;/code&gt;, then its name should match regex, so it would be ignored, so it will NOT be transformed.&lt;/li&gt;
&lt;li&gt;  If this library source files are NOT transformed to &lt;code&gt;.js&lt;/code&gt; (e.g. still in &lt;code&gt;.ts&lt;/code&gt; or &lt;code&gt;.tsx&lt;/code&gt;), then its name should NOT match regex, so it will be transformed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Here are some common errors that I will probably run into while doing unit testing. The solution to most problems is to find a way to mock a library that is not relevant to my component logic.&lt;/p&gt;

&lt;p&gt;With Nx, you do not need to explicitly install any testing library, so you can dive right in and focus on writing the tests rather than spending time on setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://medium.com/@emilyxiong/add-cypress-playwright-and-storybook-to-nx-expo-apps-1d3e409ce834" rel="noopener noreferrer"&gt;Add Cypress, Playwright, and Storybook to Nx Expo Apps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  🧠 &lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  👩‍💻 &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  💬 &lt;a href="https://go.nrwl.io/community" rel="noopener noreferrer"&gt;Nx Community Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  📹 &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  🚀 &lt;a href="https://nx.app/" rel="noopener noreferrer"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>expo</category>
      <category>jest</category>
      <category>nx</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>State Management Nx React Native/Expo Apps with TanStack Query and Redux</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Fri, 16 Feb 2024 23:21:05 +0000</pubDate>
      <link>https://forem.com/nx/state-management-nx-react-nativeexpo-apps-with-tanstack-query-and-redux-397d</link>
      <guid>https://forem.com/nx/state-management-nx-react-nativeexpo-apps-with-tanstack-query-and-redux-397d</guid>
      <description>&lt;p&gt;There are currently countless numbers of state management libraries out there. This blog will show you how to use state management for React Native in Nx monorepo with &lt;a href="https://tanstack.com/query/latest"&gt;TanStack Query&lt;/a&gt; (which happens &lt;a href="https://cloud.nx.app/orgs/6412ca9d1c251d000efa21ba/workspaces/6412c827e6da5d7b4a0b1fe3/overview"&gt;to use Nx on their repo&lt;/a&gt;) and Redux.&lt;/p&gt;

&lt;p&gt;This blog will show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  How to set up these libraries and their dev tools&lt;/li&gt;
&lt;li&gt;  How to build the sample page below in React Native / Expo with state management&lt;/li&gt;
&lt;li&gt;  How to do unit testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It will call an API and show a cat fact on the page, allowing users to like or dislike the 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%2Fuploads%2Farticles%2Fxs31z7e954qjnjhvyjmm.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%2Fuploads%2Farticles%2Fxs31z7e954qjnjhvyjmm.png" alt="Cats App" width="800" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Github repo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/xiongemi"&gt;
        xiongemi
      &lt;/a&gt; / &lt;a href="https://github.com/xiongemi/nx-expo-monorepo"&gt;
        nx-expo-monorepo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      a repo showing 2 apps created by @nx/expo
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
NxExpoMonorepo&lt;/h1&gt;
&lt;p&gt;This workspace is created using &lt;a href="https://nx.dev/packages/expo" rel="nofollow"&gt;@nx/expo&lt;/a&gt; (&lt;a href="https://nx.dev" rel="nofollow"&gt;Nx&lt;/a&gt; and &lt;a href="https://expo.io/" rel="nofollow"&gt;Expo&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nx.dev" rel="nofollow"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RoBOQypH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;✨ &lt;strong&gt;This workspace has been generated by &lt;a href="https://nx.dev" rel="nofollow"&gt;Nx, a Smart, fast and extensible build system.&lt;/a&gt;&lt;/strong&gt; ✨&lt;/p&gt;
&lt;h2&gt;
Workspace structure&lt;/h2&gt;
&lt;p&gt;It contains 2 apps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cats and its e2e (cypress/playwright)&lt;/li&gt;
&lt;li&gt;dogs and its e2e (cypress/playwright)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;4 libs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;models&lt;/li&gt;
&lt;li&gt;queries: &lt;a href="https://react-query.tanstack.com/" rel="nofollow"&gt;tanstack react-query&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;states: redux state management&lt;/li&gt;
&lt;li&gt;ui&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xiongemi/nx-expo-monorepo/blob/main/screenshots/cats.png?raw=true"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QiOp2J1T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/xiongemi/nx-expo-monorepo/raw/main/screenshots/cats.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xiongemi/nx-expo-monorepo/blob/main/screenshots/dogs.png?raw=true"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7hT-VlL2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/xiongemi/nx-expo-monorepo/raw/main/screenshots/dogs.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Commands&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nx start cats&lt;/code&gt; to start the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx start dogs&lt;/code&gt; to start the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx build cats&lt;/code&gt; to build the cats app using EAS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx build dogs&lt;/code&gt; to build the dogs app using EAS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx test cats&lt;/code&gt; to test the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx test dogs&lt;/code&gt; to test the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx lint cats&lt;/code&gt; to lint the cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx lint dogs&lt;/code&gt; to lint the dogs app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run deploy&lt;/code&gt; to deploy the cats app to github page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx e2e cats-cypress&lt;/code&gt; to run cypress e2e tests on cats app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nx e2e cats-playwright&lt;/code&gt; to…&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/xiongemi/nx-expo-monorepo"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Before We Start
&lt;/h2&gt;

&lt;p&gt;From &lt;a href="https://tanstack.com/query/latest/docs/react/guides/does-this-replace-client-state"&gt;TanStack Query documentation&lt;/a&gt;, it says:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://tanstack.com/query/latest/docs/react/overview"&gt;TanStack Query&lt;/a&gt;  is a &lt;strong&gt;server-state&lt;/strong&gt; library.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt; is a &lt;strong&gt;client-state&lt;/strong&gt; library.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is the difference between the server state and the client state?&lt;/p&gt;

&lt;p&gt;In short:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Calling an API, dealing with asynchronous data-&amp;gt; server state&lt;/li&gt;
&lt;li&gt;  Everything else about UI, dealing with synchronous data -&amp;gt; client state&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;To use &lt;a href="https://tanstack.com/query/latest"&gt;&lt;strong&gt;TanStack Query&lt;/strong&gt; / &lt;strong&gt;React Query&lt;/strong&gt;&lt;/a&gt;  for the server state, I need to install:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Library: &lt;a href="https://tanstack.com/query/latest"&gt;@tanstack/react-query&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Dev tools: &lt;a href="https://tanstack.com/query/latest/docs/react/devtools"&gt;@tanstack/react-query-devtools&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will use &lt;strong&gt;Redux&lt;/strong&gt; for everything else.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Library: &lt;a href="https://github.com/reduxjs/redux"&gt;redux&lt;/a&gt;, react-redux, @reduxjs/toolkit&lt;/li&gt;
&lt;li&gt;  Dev tools: &lt;a href="https://github.com/zalmoxisus/redux-devtools-extension"&gt;@redux-devtools/extension&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Logger: &lt;a href="https://github.com/LogRocket/redux-logger"&gt;redux-logger&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/@types/redux-logger"&gt;@types/redux-logger&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Storage: &lt;a href="https://github.com/rt2zz/redux-persist"&gt;redux-persist&lt;/a&gt;, &lt;a href="https://github.com/react-native-async-storage/async-storage"&gt;@react-native-async-storage/async-storage&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To install all the above packages:&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;#npm  &lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; @tanstack/react-query @tanstack/react-query-devtools redux react-redux @reduxjs/toolkit @redux-devtools/extension redux-logger @types/redux-logger redux-persist @react-native-async-storage/async-storage &lt;span class="nt"&gt;--save-dev&lt;/span&gt;  

&lt;span class="c"&gt;#yarn  &lt;/span&gt;
yarn add @tanstack/react-query @tanstack/react-query-devtools redux react-redux @reduxjs/toolkit @redux-devtools/extension redux-logger @types/redux-logger redux-persist @react-native-async-storage/async-storage &lt;span class="nt"&gt;--dev&lt;/span&gt;  

&lt;span class="c"&gt;#pnpm  &lt;/span&gt;
pnpm add @tanstack/react-query @tanstack/react-query-devtools redux react-redux @reduxjs/toolkit @redux-devtools/extension redux-logger @types/redux-logger redux-persist @react-native-async-storage/async-storage &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Server State with React Query
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Setup Devtools
&lt;/h3&gt;

&lt;p&gt;First, you need to add React Query / TanStack Query in the &lt;code&gt;App.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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="s1"&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;QueryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&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;ReactQueryDevtools&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query-devtools&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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;const&lt;/span&gt; &lt;span class="nx"&gt;App&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;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&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;QueryClientProvider&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&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;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="s1"&gt;web&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReactQueryDevtools&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/QueryClientProvider&amp;gt; &lt;/span&gt;&lt;span class="err"&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&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 &lt;a href="https://tanstack.com/query/latest/docs/react/devtools"&gt;React Query Devtools&lt;/a&gt; currently do not support react native, and it only works on the web, so there is a condition: &lt;code&gt;{ Platform.OS === ‘web’ &amp;amp;&amp;amp; &amp;lt;ReactQueryDevtools /&amp;gt;}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the react native apps, in order to use this tool, you need to use &lt;a href="https://necolas.github.io/react-native-web/"&gt;react-native-web&lt;/a&gt; to interpolate your native app to the web app first.&lt;/p&gt;

&lt;p&gt;If you open my Expo app on the web by running &lt;code&gt;nx start cats&lt;/code&gt; and choose the options &lt;code&gt;Press w │ open web&lt;/code&gt;, you should be able to use the dev tools and see the state of my react queries:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BdW9dxXW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2ApwWnPsEymAZAaYTF3SjnmA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BdW9dxXW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2ApwWnPsEymAZAaYTF3SjnmA.png" alt="React Query Devtools" width="800" height="1704"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a Query
&lt;/h3&gt;

&lt;p&gt;What is a query?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“A query is a declarative dependency on an asynchronous source of data that is tied to a unique key. A query can be used with any Promise-based method (including GET and POST methods) to fetch data from a server.” (&lt;a href="https://tanstack.com/query/latest/docs/react/guides/queries"&gt;https://tanstack.com/query/v4/docs/react/guides/queries&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now let’s add our first query. In this example, it will be added under&lt;code&gt;lib/queries&lt;/code&gt; folder. To create a query to fetch a new fact about cats, run the command:&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 workspace  &lt;/span&gt;
npx nx generate @nx/expo:lib use-cat-fact &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;queries  

&lt;span class="c"&gt;# react-native workspace  &lt;/span&gt;
npx nx generate @nx/react-native:lib use-cat-fact &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;queries
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or use &lt;a href="https://nx.dev/recipes/nx-console"&gt;Nx Console&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TOKiTc6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2A6mZI98DHk9j-CZ0fjSlW7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TOKiTc6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2A6mZI98DHk9j-CZ0fjSlW7g.png" alt="Nx Console" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now notice under libs folder, &lt;code&gt;use-cat-fact&lt;/code&gt; folder got created under &lt;code&gt;libs/queries&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--24qvpQwv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/1%2A9gobKMSOOmOi3PYg93_LBQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--24qvpQwv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/1%2A9gobKMSOOmOi3PYg93_LBQ.png" alt="use-cat-fact" width="648" height="862"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you use React Native CLI, just add a folder in your workspace root.&lt;/p&gt;

&lt;p&gt;For this app, let’s use this API: &lt;a href="https://catfact.ninja/"&gt;https://catfact.ninja/&lt;/a&gt;. At &lt;code&gt;libs/queries/use-cat-fact/src/lib/use-cat-fact.ts&lt;/code&gt;, add code to fetch the data from this API:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchCatFact&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://catfact.ninja/fact&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;data&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;};&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useCatFact&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;return&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
    &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cat-fact&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
    &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fetchCatFact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;enabled&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Essentially, you have created a custom hook that calls &lt;code&gt;useQuery&lt;/code&gt; function from the TanStack Query library.&lt;/p&gt;
&lt;h3&gt;
  
  
  Unit Testing
&lt;/h3&gt;

&lt;p&gt;If you render this hook directly and run the unit test with the command &lt;code&gt;npx nx test queries-use-cat-fact&lt;/code&gt;, this error will show up in the console:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:  
    1. You might have mismatching versions of React and the renderer (such as React DOM)  
    2. You might be breaking the Rules of Hooks  
    3. You might have more than one copy of React in the same app  
    See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To solve this, you need to wrap your component inside the &lt;code&gt;renderHook&lt;/code&gt; function from &lt;code&gt;@testing-library/react-native&lt;/code&gt; library:&lt;/p&gt;
&lt;h4&gt;
  
  
  1. Install Library to Mock Fetch
&lt;/h4&gt;

&lt;p&gt;Depending on which library you use to make HTTP requests. (e.g. fetch, axios), you need to install a library to mock the response.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you use &lt;code&gt;fetch&lt;/code&gt; to fetch data, you need to install &lt;code&gt;jest-fetch-mock&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If you use &lt;code&gt;axios&lt;/code&gt; to fetch data, you need to install 
&lt;code&gt;axios-mock-adapter&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this example, since it uses fetch, you need to install &lt;code&gt;jest-fetch-mock&lt;/code&gt;:&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;#npm  &lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;jest-fetch-mock &lt;span class="nt"&gt;--save-dev&lt;/span&gt;  

&lt;span class="c"&gt;#yarn  &lt;/span&gt;
yard add jest-fetch-mock &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You also need to mock &lt;code&gt;fetch&lt;/code&gt; library in &lt;code&gt;libs/queries/use-cat-fact/test-setup.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fetchMock&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jest-fetch-mock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nx"&gt;fetchMock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enableMocks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  2. Create Mock Query Provider
&lt;/h4&gt;

&lt;p&gt;To test out &lt;code&gt;useQuery&lt;/code&gt; hook, you need to wrap it inside a mock &lt;code&gt;QueryClientProvider&lt;/code&gt;. Since this mock query provider is going to be used more than once, let’s create a library for this wrapper:&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 library  &lt;/span&gt;
npx nx generate @nx/expo:library test-wrapper &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;queries  

&lt;span class="c"&gt;# react native library  &lt;/span&gt;
npx nx generate @nx/react-native:library test-wrapper &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;queries
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then a component inside this library:&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 library  &lt;/span&gt;
npx nx generate @nx/expo:component test-wrapper &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;queries-test-wrapper  

&lt;span class="c"&gt;# react native library  &lt;/span&gt;
npx nx generate @nx/react-native:component test-wrapper &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;queries-test-wrapper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Add the mock &lt;code&gt;QueryClientProvider&lt;/code&gt; in &lt;code&gt;libs/queries/test-wrapper/src/lib/test-wrapper/test-wrapper.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;QueryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&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;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;TestWrapperProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TestWrapper&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;TestWrapperProps&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;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&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;QueryClientProvider&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&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;children&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;/QueryClientProvider&amp;gt; &lt;/span&gt;&lt;span class="err"&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;TestWrapper&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  3. Use Mock Responses in Unit Test
&lt;/h4&gt;

&lt;p&gt;Then this is what the unit test for my query would look like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;TestWrapper&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nx-expo-monorepo/queries/test-wrapper&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;renderHook&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;waitFor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/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;useCatFact&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./use-cat-fact&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;fetchMock&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jest-fetch-mock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;useCatFact&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;afterEach&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;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resetAllMocks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;  

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status should be success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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="c1"&gt;// simulating a server response  &lt;/span&gt;
    &lt;span class="nx"&gt;fetchMock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockResponseOnce&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="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
      &lt;span class="na"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;random cat fact&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;useCatFact&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TestWrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="p"&gt;});&lt;/span&gt;  
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// refetching the query  &lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;waitFor&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;random cat fact&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status should be error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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="nx"&gt;fetchMock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockRejectOnce&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;result&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;useCatFact&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TestWrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="p"&gt;});&lt;/span&gt;  
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// refetching the query  &lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;waitFor&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you use axios, your unit test would look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;TestWrapper&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nx-expo-monorepo/queries/test-wrapper&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;renderHook&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;waitFor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/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;useCatFact&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./use-cat-fact&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;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&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;MockAdapter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios-mock-adapter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// This sets the mock adapter on the default instance&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockAxios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MockAdapter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;useCatFact&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;afterEach&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;mockAxios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status should be success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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="c1"&gt;// simulating a server response&lt;/span&gt;
    &lt;span class="nx"&gt;mockAxios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onGet&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replyOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;random cat fact&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;useCatFact&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TestWrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// refetching the query&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;waitFor&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;random cat fact&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status should be error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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="nx"&gt;mockAxios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onGet&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replyOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&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;result&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;useCatFact&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TestWrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// refetching the query&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;waitFor&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Notice that this file imports &lt;code&gt;TestWrapper&lt;/code&gt; from &lt;code&gt;@nx-expo-monorepo/queries/test-wrapper&lt;/code&gt;, and it is added to &lt;code&gt;renderHook&lt;/code&gt; function with &lt;code&gt;{ wrapper: TestWrapper }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now you run the test command &lt;code&gt;nx test queries-use-cat-fact&lt;/code&gt;, it should pass:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; PASS   queries-use-cat-fact  libs/queries/use-cat-fact/src/lib/use-cat-fact.spec.ts (5.158 s)  
  useCatFact  
    ✓ status should be success (44 ms)  
    ✓ status should be error (96 ms)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Integrate with Component
&lt;/h3&gt;

&lt;p&gt;Currently &lt;code&gt;userQuery&lt;/code&gt; returns the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;isLoading&lt;/code&gt; or &lt;code&gt;status === 'loading'&lt;/code&gt; - The query has no data yet&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;isError&lt;/code&gt; or &lt;code&gt;status === 'error'&lt;/code&gt; - The query encountered an error&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;isSuccess&lt;/code&gt; or &lt;code&gt;status === 'success'&lt;/code&gt; - The query was successful and data is available&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now with components controlled by the server state, you can leverage the above properties and change your component to follow the below pattern:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CarouselProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nl"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  


&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Carousel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
  &lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;CarouselProps&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;&amp;gt;&lt;/span&gt;  
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isSuccess&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;isLoading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;isError&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt; &lt;/span&gt;&lt;span class="err"&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Carousel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then in the parent component, you can use the query created above:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;useCatFact&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nx-expo-monorepo/queries/use-cat-fact&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;Carousel&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nx-expo-monorepo/ui&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;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Facts&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isFetching&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  
    &lt;span class="nf"&gt;useCatFact&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;Carousel&lt;/span&gt;  
      &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
      &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;isFetching&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
      &lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
      &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
      &lt;span class="nx"&gt;onReload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;refetch&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;);&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you serve the app on the web and open the &lt;a href="https://tanstack.com/query/v4/docs/react/devtools"&gt;React Query Devtools&lt;/a&gt;, you should be able to see the query I created &lt;code&gt;cat-fact&lt;/code&gt; and data in the query.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qb917ouQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2AvGUQ_wHNfm2zqln-z0NE-Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qb917ouQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2AvGUQ_wHNfm2zqln-z0NE-Q.png" alt="React Query Devtools" width="800" height="860"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Redux
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Create a Library
&lt;/h3&gt;

&lt;p&gt;First, you need to create a library for redux:&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 library  &lt;/span&gt;
npx nx generate @nx/expo:lib &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;states  

&lt;span class="c"&gt;# react native library  &lt;/span&gt;
npx nx generate @nx/react-native:lib &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;states
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This should create a folder under libs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9RDzr7K4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2Ae5jaFK8syLNF1ndMFcEmPw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9RDzr7K4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2Ae5jaFK8syLNF1ndMFcEmPw.png" alt="cat folder under libs/states" width="416" height="736"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a State
&lt;/h3&gt;

&lt;p&gt;This app is going to track when users click the like button, so you need to create a state called &lt;code&gt;likes&lt;/code&gt;.&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%2Fuploads%2Farticles%2Fk5vfoiwekprk0m9no8zb.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%2Fuploads%2Farticles%2Fk5vfoiwekprk0m9no8zb.png" alt="Cats like button" width="800" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use the &lt;a href="https://nx.dev/recipes/nx-console"&gt;Nx Console&lt;/a&gt; to create a redux slice:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kNKTidIJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2AdJ5O8O4Eetpig6pu7lerGA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kNKTidIJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2AdJ5O8O4Eetpig6pu7lerGA.png" alt="nx console slice" width="800" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or run this command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nx generate @nx/react:redux likes &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;states-cat &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;likes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then update the redux slice at &lt;code&gt;libs/states/cat/src/lib/likes/likes.slice.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;createEntityAdapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;createSelector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nx"&gt;EntityState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LIKES&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_FEATURE&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;likes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;LikesEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;dateAdded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;LikesState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;EntityState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LikesEntity&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likesAdapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createEntityAdapter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LikesEntity&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialLikesState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LikesState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;likesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInitialState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likesSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LIKES&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_FEATURE&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialLikesState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;like&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;likesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;likesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;likesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeAll&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="se"&gt;\*&lt;/span&gt;&lt;span class="sr"&gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;Export&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="nx"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;  
 &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="sr"&gt;/ &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likesReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;likesSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likesActions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;likesSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&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;selectAll&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;likesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSelectors&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;getlikesState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ROOT&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LikesState&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;rootState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ROOT&lt;/span&gt;  
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;LikesState&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;rootState&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;LIKES&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_FEATURE&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_KEY&lt;/span&gt;&lt;span class="err"&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;selectAllLikes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getlikesState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selectAll&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likesSelectors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;selectAllLikes&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;Every time the “like” button gets clicked, you want to store the content of what users liked. So you need to create an entity to store this information.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;LikesEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;dateAdded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;This state has 3 actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  like: when users click like&lt;/li&gt;
&lt;li&gt;  remove: when users cancel the like&lt;/li&gt;
&lt;li&gt;  clear: when users clear all the likes&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Root Store
&lt;/h3&gt;

&lt;p&gt;Then you have to add the root store and create a transform function to stringify the redux state:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Connect Redux State with UI
&lt;/h3&gt;

&lt;p&gt;Then in &lt;code&gt;apps/cats/src/app/App.tsx&lt;/code&gt;, you have to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  wrap the app inside the &lt;code&gt;StoreProvider&lt;/code&gt; with the root store to connect with the Redux state.&lt;/li&gt;
&lt;li&gt;  wrap the app inside &lt;code&gt;PersistGate&lt;/code&gt; to persist the redux state in the storage
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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="s1"&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="nx"&gt;AsyncStorage&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-native-async-storage/async-storage&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;PersistGate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux-persist/integration/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;createRootStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;transformEntityStateToPersist&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nx-expo-monorepo/states/cat&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;Loading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nx-expo-monorepo/ui&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;Provider&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;StoreProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&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;App&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;persistConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AsyncStorage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;transforms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;transformEntityStateToPersist&lt;/span&gt;&lt;span class="err"&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;persistor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRootStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;persistConfig&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;PersistGate&lt;/span&gt; &lt;span class="nx"&gt;loading&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;Loading&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;persistor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;persistor&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;StoreProvider&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
        &lt;span class="p"&gt;...&lt;/span&gt;  
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/StoreProvider&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/PersistGate&amp;gt; &lt;/span&gt;&lt;span class="err"&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your component where the like button is located, you need to dispatch the like action. I created a file at &lt;code&gt;apps/cats/src/app/facts/facts.props.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;likesActions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LikesEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;RootState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nx-expo-monorepo/states/cat&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;AnyAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ThunkDispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@reduxjs/toolkit&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;mapDispatchToProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;  
  &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ThunkDispatch&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RootState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AnyAction&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;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="nf"&gt;like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LikesEntity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;likesActions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;like&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="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;type&lt;/span&gt; &lt;span class="nx"&gt;mapDispatchToPropsType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;mapDispatchToProps&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;type&lt;/span&gt; &lt;span class="nx"&gt;FactsProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mapDispatchToPropsType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mapDispatchToProps&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;  
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FactsProps&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have passed the &lt;code&gt;like&lt;/code&gt; function to the props of the facts component. Now inside the facts component, you can call the like function from props to dispatch the like action.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging
&lt;/h3&gt;

&lt;p&gt;To debug redux with Expo, I can simply open the Debugger Menu by entering “d” in the console or in the app, then choose the option “Open JS Debugger”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hWALlr87--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2Akp09e4iConN0-NF-LkMj7A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hWALlr87--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/1%2Akp09e4iConN0-NF-LkMj7A.png" alt="JS Debugger" width="800" height="1734"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then you can view my redux logs in the JS Debugger console:&lt;/p&gt;

&lt;p&gt;You can see the redux logs in console now:&lt;br&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%2Fuploads%2Farticles%2Fgq3pymwkk0z11naeh186.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%2Fuploads%2Farticles%2Fgq3pymwkk0z11naeh186.png" alt="Redux Logs" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or you can run &lt;code&gt;nx serve cats&lt;/code&gt; to launch the app in web view. Then you can use Redux Devtools and debug the native app like a web app:&lt;br&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%2Fuploads%2Farticles%2Fjimbmg65n32lgwsvikwm.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%2Fuploads%2Farticles%2Fjimbmg65n32lgwsvikwm.png" alt="Redux Devtools" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Here is a simple app that uses TanStack Query and Redux for state management. These 2 tools are pretty powerful and they manage both server and client state for you, which is easy to scale, test, and debug.&lt;/p&gt;

&lt;p&gt;Nx is a powerful monorepo tool. Together with Nx and these 2 state management tools, it will be very easy to scale up any app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  TanStack Query site: &lt;a href="https://tanstack.com/query/latest"&gt;https://tanstack.com/query/latest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Official @nx/expo plugin: &lt;a href="https://nx.dev/packages/expo"&gt;https://nx.dev/packages/expo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Official @nx/react-native plugin: &lt;a href="https://nx.dev/packages/react-native"&gt;https://nx.dev/packages/react-native&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  🧠 &lt;a href="https://nx.dev/"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  👩‍💻 &lt;a href="https://github.com/nrwl/nx"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  💬 &lt;a href="https://go.nrwl.io/community"&gt;Nx Community Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  📹 &lt;a href="https://www.youtube.com/@nxdevtools"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  🚀 &lt;a href="https://nx.app/"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tanstack</category>
      <category>reactnative</category>
      <category>expo</category>
      <category>redux</category>
    </item>
    <item>
      <title>Step-by-Step Guide to Creating an Expo Monorepo with Nx</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Fri, 16 Feb 2024 22:19:07 +0000</pubDate>
      <link>https://forem.com/nx/step-by-step-guide-to-creating-an-expo-monorepo-with-nx-3b17</link>
      <guid>https://forem.com/nx/step-by-step-guide-to-creating-an-expo-monorepo-with-nx-3b17</guid>
      <description>&lt;p&gt;This blog will show you how to create an Expo monorepo with Nx. In this example, you will be creating two Expo apps in a monorepo with @nx/expo: one shows random facts about cats, and the other shows random facts about dogs.&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%2Fonnb7oaebj8bjdm7hhnz.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%2Fonnb7oaebj8bjdm7hhnz.png" alt="Cats App Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fij4elkatpvxomkm81530.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%2Fij4elkatpvxomkm81530.png" alt="Dogs App Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As shown in the above screenshots, these two apps have the same branding and reuse all components.&lt;/p&gt;

&lt;p&gt;This blog will go through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to create a monorepo workspace with Nx&lt;/li&gt;
&lt;li&gt;How to share a React Native library&lt;/li&gt;
&lt;li&gt;How to build an Expo app&lt;/li&gt;
&lt;li&gt;How to submit an Expo app to the app store&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Github repo: &lt;a href="https://github.com/xiongemi/nx-expo-monorepo" rel="noopener noreferrer"&gt;https://github.com/xiongemi/nx-expo-monorepo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating an Nx Workspace
&lt;/h2&gt;

&lt;p&gt;To create a new Nx workspace, run the command npx create-nx-workspace  in the terminal. In this example, let’s name it nx-expo-monorepo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✔ Where would you like to create your workspace? · create-nx-monorepo
✔ Which stack do you want to use? · react
✔ What framework would you like to use? · expo
✔ Application name · cats
✔ Enable distributed caching to make your CI faster · No
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will create an &lt;a href="https://nx.dev/concepts/integrated-vs-package-based#integrated-repos" rel="noopener noreferrer"&gt;integrated repo&lt;/a&gt;. What is an integrated repo?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An integrated repo contains projects that depend on each other through standard import statements. There is typically a single version of every dependency defined at the root.&lt;br&gt;
&lt;a href="https://nx.dev/concepts/integrated-vs-package-based#integrated-repos" rel="noopener noreferrer"&gt;https://nx.dev/concepts/integrated-vs-package-based#integrated-repos&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, your Nx workspace should have cats and cats-e2e under the apps folder and an empty libs folder:&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%2Frt234mh8n0kn9m16pb62.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%2Frt234mh8n0kn9m16pb62.png" alt="Nx workspace with cats app"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Existing Nx Workspace
&lt;/h3&gt;

&lt;p&gt;If you already have an Nx workspace, you need to install the @nx/expo package:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx add @nx/expo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To create an Expo app, run:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx generate @nx/expo:app cats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Alternatively, if you use Visual Studio Code as your code editor, you can also create apps using &lt;a href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console" rel="noopener noreferrer"&gt;Nx Console&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Filktnkv9awxe5drqpj7b.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%2Filktnkv9awxe5drqpj7b.png" alt="nx console"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Install Tech Stacks
&lt;/h2&gt;

&lt;p&gt;Here are the tech stacks this example is going to use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Material design library: &lt;a href="https://callstack.github.io/react-native-paper/" rel="noopener noreferrer"&gt;react-native-paper&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# npm  
npm install react-native-paper react-native-safe-area-context --save  

# yarn  
yarn add react-native-paper react-native-safe-area-context  

# pnpm  
pnpm add react-native-paper react-native-safe-area-context --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;  Routing: &lt;a href="https://reactnavigation.org/" rel="noopener noreferrer"&gt;@react-navigation/native&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# npm  
npm install react-native-paper react-native-screens @react-navigation/native-stack --save  

# yarn  
yarn add react-native-paper react-native-screens @react-navigation/native-stack  

# pnpm  
pnpm add react-native-paper react-native-screens @react-navigation/native-stack --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Create a Shareable UI Library
&lt;/h2&gt;

&lt;p&gt;With all the required libraries installed, you need to create a sharable UI library:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx generate @nx/expo:lib ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now under the &lt;code&gt;libs&lt;/code&gt; folder, a &lt;code&gt;ui&lt;/code&gt; folder has been created:&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%2Fspgvugsru2q1hbvhghfw.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%2Fspgvugsru2q1hbvhghfw.png" alt="ui folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To create a component in the &lt;code&gt;ui&lt;/code&gt; library, run:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx generate @nx/expo:component carousel --project=ui --export
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can see that a &lt;code&gt;carousel&lt;/code&gt; folder has been created in the &lt;code&gt;libs/ui/src/lib&lt;/code&gt; folder:&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%2Fwyzjj5bxrv0jd0g1wi1l.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%2Fwyzjj5bxrv0jd0g1wi1l.png" alt="carousel folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, modify this component to display the content with props passed in:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Now you can use this component in your app directly using an import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Carousel } from '@nx-expo-monorepo/ui';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Add Navigation
&lt;/h2&gt;

&lt;p&gt;This project is going to use the &lt;a href="https://reactnavigation.org/docs/stack-navigator" rel="noopener noreferrer"&gt;stack navigator&lt;/a&gt; from &lt;a href="https://reactnavigation.org/" rel="noopener noreferrer"&gt;@react-navigation/native&lt;/a&gt;. So the app needs to import from @react-navigation/stack. In &lt;code&gt;apps/cats/src/app/App.tsx&lt;/code&gt;, you can change the UI to have one screen displaying a carousel with mock data:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Run the app with &lt;code&gt;nx start cats&lt;/code&gt;, and you should be able to see the app on the simulator:&lt;/p&gt;

&lt;p&gt;Page on the simulator (left: iOS, right: Android)&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%2Fhrqhgf7lh5uf684gaqzj.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%2Fhrqhgf7lh5uf684gaqzj.png" alt="Cats app screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Add Another App
&lt;/h2&gt;

&lt;p&gt;In this example, there is already a &lt;code&gt;Cats&lt;/code&gt; app. To create the &lt;code&gt;Dogs&lt;/code&gt; app, run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx generate @nx/expo:app dogs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Alternatively, if you use Visual Studio Code as your code editor, you can also create apps using &lt;a href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console" rel="noopener noreferrer"&gt;Nx Console&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2A8ut9KSAOn-UBBNxHJMtVXQ.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%2Fmiro.medium.com%2Fv2%2F1%2A8ut9KSAOn-UBBNxHJMtVXQ.png" alt="nx console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under the apps folder, there should be &lt;code&gt;cats/&lt;/code&gt;, &lt;code&gt;dogs/&lt;/code&gt; and their e2es.&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%2Fzxtra7hkk76srplz2ne3.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%2Fzxtra7hkk76srplz2ne3.png" alt="apps folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can reuse the UI library in the Dogs app in &lt;code&gt;apps/dogs/src/app/App.tsx&lt;/code&gt; with the below code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  Build Expo Apps
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.expo.dev/build/introduction/" rel="noopener noreferrer"&gt;EAS Build&lt;/a&gt; is a hosted service for building app binaries for your Expo and React Native projects. To set up EAS locally:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install EAS CLI
&lt;/h3&gt;

&lt;p&gt;EAS CLI is the command-line app to interact with EAS services in the terminal. To install it, run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g eas-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Login To EAS
&lt;/h3&gt;

&lt;p&gt;If you are not logged in, run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eas login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Build the Apps
&lt;/h3&gt;

&lt;p&gt;After the EAS setup, you can build apps by running the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx build cats  
npx nx build dogs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are different options you can specify with the build command. For example, you can specify the platform you want to build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx build cats --platform=all  
npx nx build cats --platform=android  
npx nx build cats --platform=ios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, if you want to create a build to run on a simulator/emulator, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx build cats --profile=preview
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can view your build status at &lt;a href="https://expo.dev/" rel="noopener noreferrer"&gt;https://expo.dev/&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2F1%2ApQxTgypzL10_SmI71jaWVQ.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%2Fmiro.medium.com%2Fv2%2F1%2ApQxTgypzL10_SmI71jaWVQ.png" alt="expo.dev"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to create a build locally using your own infrastructure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx build cats --local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the complete list of flags for the build command: &lt;a href="https://nx.dev/packages/expo/executors/build" rel="noopener noreferrer"&gt;https://nx.dev/packages/expo/executors/build&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submit to the App Store
&lt;/h3&gt;

&lt;p&gt;Before you submit, you need to have paid developer accounts for iOS and Android.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  iOS: You need to create an Apple Developer account on the Apple &lt;a href="https://developer.apple.com/account/" rel="noopener noreferrer"&gt;Developer Portal&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  Android: You need to create a Google Play Developer account on the &lt;a href="https://play.google.com/apps/publish/signup/" rel="noopener noreferrer"&gt;Google Play Console sign-up page&lt;/a&gt;. You also need to manually create an app on &lt;a href="https://play.google.com/apps/publish/" rel="noopener noreferrer"&gt;Google Play Console&lt;/a&gt; and upload your app for the first time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1. Run the production build
&lt;/h3&gt;

&lt;p&gt;To submit to the app store, you can build the app by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx build cats --profile=production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Submit the Build
&lt;/h3&gt;

&lt;p&gt;You can manually upload the build bundle binary to the app store, or you can submit it through EAS.&lt;/p&gt;

&lt;p&gt;First, in &lt;code&gt;app.json&lt;/code&gt; under the project &lt;code&gt;apps/cats/app.json&lt;/code&gt;, you need to make sure&lt;code&gt;ios.bundleIdentifier&lt;/code&gt; and &lt;code&gt;android.package&lt;/code&gt; keys are correct:&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%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A1400%2Fformat%3Awebp%2F1%2Aj9TAZZgqplZCcjD4hiWNpg.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%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A1400%2Fformat%3Awebp%2F1%2Aj9TAZZgqplZCcjD4hiWNpg.png" alt="app.json"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To submit your app to the app stores, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx submit cats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nx will prompt you to choose the platform to which you want to submit:&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%2Fmiro.medium.com%2Fv2%2F1%2APcBvY1SJCHZyOnJI1hskAQ.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%2Fmiro.medium.com%2Fv2%2F1%2APcBvY1SJCHZyOnJI1hskAQ.png" alt="submit prompt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or you can also specify the platform directly in the initial command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx submit cats --platform=all  
npx nx submit cats --platform=android  
npx nx submit cats --platform=ios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will then ask you to choose which binary to submit from one of the following options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The latest finished Android build for the project on EAS servers.&lt;/li&gt;
&lt;li&gt;  Specific build ID. It can be found on the &lt;a href="https://expo.dev/builds" rel="noopener noreferrer"&gt;builds dashboard&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  Path to an .apk or .aab or .ipa archive on your local filesystem.&lt;/li&gt;
&lt;li&gt;  URL to the app archive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alternatively, you can submit your app on the &lt;a href="https://expo.dev/" rel="noopener noreferrer"&gt;expo.dev&lt;/a&gt; site. Go to your build, under options, choose “Submit to an app store”:&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%2Fmiro.medium.com%2Fv2%2F1%2AyQlEmKOy3TXdWPCk9ILiZA.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%2Fmiro.medium.com%2Fv2%2F1%2AyQlEmKOy3TXdWPCk9ILiZA.png" alt="submit to an app store"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this article, you have learned how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create multiple apps in a monorepo using @nx/expo&lt;/li&gt;
&lt;li&gt;  Create a shared library&lt;/li&gt;
&lt;li&gt;  Build your app using EAS&lt;/li&gt;
&lt;li&gt;  Submit your app to the App Store&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Nx, it is easy to create and scale up an Expo app. Even though this app is currently a simple 2-page app, you can easily scale it up with more libraries and components. Furthermore, you can also reuse those libraries in the future if you decide to add another app to the repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://medium.com/unit-testing-expo-apps-with-jest-22a0309aa7bb" rel="noopener noreferrer"&gt;Unit Testing Expo Apps With Jest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://medium.com/@emilyxiong/add-cypress-playwright-and-storybook-to-nx-expo-apps-1d3e409ce834" rel="noopener noreferrer"&gt;Add Cypress, Playwright, and Storybook to Nx Expo Apps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  🧠 &lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  👩‍💻 &lt;a href="https://github.com/nrwl/nx" rel="noopener noreferrer"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  💬 &lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;Nx Community Slack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  📹 &lt;a href="https://www.youtube.com/@nxdevtools" rel="noopener noreferrer"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  🚀 &lt;a href="https://nx.app/" rel="noopener noreferrer"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>monorepo</category>
      <category>expo</category>
      <category>nx</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>Using react-native-web with Webpack in a Nx monorepo</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Mon, 27 Nov 2023 06:12:36 +0000</pubDate>
      <link>https://forem.com/xiongemi/using-react-native-web-with-webpack-in-a-nx-monorepo-429a</link>
      <guid>https://forem.com/xiongemi/using-react-native-web-with-webpack-in-a-nx-monorepo-429a</guid>
      <description>&lt;p&gt;This blog shows how to add a web app using &lt;a href="https://necolas.github.io/react-native-web/" rel="noopener noreferrer"&gt;react-native-web&lt;/a&gt; with Webpack as the bundler in a Nx monorepo.&lt;/p&gt;

&lt;p&gt;Github Repo: &lt;a href="https://github.com/xiongemi/nx-react-native-monorepo-jokes" rel="noopener noreferrer"&gt;https://github.com/xiongemi/nx-react-native-monorepo-jokes&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;First, I need to install &lt;code&gt;react-native-web&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# npm
npm install react-native-web --save-dev

# yarn
yarn add react-native-web --dev

# pnpm
pnpm add react-native-web --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Add a React App in the Nx Monorepo
&lt;/h2&gt;

&lt;p&gt;Run command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx g @nx/react:app &amp;lt;web app name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the terminal output, select webpack as bundler:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;  NX  Generating @nx/react:application

✔ Which stylesheet format would you like to use? · none
✔ Would you like to add React Router to this application? (y/N) · false
✔ Which E2E test runner would you like to use? · none
✔ Which bundler do you want to use to build the application? · webpack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Import the Native App
&lt;/h2&gt;

&lt;p&gt;In the web app, in &lt;code&gt;apps/&amp;lt;web app name&amp;gt;/src/main.tsx&lt;/code&gt;, change the import of App to:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// eslint-disable-next-line @nx/enforce-module-boundaries
import App from '../../&amp;lt;native app name&amp;gt;/src/app/App';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Also, in web app's &lt;code&gt;project.json&lt;/code&gt;, add &lt;code&gt;implicitDependencies&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "implicitDependencies": ["&amp;lt;native app name&amp;gt;"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Add Alias in webpack.config.ts
&lt;/h2&gt;

&lt;p&gt;In apps/techy-jokes-webpack/webpack.config.ts, add below alias:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  config.resolve.alias = {
    ...config.resolve?.alias ?? {},
    'react-native$': 'react-native-web',
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Change index.html to be full height
&lt;/h2&gt;

&lt;p&gt;In the index.html, change the:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;style="height: 100%"&lt;/code&gt; to html tag&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;style="min-height: 100%"&lt;/code&gt; to body tag&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;style="display: flex; min-height: 100vh"&lt;/code&gt; to div with root id&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These style changes are taken from examples in &lt;a href="https://reactnavigation.org/docs/server-rendering" rel="noopener noreferrer"&gt;https://reactnavigation.org/docs/server-rendering&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So the index.html would look like:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en" style="height: 100%"&amp;gt;
  &amp;lt;head&amp;gt;
    ...
  &amp;lt;/head&amp;gt;
  &amp;lt;body style="min-height: 100%"&amp;gt;
    &amp;lt;div id="root" style="display: flex; min-height: 100vh"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;script type="module" src="/src/main.tsx"&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then that is it, I can now view the web app using &lt;code&gt;npx nx serve &amp;lt;web app name&amp;gt;&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  react-native-vector-icons
&lt;/h3&gt;

&lt;p&gt;Because I use &lt;a href="https://github.com/oblador/react-native-vector-icons/" rel="noopener noreferrer"&gt;react-native-vector-icons&lt;/a&gt;, I got this error:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR in ../../node_modules/react-native-vector-icons/lib/create-icon-set.js 70:8
Module parse failed: Unexpected token (70:8)
File was processed with these loaders:
 * ../../node_modules/source-map-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
| 
|       return (
&amp;gt;         &amp;lt;Text selectable={false} {...props}&amp;gt;
|           {glyph}
|           {children}

webpack compiled with 1 error (af4bf9f7c72b44dc)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This happens because &lt;code&gt;react-native-vector-icons&lt;/code&gt; contains jsx code (e.g. &lt;code&gt;&amp;lt;Text&amp;gt;&lt;/code&gt;) inside &lt;code&gt;.js&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;First, I need to add files with &lt;code&gt;.web&lt;/code&gt; to the extensions (the order of the extension in the array actually matters):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  config.resolve.extensions = [
    '.web.tsx',
    '.web.ts',
    '.web.jsx',
    '.web.js',
    ...config.resolve.extensions,
  ];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then I need to add a rule to load the &lt;code&gt;.js&lt;/code&gt; file from &lt;code&gt;react-native-vector-icons&lt;/code&gt; using babel loader (&lt;a href="https://stackoverflow.com/questions/56750269/react-native-web-failed-to-compile-react-native-vector-icons):" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/56750269/react-native-web-failed-to-compile-react-native-vector-icons):&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  config.module.rules.push({
    test: /\.(js|jsx)$/,
    include: /react-native-vector-icons/,
    loader: 'babel-loader',
    options: {
      presets: [
        '@babel/preset-env',
        ['@babel/preset-react', { runtime: 'automatic' }],
      ],
    },
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When I serve up the web app, I will get this error message:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MaterialCommunityIcon.tsx:49 Error: Dynamic require of "react-native-vector-icons/MaterialCommunityIcons" is not supported
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I copy the font file from react-native-vector-icons library to the src/assets folder: &lt;a href="https://github.com/oblador/react-native-vector-icons/tree/master/Fonts" rel="noopener noreferrer"&gt;https://github.com/oblador/react-native-vector-icons/tree/master/Fonts&lt;/a&gt;.&lt;br&gt;
So in my web app's index.html, I need to add:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;style type="text/css"&amp;gt;
      @font-face {
        font-family: 'MaterialCommunityIcons';
        src: url('/assets/MaterialCommunityIcons.ttf') format('truetype');
      }
    &amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now build command (&lt;code&gt;nx build &amp;lt;web app name&amp;gt;&lt;/code&gt;) should work.&lt;/p&gt;




&lt;p&gt;The final &lt;code&gt;webpack.config.js&lt;/code&gt; would look like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { composePlugins, withNx } = require('@nx/webpack');
const { withReact } = require('@nx/react');

// Nx plugins for webpack.
module.exports = composePlugins(withNx(), withReact(), (config) =&amp;gt; {
  // Update the webpack config as needed here.
  // e.g. `config.plugins.push(new MyPlugin())`
  config.resolve.alias = {
    ...config.resolve?.alias ?? {},
    'react-native$': 'react-native-web',
  };
  config.resolve.extensions = [
    '.web.tsx',
    '.web.ts',
    '.web.jsx',
    '.web.js',
    ...config.resolve.extensions,
  ];
  config.module.rules.push({
    test: /\.(js|jsx)$/,
    include: /react-native-vector-icons/,
    loader: 'babel-loader',
    options: {
      presets: [
        '@babel/preset-env',
        ['@babel/preset-react', { runtime: 'automatic' }],
      ],
    },
  });
  return config;
});

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

&lt;/div&gt;




&lt;h2&gt;
  
  
  Deploy to GitHub Pages
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pages.github.com/" rel="noopener noreferrer"&gt;GitHub Pages&lt;/a&gt; is designed to host your personal, organization, or project pages from a GitHub repository.&lt;/p&gt;

&lt;p&gt;To deploy this web app to GitHub page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;a href="https://github.com/tschaub/gh-pages" rel="noopener noreferrer"&gt;&lt;code&gt;gh-pages&lt;/code&gt;&lt;/a&gt;
```
# npm
npm install gh-pages --save-dev&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  yarn
&lt;/h1&gt;

&lt;p&gt;yarn add gh-pages --dev&lt;/p&gt;

&lt;h1&gt;
  
  
  pnpm
&lt;/h1&gt;

&lt;p&gt;pnpm add gh-pages --save-dev&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
- Create a script called `gh-pages.js` under the app:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;var ghpages = require('gh-pages');&lt;/p&gt;

&lt;p&gt;ghpages.publish('', function (err) {&lt;br&gt;
  if (!err) {&lt;br&gt;
    console.error(err);&lt;br&gt;
  }&lt;br&gt;
});&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
For this example, the `gh-pages.js` look like:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;var ghpages = require('gh-pages');&lt;/p&gt;

&lt;p&gt;ghpages.publish('../../dist/apps/techy-jokes-webpack', function (err) {&lt;br&gt;
  if (!err) {&lt;br&gt;
    console.error(err);&lt;br&gt;
  }&lt;br&gt;
});&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
- If your GitHub has a base href, run the build command with `--baseHref`. For example, my GitHub page is at https://xiongemi.github.io/nx-react-native-monorepo-jokes/, to build for it, the command is `nx build techy-jokes-webpack --baseHref=/nx-react-native-monorepo-jokes/`.

- Add a target in project.json:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"gh-pages": {
  "command": "npx nx build &amp;lt;app name&amp;gt; --base=&amp;lt;app base href&amp;gt; --prod &amp;amp;&amp;amp; node gh-pages.js",
  "cwd": "{projectRoot}"
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
For this example, the target would be:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"gh-pages": {
  "command": "npx nx build techy-jokes-webpack --prod --baseHref=/nx-react-native-monorepo-jokes &amp;amp;&amp;amp; node gh-pages.js",
  "cwd": "{projectRoot}"
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Now you can run the command `nx gh-pages &amp;lt;your app name&amp;gt;` to deploy your app to GitHub Pages.

---
## Nx Graph

If you run command `nx graph`, you should see the web app implict depends on the react native mobile app:


![nx dependency graph](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tcdbru3zwq12aaech5wn.png)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>nx</category>
      <category>reactnativeweb</category>
      <category>reactnative</category>
      <category>webpack</category>
    </item>
    <item>
      <title>Using react-native-web with Vite in a Nx monorepo</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Wed, 11 Oct 2023 04:34:47 +0000</pubDate>
      <link>https://forem.com/xiongemi/using-react-native-web-with-vite-4in8</link>
      <guid>https://forem.com/xiongemi/using-react-native-web-with-vite-4in8</guid>
      <description>&lt;p&gt;This blog shows how to add a web app using react-native-web with vite as the bundler in a Nx monorepo.&lt;/p&gt;

&lt;p&gt;Github Repo: &lt;a href="https://github.com/xiongemi/nx-react-native-monorepo-jokes" rel="noopener noreferrer"&gt;https://github.com/xiongemi/nx-react-native-monorepo-jokes&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;First, I need to install &lt;code&gt;react-native-web&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# npm
npm install react-native-web --save-dev

# yarn
yarn add react-native-web --dev

# pnpm
pnpm add react-native-web --save-dev


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Add a React App in the Nx Monorepo
&lt;/h2&gt;

&lt;p&gt;Run command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx nx g @nx/react:app &amp;lt;web app name&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;In the terminal output, select vite as bundler:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;gt;  NX  Generating @nx/react:application

✔ Which stylesheet format would you like to use? · none
✔ Would you like to add React Router to this application? (y/N) · false
✔ Which E2E test runner would you like to use? · none
✔ Which bundler do you want to use to build the application? · vite


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Import the Native App
&lt;/h2&gt;

&lt;p&gt;In the web app, in &lt;code&gt;apps/&amp;lt;web app name&amp;gt;/src/main.tsx&lt;/code&gt;, change the import of App to:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// eslint-disable-next-line @nx/enforce-module-boundaries
import App from '../../&amp;lt;native app name&amp;gt;/src/app/App';


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

&lt;/div&gt;

&lt;p&gt;Also, in web app's &lt;code&gt;project.json&lt;/code&gt;, add &lt;code&gt;implicitDependencies&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  "implicitDependencies": ["&amp;lt;native app name&amp;gt;"]


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Add Alias in vite.config.ts
&lt;/h2&gt;

&lt;p&gt;In apps/techy-jokes-vite/vite.config.ts, add below alias:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  resolve: {
    alias: {
      'react-native': 'react-native-web',
    },
  },


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

&lt;/div&gt;

&lt;p&gt;Then that is it, I can now view the web app using &lt;code&gt;npx nx serve &amp;lt;web app name&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Change index.html to be full height
&lt;/h2&gt;

&lt;p&gt;In the index.html, change the:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;style="height: 100%"&lt;/code&gt; to html tag&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;style="min-height: 100%"&lt;/code&gt; to body tag&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;style="display: flex; min-height: 100vh"&lt;/code&gt; to div with root id&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These style changes are taken from examples in &lt;a href="https://reactnavigation.org/docs/server-rendering" rel="noopener noreferrer"&gt;https://reactnavigation.org/docs/server-rendering&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So the index.html would look like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en" style="height: 100%"&amp;gt;
  &amp;lt;head&amp;gt;
    ...
  &amp;lt;/head&amp;gt;
  &amp;lt;body style="min-height: 100%"&amp;gt;
    &amp;lt;div id="root" style="display: flex; min-height: 100vh"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;script type="module" src="/src/main.tsx"&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;


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

&lt;/div&gt;




&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  react-native-vector-icons
&lt;/h3&gt;

&lt;p&gt;Because I use &lt;a href="https://github.com/oblador/react-native-vector-icons/" rel="noopener noreferrer"&gt;react-native-vector-icons&lt;/a&gt;, I got this error:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

[commonjs--resolver] Unexpected token (70:8) in /Users/emily/code/tmp/nx-react-native-monorepo-jokes/node_modules/react-native-vector-icons/lib/create-icon-set.js
file: /Users/emily/code/tmp/nx-react-native-monorepo-jokes/node_modules/react-native-vector-icons/lib/create-icon-set.js:70:8
68: 
69:       return (
70:         &amp;lt;Text selectable={false} {...props}&amp;gt;
            ^
71:           {glyph}
72:           {children}

 &amp;gt;  NX   Unexpected token (70:8) in /Users/emily/code/tmp/nx-react-native-monorepo-jokes/node_modules/react-native-vector-icons/lib/create-icon-set.js


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

&lt;/div&gt;

&lt;p&gt;This happens because &lt;code&gt;react-native-vector-icons&lt;/code&gt; contains jsx code (e.g. &lt;code&gt;&amp;lt;Text&amp;gt;&lt;/code&gt;) inside &lt;code&gt;.js&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;First, I need to add files with &lt;code&gt;.web&lt;/code&gt; to the extensions (the order of the extension in the array actually matters, &lt;code&gt;.web&lt;/code&gt; needs to be loaded first):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

const extensions = [
  '.mjs',
  '.web.tsx',
  '.tsx',
  '.web.ts',
  '.ts',
  '.web.jsx',
  '.jsx',
  '.web.js',
  '.js',
  '.css',
  '.json',
];


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

&lt;/div&gt;

&lt;p&gt;Add these extensions to resolve:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export default defineConfig({
...

  resolve: {
    extensions,
...


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

&lt;/div&gt;

&lt;p&gt;Then inside &lt;code&gt;defineConfig&lt;/code&gt;, I added to optimizeDeps to resolve js files using jsx loader:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  optimizeDeps: {
    esbuildOptions: {
      resolveExtensions: extensions,
      jsx: "automatic",
      loader: { ".js": "jsx" },
    },
  },


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

&lt;/div&gt;

&lt;p&gt;When I serve up the web app, I will get this error message:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

MaterialCommunityIcon.tsx:49 Error: Dynamic require of "react-native-vector-icons/MaterialCommunityIcons" is not supported


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

&lt;/div&gt;

&lt;p&gt;I copy the font file from react-native-vector-icons library to the public folder: &lt;a href="https://github.com/oblador/react-native-vector-icons/tree/master/Fonts" rel="noopener noreferrer"&gt;https://github.com/oblador/react-native-vector-icons/tree/master/Fonts&lt;/a&gt;.&lt;br&gt;
So in my web app's index.html, I need to add:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    &amp;lt;style type="text/css"&amp;gt;
      @font-face {
        font-family: 'MaterialCommunityIcons';
        src: url('/MaterialCommunityIcons.ttf') format('truetype');
      }
    &amp;lt;/style&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;Now the serve command (&lt;code&gt;nx serve &amp;lt;web app name&amp;gt;&lt;/code&gt;) is working. However, the build command (&lt;code&gt;nx run &amp;lt;web app name&amp;gt;&lt;/code&gt;) still does not work with the same error.&lt;/p&gt;

&lt;p&gt;I created a rollup plugin:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

const rollupPlugin = (matchers: RegExp[]) =&amp;gt; ({
  name: 'js-in-jsx',
  load(id: string) {
    if (
      matchers.some((matcher) =&amp;gt; matcher.test(id)) &amp;amp;&amp;amp;
      id.endsWith('.js')
    ) {
      const file = readFileSync(id, { encoding: 'utf-8' });
      return esbuild.transformSync(file, { loader: 'jsx', jsx: 'automatic' });
    }
  },
});


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

&lt;/div&gt;

&lt;p&gt;Then add this plugin to the vite config:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  build: {
    rollupOptions: {
      plugins: [rollupPlugin([/react-native-vector-icons/])],
    },
  },


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

&lt;/div&gt;

&lt;p&gt;Now build command (&lt;code&gt;nx build &amp;lt;web app name&amp;gt;&lt;/code&gt;) should work.&lt;/p&gt;

&lt;h3&gt;
  
  
  global is not defined
&lt;/h3&gt;

&lt;p&gt;In the web browser, I got this error:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

NavigationContainer.tsx:29 Uncaught ReferenceError: global is not defined


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

&lt;/div&gt;

&lt;p&gt;In vite.config.ts, add:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  define: {
    global: "window",
  },


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

&lt;/div&gt;




&lt;p&gt;The final vite.config.ts:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import * as esbuild from 'esbuild';
import { readFileSync } from 'fs';

const extensions = [
  '.mjs',
  '.web.tsx',
  '.tsx',
  '.web.ts',
  '.ts',
  '.web.jsx',
  '.jsx',
  '.web.js',
  '.js',
  '.css',
  '.json',
];

const rollupPlugin = (matchers: RegExp[]) =&amp;gt; ({
  name: 'js-in-jsx',
  load(id: string) {
    if (matchers.some((matcher) =&amp;gt; matcher.test(id)) &amp;amp;&amp;amp; id.endsWith('.js')) {
      const file = readFileSync(id, { encoding: 'utf-8' });
      return esbuild.transformSync(file, { loader: 'jsx', jsx: 'automatic' });
    }
  },
});

export default defineConfig({
  cacheDir: '../../node_modules/.vite/techy-jokes-vite',
  define: {
    global: 'window',
  },

  resolve: {
    extensions,
    alias: {
      'react-native': 'react-native-web',
    },
  },

  build: {
    rollupOptions: {
      plugins: [rollupPlugin([/react-native-vector-icons/])],
    },
  },

  server: {
    port: 4200,
    host: 'localhost',
  },

  preview: {
    port: 4300,
    host: 'localhost',
  },

  optimizeDeps: {
    esbuildOptions: {
      resolveExtensions: extensions,
      jsx: 'automatic',
      loader: { '.js': 'jsx' },
    },
  },

  plugins: [react(), nxViteTsPaths()],

  // Uncomment this if you are using workers.
  // worker: {
  //  plugins: [ nxViteTsPaths() ],
  // },

  test: {
    globals: true,
    cache: { dir: '../../node_modules/.vitest' },
    environment: 'jsdom',
    include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
  },
});


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

&lt;/div&gt;




&lt;h2&gt;
  
  
  Deploy to GitHub Pages
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pages.github.com/" rel="noopener noreferrer"&gt;GitHub Pages&lt;/a&gt; is designed to host your personal, organization, or project pages from a GitHub repository.&lt;/p&gt;

&lt;p&gt;To deploy this web app to GitHub Pages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;install &lt;a href="https://github.com/tschaub/gh-pages" rel="noopener noreferrer"&gt;&lt;code&gt;gh-pages&lt;/code&gt;&lt;/a&gt;:
```
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  npm
&lt;/h1&gt;

&lt;p&gt;npm install gh-pages --save-dev&lt;/p&gt;

&lt;h1&gt;
  
  
  yarn
&lt;/h1&gt;

&lt;p&gt;yarn add gh-pages --dev&lt;/p&gt;

&lt;h1&gt;
  
  
  pnpm
&lt;/h1&gt;

&lt;p&gt;pnpm add gh-pages --save-dev&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
2. Create a script called `gh-pages.js` under the app:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;var ghpages = require('gh-pages');&lt;/p&gt;

&lt;p&gt;ghpages.publish('', function (err) {&lt;br&gt;
  if (!err) {&lt;br&gt;
    console.error(err);&lt;br&gt;
  }&lt;br&gt;
});&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
For this example, the `gh-pages.js` look like:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;var ghpages = require('gh-pages');&lt;/p&gt;

&lt;p&gt;ghpages.publish('../../dist/apps/techy-jokes-vite', function (err) {&lt;br&gt;
  if (!err) {&lt;br&gt;
    console.error(err);&lt;br&gt;
  }&lt;br&gt;
});&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
3. if your GitHub has a base href, run the build command with `--base`. For example, my GitHub page is at https://xiongemi.github.io/nx-react-native-monorepo-jokes/, to build for it, the command is `nx build techy-jokes-vite --base=/nx-react-native-monorepo-jokes/`.

4. Add a target in project.json:

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

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"gh-pages": {
  "command": "nx build techy-jokes-vite --base=/nx-react-native-monorepo-jokes/ &amp;amp;&amp;amp; node gh-pages.js",
  "cwd": "{projectRoot}"
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Now you can run the command `nx gh-pages &amp;lt;your app name&amp;gt;` to deploy your app to GitHub Pages.

---
## Nx Graph

If you run command `nx graph`, you should see the web app implict depends on the react native mobile app:

![nx dependency graph](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zal9dcj1ag55ta6734hh.png)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>reactnative</category>
      <category>reactnativeweb</category>
      <category>vite</category>
      <category>nx</category>
    </item>
    <item>
      <title>Introducing Playwright Support for Nx</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Mon, 18 Sep 2023 16:58:38 +0000</pubDate>
      <link>https://forem.com/nx/introducing-playwright-support-for-nx-43ln</link>
      <guid>https://forem.com/nx/introducing-playwright-support-for-nx-43ln</guid>
      <description>&lt;p&gt;We are very excited to announce our support for Playwright with our new plugin &lt;code&gt;@nx/playwright&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This blog will show you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is Playwright&lt;/li&gt;
&lt;li&gt;How to create a new Nx workspace with Playwright support&lt;/li&gt;
&lt;li&gt;How to add Playwright to an existing Nx workspace&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/k1U3PuBrZFQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Playwright?
&lt;/h2&gt;

&lt;p&gt;Before we start, let’s answer this question: what is Playwright and why should we use it?&lt;/p&gt;

&lt;p&gt;From &lt;a href="//playwright.dev"&gt;playwright.dev&lt;/a&gt;, it says: “Playwright is end-to-end testing for modern web apps”. It sounds good, what does it do for us developers? What developer experience does it provide?&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple Browsers
&lt;/h3&gt;

&lt;p&gt;It is easy to run e2e test suites across multiple browsers. Playwright supports all modern rendering engines including Chromium, WebKit, and Firefox. It also supports branded browsers and mobile viewports. For example, we can simply add the below code to the playwright configuration file to run the same test across these browsers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  projects: [
    /* Test against desktop browsers */
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    /* Test against mobile viewports. */
    {
      name: 'Mobile Chrome',
      use: { ...devices['Pixel 5'] },
    },
    /* Test against branded browsers. */
    {
      name: 'Google Chrome',
      use: { ...devices['Desktop Chrome'], channel: 'chrome' }, // or 'chrome-beta'
    },
  ],
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Auto Waiting
&lt;/h3&gt;

&lt;p&gt;Playwright automatically waits for the relevant checks to pass, then performs the request action. What does it mean? For example, let's say we have a sign-up form where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;while the app checks that the user name is unique, the submit button is disabled.&lt;/li&gt;
&lt;li&gt;after checking with the server, the submit button becomes enabled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How do we write tests in the Playwright? Playwright performs a range of actionability checks on the elements before making actions to ensure these actions behave as expected. So we don't need to wait for the button to be enabled. Playwright will check it. We can simply write:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await page.getByTestId('submit-button').click();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  HTML Test Report
&lt;/h3&gt;

&lt;p&gt;Playwright creates a nice HTML test report that allows filtering tests by browsers, passed tests, failed tests, skipped tests, and flaky tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Iz3Jx60---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3nuhtgocxl64gnec52q1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Iz3Jx60---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3nuhtgocxl64gnec52q1.png" alt="HTML Test Report" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking on the individual test shows more detailed errors along with each step of the test:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--engHd9mZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9tkmznjvcgjif6jaj2gp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--engHd9mZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9tkmznjvcgjif6jaj2gp.png" alt="Individual Test Error" width="800" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also has other features like recording &lt;a href="https://playwright.dev/docs/screenshots"&gt;screenshots&lt;/a&gt; and &lt;a href="https://playwright.dev/docs/videos"&gt;videos&lt;/a&gt;, &lt;a href="https://playwright.dev/docs/codegen"&gt;test generation&lt;/a&gt;, and &lt;a href="https://playwright.dev/docs/test-snapshots"&gt;visual comparisons&lt;/a&gt;. Read more about Playwright at &lt;a href="https://playwright.dev"&gt;playwright.dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next, let’s write and run some Playwright tests.&lt;/p&gt;


&lt;h2&gt;
  
  
  Create a new Nx Workspace with Playwright
&lt;/h2&gt;

&lt;p&gt;In this example, we will create a React app using Playwright as its end-to-end testing framework. In the terminal, run the below command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-nx-workspace

✔ Where would you like to create your workspace? · nx-react-playwright
✔ Which stack do you want to use? · react
✔ What framework would you like to use? · none
✔ Integrated monorepo, or standalone project? · standalone
✔ Which bundler would you like to use? · vite
✔ Test runner to use for end to end (E2E) tests · playwright
✔ Default stylesheet format · css
✔ Enable distributed caching to make your CI faster · No
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We get a standalone Nx React app named &lt;code&gt;nx-react-playwright&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KvacbV-2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eyue6nn0o8cia72l1sr0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KvacbV-2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eyue6nn0o8cia72l1sr0.png" alt="Nx Workspace" width="516" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is a &lt;a href="https://nx.dev/concepts/integrated-vs-package-based#standalone-applications"&gt;standalone application&lt;/a&gt;? It is like an integrated monorepo setup but with just a single, root-level application. The repo has the same file structure as an app created from Create-React-App, but we can still leverage all the generators and executors and structure your application into libraries or submodules.&lt;/p&gt;
&lt;h3&gt;
  
  
  Run E2E
&lt;/h3&gt;

&lt;p&gt;The default e2e test is located in &lt;code&gt;e2e/src/example.spec.ts&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;import { test, expect } from '@playwright/test';

test('has title', async ({ page }) =&amp;gt; {
  await page.goto('/');
  // Expect h1 to contain a substring.
  expect(await page.locator('h1').innerText()).toContain('Welcome');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The test verifies the h1 header contains the text Welcome:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ezO51Cfb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4wf6316bguq2djvqr919.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ezO51Cfb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4wf6316bguq2djvqr919.png" alt="h1 header with Welcome text" width="776" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To run the e2e tests, run the below command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx e2e e2e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the terminal, it shows the following log:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; nx run nx-react-playwright:serve:development
  ➜  Local:   http://localhost:4200/
  3 passed (11.8s)
To open last HTML report run:

  npx playwright show-report dist/.playwright/e2e/playwright-report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So the test passed and it also generated a report at &lt;code&gt;dist/.playwright/e2e/playwright-report/index.html&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q6-Sjp4W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nta7a5rx1eidw8zczmtv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q6-Sjp4W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nta7a5rx1eidw8zczmtv.png" alt="HTML test report" width="800" height="272"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Add Another Test
&lt;/h3&gt;

&lt;p&gt;Let's add another test to check the Documentation button works:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IVjvL-Wt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ob9ehwjq97ekruyqdxg2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IVjvL-Wt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ob9ehwjq97ekruyqdxg2.png" alt="Documentation Button" width="408" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;src/app/nx-welcome.tsx&lt;/code&gt;, we need to add a test id to the link:&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;a
  href="https://nx.dev/getting-started/intro?utm_source=nx-project"
  target="_blank"
  rel="noreferrer"
  className="list-item-link"
  data-testid="documentation-link"
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then in &lt;code&gt;e2e/src/example.spec.ts&lt;/code&gt;, the test file will become:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { test, expect } from '@playwright/test';

test.describe('navigation', () =&amp;gt; {
  test.beforeEach(async ({ page }) =&amp;gt; {
    // Go to the starting url before each test.
    await page.goto('/');
  });

  test('has title', async ({ page }) =&amp;gt; {
    // Expect h1 to contain a substring.
    expect(await page.locator('h1').innerText()).toContain('Welcome');
  });

  test('should go to documentation site', async ({ page, context }) =&amp;gt; {
    await page.getByTestId('documentation-link').click();
    // Opening a new tab and waiting for the page to render
    const pagePromise = context.waitForEvent('page');
    const newPage = await pagePromise;
    await newPage.waitForLoadState();
    expect(await newPage.title()).toContain('Intro to Nx');
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now run &lt;code&gt;npx nx e2e e2e&lt;/code&gt;, the test would still pass:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; nx run nx-react-playwright:serve:development
  ➜  Local:   http://localhost:4200/
  6 passed (3.1s)
To open last HTML report run:

  npx playwright show-report dist/.playwright/e2e/playwright-report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now we have created a new Nx workspace with Playwright. However, if you already have an Nx repo, how do you add Playwright E2E configuration to an existing app?&lt;/p&gt;


&lt;h2&gt;
  
  
  How to add Playwright to an existing Nx workspace
&lt;/h2&gt;

&lt;p&gt;For this example, I am going to add Playwright e2e tests to the below repo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/nrwl"&gt;
        nrwl
      &lt;/a&gt; / &lt;a href="https://github.com/nrwl/nx-examples"&gt;
        nx-examples
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Example repo for Nx workspace
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
NxExample&lt;/h1&gt;
&lt;p&gt;This project was generated using &lt;a href="https://nx.dev" rel="nofollow"&gt;Nx&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/nrwl/nx/master/nx-logo.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EiUAkgZc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/nrwl/nx/master/nx-logo.png" width="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;🔎 &lt;strong&gt;Powerful, Extensible Dev Tools&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
Quick Start &amp;amp; Documentation&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://nx.dev" rel="nofollow"&gt;Nx Documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nx.dev/getting-started/what-is-nx" rel="nofollow"&gt;30-minute video showing all Nx features&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nx.dev/tutorial/01-create-application" rel="nofollow"&gt;Interactive Tutorial&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Adding capabilities to your workspace&lt;/h2&gt;
&lt;p&gt;Nx supports many plugins which add capabilities for developing different types of applications and different tools.&lt;/p&gt;
&lt;p&gt;These capabilities include generating applications, libraries, etc as well as the devtools to test, and build projects as well.&lt;/p&gt;
&lt;p&gt;Below are our core plugins:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://reactjs.org" rel="nofollow"&gt;React&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npm install --save-dev @nx/react&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Web (no framework frontends)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npm install --save-dev @nx/web&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://angular.io" rel="nofollow"&gt;Angular&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npm install --save-dev @nx/angular&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nestjs.com" rel="nofollow"&gt;Nest&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npm install --save-dev @nrwl/nest&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://expressjs.com" rel="nofollow"&gt;Express&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npm install --save-dev @nrwl/express&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org" rel="nofollow"&gt;Node&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npm install --save-dev @nrwl/node&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are also many &lt;a href="https://nx.dev/community" rel="nofollow"&gt;community plugins&lt;/a&gt; you could add.&lt;/p&gt;
&lt;h2&gt;
Generate an application&lt;/h2&gt;
&lt;p&gt;Run &lt;code&gt;nx g @nx/react:app my-app&lt;/code&gt; to generate an application.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can use any of the plugins above to generate applications as well.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When using Nx, you can create multiple applications and libraries in…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/nrwl/nx-examples"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;We are going to focus on the cart app in this example. In the terminal, run &lt;code&gt;npx nx serve cart&lt;/code&gt; and it should serve up the app at &lt;a href="http://localhost:4200/cart"&gt;http://localhost:4200/cart&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Sn4tyqiy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sjbz9dbvgqzuelfgl5ch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Sn4tyqiy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sjbz9dbvgqzuelfgl5ch.png" alt="Cart App" width="800" height="648"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install @nx/playwright
&lt;/h3&gt;

&lt;p&gt;To install, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#npm
npm install @nx/playwright --save-dev

#yarn
yarn add @nx/playwright --dev

#pnpm
pnpm i -D @nx/playwright
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Apply Playwrightt Configuration
&lt;/h3&gt;

&lt;p&gt;There are 2 ways to apply the E2E Playwright configuration.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Apply directly on the cart app
&lt;/h4&gt;

&lt;p&gt;We can set up Playwright directly on the cart app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx generate @nx/playwright:configuration --project=cart ---webServerCommand="npx nx serve cart"  --webServerAddress="http://localhost:4200"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It adds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an e2e target in &lt;code&gt;apps/cart/project.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;an e2e folder at &lt;code&gt;apps/cart/e2e&lt;/code&gt; containing e2e tests&lt;/li&gt;
&lt;li&gt;playwright.config.ts containing Playwright configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ENmXbFM8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1pkdwhv25jqxgvzcr0ld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ENmXbFM8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1pkdwhv25jqxgvzcr0ld.png" alt="Playwright Files Added" width="520" height="752"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's update the default test &lt;code&gt;apps/cart/e2e/example.spec.ts&lt;/code&gt; to check whether the header exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { test, expect } from '@playwright/test';

test('has title', async ({ page }) =&amp;gt; {
  await page.goto('/cart');

  await expect(page.locator('nx-example-header')).toBeVisible()
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can run &lt;code&gt;npx nx e2e cart&lt;/code&gt; and it should pass.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Add a separate E2E Project
&lt;/h4&gt;

&lt;p&gt;The second way is to create a separate E2E project folder and apply configuration there.&lt;br&gt;
Create a folder e2e at the workspace root and a &lt;code&gt;project.json&lt;/code&gt; file inside it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aTymuTll--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/icj7iqvw9cdkxppt7s85.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aTymuTll--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/icj7iqvw9cdkxppt7s85.png" alt="project.json" width="290" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add name in e2e/project.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "e2e"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now apply the Playwright configuration to the e2e project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nx generate @nx/playwright:configuration --project=e2e ---webServerCommand="npx nx serve cart"  --webServerAddress="http://localhost:4200"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I created an e2e folder at the workspace root:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LQWkRXUZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jachsr1wo2053po8erjx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LQWkRXUZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jachsr1wo2053po8erjx.png" alt="e2e folder" width="412" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can run &lt;code&gt;npx nx e2e e2e&lt;/code&gt; to run the Playwright e2e tests.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this blog, we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created a new Nx react repo with Playwright&lt;/li&gt;
&lt;li&gt;Written our own Playwright tests&lt;/li&gt;
&lt;li&gt;Used Nx to run Playwright tests&lt;/li&gt;
&lt;li&gt;Set up a Playwright configuration for an existing Nx app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hopefully, this gives you good insight into how to get started with Playwright. The Playwright configuration in this example is pretty simple, to learn more about &lt;code&gt;@nx/playwright&lt;/code&gt; plugin, check out the Nx documentation: &lt;a href="https://nx.dev/packages/playwright"&gt;https://nx.dev/packages/playwright&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;a href="https://nx.dev/"&gt;Nx Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👩‍💻 &lt;a href="https://github.com/nrwl/nx"&gt;Nx GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://go.nrwl.io/join-slack"&gt;Nx Community Slack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📹 &lt;a href="https://www.youtube.com/@nxdevtools"&gt;Nx Youtube Channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;a href="https://nx.app/"&gt;Speed up your CI&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Speed up your Yarn Workspace with Nx</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Wed, 01 Jun 2022 15:48:18 +0000</pubDate>
      <link>https://forem.com/nx/speed-up-your-yarn-workspace-with-nx-3an8</link>
      <guid>https://forem.com/nx/speed-up-your-yarn-workspace-with-nx-3an8</guid>
      <description>&lt;p&gt;If you have a Yarn workspace, you can turn it into an &lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;Nx&lt;/a&gt; monorepo with a simple command. Below is an example of a Yarn workspace with multiple Expo apps which we will be using to add Nx:&lt;br&gt;
&lt;a href="https://github.com/byCedric/eas-monorepo-example" rel="noopener noreferrer"&gt;https://github.com/byCedric/eas-monorepo-example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this example workspace, there are 3 Expo applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;managed: Expo &lt;a href="https://docs.expo.dev/introduction/managed-vs-bare/#managed-workflow" rel="noopener noreferrer"&gt;managed&lt;/a&gt; app&lt;/li&gt;
&lt;li&gt;ejected: Expo &lt;a href="https://docs.expo.dev/introduction/managed-vs-bare/#bare-workflow" rel="noopener noreferrer"&gt;bare&lt;/a&gt; app&lt;/li&gt;
&lt;li&gt;with-sentry: Expo managed app with &lt;a href="https://github.com/expo/sentry-expo" rel="noopener noreferrer"&gt;&lt;code&gt;sentry-expo&lt;/code&gt;&lt;/a&gt; integrated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you run the app, each app will just have a text in the middle of the screen:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1260%2F1%2AZUmmlN28C0dG9I_fu1lttw.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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2AZUmmlN28C0dG9I_fu1lttw.png" alt="Screenshots of 3 applications"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog is going to show you how to turn the above Yarn workspace to Nx.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why Nx?
&lt;/h2&gt;

&lt;p&gt;Before we start, the first question we need to address is: why go through all the troubles to turn a working Yarn workspace to Nx? If you got a Yarn workspace, you can already share code between apps. So why Nx?&lt;/p&gt;

&lt;p&gt;Like Yarn workspace, Nx is a monorepo tool. However, unlike Yarn workspace, not only does Nx provide faster build time and better developer experience, but it will also provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Workspace visualizations&lt;/li&gt;
&lt;li&gt;Distributed Task Execution&lt;/li&gt;
&lt;li&gt;Easy Updating&lt;/li&gt;
&lt;li&gt;Editor Plugin&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;p&gt;After checkout the repo, go to the folder and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx add-nx-to-monorepo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see below in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;  NX  🐳 Nx initialization
? Use Nx Cloud? (It's free and doesn't require registration.) Yes [Faster builds, run detail
s, Github integration. Learn more at https://nx.app]
&amp;gt;  NX  🧑‍🔧 Analyzing the source code and creating configuration files
&amp;gt;  NX  📦 Installing dependencies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see that a file named &lt;code&gt;nx.json&lt;/code&gt; is created in your workspace root.&lt;/p&gt;

&lt;p&gt;Notice in package.json: you should see the latest &lt;code&gt;nx&lt;/code&gt; is added to devDependencies like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"devDependencies": {
  "nx": "14.1.6"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it! Now you officially added Nx to your workspace.&lt;/p&gt;




&lt;h2&gt;
  
  
  Faster Build
&lt;/h2&gt;

&lt;p&gt;In the Yarn workspace, if you run yarn build, it will run the build command for each app and library. It took 5.51 seconds for the below instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yarn workspaces run build
&amp;gt; @acme/app-ejected
$ echo 'Nothing to build'
Nothing to build
&amp;gt; @acme/app-managed
$ echo 'Nothing to build'
Nothing to build
&amp;gt; @acme/app-with-dev-client
$ echo 'Nothing to build'
Nothing to build
&amp;gt; @acme/app-with-sentry
$ echo 'Nothing to build'
Nothing to build
&amp;gt; @acme/babel-preset-expo
$ echo 'Nothing to build'
Nothing to build
&amp;gt; @acme/eslint-config
$ echo 'Nothing to build'
Nothing to build
&amp;gt; @acme/ui
$ bob build
ℹ Building target commonjs
ℹ Cleaning up previous build at build/commonjs
ℹ Compiling 1 files in src with babel
✔ Wrote files to build/commonjs
ℹ Building target module
ℹ Cleaning up previous build at build/module
ℹ Compiling 1 files in src with babel
✔ Wrote files to build/module
ℹ Building target typescript
ℹ Cleaning up previous build at build/typescript
ℹ Generating type definitions with tsc
✔ Wrote definition files to build/typescript
✨  Done in 5.51s.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, after turning the workspace to Nx, run the build command against all apps and libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn nx run-many --target=build --all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice it will take much less time the 2nd run. For example, it only took 0.96 seconds for the below instance:&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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2AqjNY5uCAnC_0O2coa0Trpw.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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2AqjNY5uCAnC_0O2coa0Trpw.png" alt="Console output for Nx build command"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same goes for linting. If you run &lt;code&gt;yarn test&lt;/code&gt;, notice it would run linting for each app and library (in this repo, it uses the test script to run eslint). For the below instance, it took 18.26 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn run v1.22.10
$ yarn workspaces run test
&amp;gt; @acme/app-ejected
$ eslint --ext js,ts,tsx .
&amp;gt; @acme/app-managed
$ eslint --ext js,ts,tsx .
&amp;gt; @acme/app-with-dev-client
$ eslint --ext js,ts,tsx .
&amp;gt; @acme/app-with-sentry
$ eslint --ext js,ts,tsx .
&amp;gt; @acme/babel-preset-expo
$ echo 'Nothing to test'
Nothing to test
&amp;gt; @acme/eslint-config
$ echo 'Nothing to test'
Nothing to test
&amp;gt; @acme/ui
$ eslint --ext ts,tsx ./src
✨  Done in 18.26s.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run the test command for all apps and libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn nx run-many --target=test --all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice for the below instance, it only took 0.95 seconds:&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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2Am0GGbuQjBHCURuV71lxQMw.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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2Am0GGbuQjBHCURuV71lxQMw.png" alt="Console output for Nx test command"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this repo, it actually decreased build and lint runtime by ~90%. How does Nx achieve that?&lt;/p&gt;

&lt;p&gt;Notice in the terminal console that it sometimes says &lt;code&gt;Nx read the output from the cache instead of running the command&lt;/code&gt;. This is because Nx uses &lt;a href="https://nx.dev/using-nx/caching#computation-caching" rel="noopener noreferrer"&gt;Computation Caching&lt;/a&gt;. If the app or lib has no change, it would retrieve the computation from the cache. In short, it never builds, tests, or lints the same code twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workspace Visualizations &amp;amp; Boundary Rules
&lt;/h2&gt;

&lt;p&gt;To see the workspace project graph, run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn nx graph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should be able to see the below graph:&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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2ApILzV-ESjXR_xsBBXRwPJw.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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2ApILzV-ESjXR_xsBBXRwPJw.png" alt="Workspace project graph"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Being able to perform &lt;a href="https://nx.dev/structure/dependency-graph#analyzing--visualizing-workspaces" rel="noopener noreferrer"&gt;workspace visualization&lt;/a&gt; can be a huge benefit. In particular, it is handy for tracing and debugging as you can clearly see how apps and libs on this workspace are related to each other.&lt;/p&gt;

&lt;p&gt;Now, this is a relatively small workspace with only 3 libraries and 4 applications. As your workspace grows it becomes increasingly a challenge to tame dependencies and imports between libs. You definitely don’t want your monorepo to become a big entangled mess. Also, tracing circular dependencies in a bigger repo can quickly become a headache to trace and debug if your only tool is examining the code.&lt;/p&gt;

&lt;p&gt;In addition to using the project graph Nx also comes with a lint rule &lt;code&gt;@nrwl/nx/enforce-module-boundaries&lt;/code&gt; to help detect circular dependencies early and prevent imports between libs that shouldn’t talk to each other. Read more in our blog post on “&lt;a href="https://dev.to/nx/taming-code-organization-with-module-boundaries-in-nx-1icl"&gt;Taming Code Organization with Module Boundaries in Nx&lt;/a&gt;”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distributed Task Execution
&lt;/h2&gt;

&lt;p&gt;Nx also comes with an &lt;code&gt;affected&lt;/code&gt; command: instead of running the command against all apps and libraries, it will only run the command against the one that got “affected” by a change.&lt;/p&gt;

&lt;p&gt;For example, if you made no code change and run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn nx affected --target=build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will not run build for any project:&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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2AIRF5-bzEexpfPyGq0m4UVA.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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2AIRF5-bzEexpfPyGq0m4UVA.png" alt="Console output for Nx build when no change is made"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If instead, you changed the &lt;code&gt;ui&lt;/code&gt; library in this workspace, the apps that depend on the library will get affected (&lt;code&gt;apps-ejected&lt;/code&gt;, &lt;code&gt;app-managed&lt;/code&gt;, &lt;code&gt;app-with-dev-client&lt;/code&gt;, &lt;code&gt;app-with-sentry&lt;/code&gt;); the library &lt;code&gt;babel-preset-expo&lt;/code&gt; and &lt;code&gt;eslint-config&lt;/code&gt; will not be affected.&lt;/p&gt;

&lt;p&gt;If you run yarn &lt;code&gt;nx affected:graph&lt;/code&gt;, you should see the dependency graph:&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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2ABUshtwYUlgzhBjVSy2ly4A.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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2ABUshtwYUlgzhBjVSy2ly4A.png" alt="Affected dependency graph with UI change"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now run the command &lt;code&gt;yarn nx affected --target=build&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1260%2F1%2AQm93eM3ZbTHNgzzwLBfsAQ.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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2AQm93eM3ZbTHNgzzwLBfsAQ.png" alt="Console output for Nx build when ui library changed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice in the console, &lt;code&gt;babel-preset-expo&lt;/code&gt; and &lt;code&gt;eslint-config&lt;/code&gt; are retrieved from the cache; the library ui and all the apps are rebuilt.&lt;/p&gt;

&lt;p&gt;If you only changed the managed app, the other apps are not affected.The dependency graph should look like the below with only &lt;code&gt;app-managed&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F277%2F1%2AywPHCW_mknliXc2qJMc5gw.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%2Fmiro.medium.com%2Fmax%2F277%2F1%2AywPHCW_mknliXc2qJMc5gw.png" alt="Dependency graph with managed app changed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now run the command again:&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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2AjHnN0ErSuVMAtEFXDJOTAw.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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2AjHnN0ErSuVMAtEFXDJOTAw.png" alt="Console output for Nx build when managed app changed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that it only builds the &lt;code&gt;app-managed&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;affected&lt;/code&gt; command is a powerful tool that further reduces your build, test and lint time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Easy Updating
&lt;/h2&gt;

&lt;p&gt;Another powerful command Nx has to offer is &lt;a href="https://nx.dev/cli/migrate#migrate" rel="noopener noreferrer"&gt;&lt;code&gt;migrate&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By running command &lt;code&gt;yarn nx migrate latest&lt;/code&gt;, it would automatically update to the latest versions of all frameworks and tools. For example, for an Expo workspace, if you want to upgrade the Expo version, you may need to upgrade React Native, React and other libraries' versions as well. You can go into your package.json and try to change the version number manually, or you can leave it to Nx to upgrade the version for you. Nx is not only going to update the version numbers, but also run code &amp;amp; config migrations if applicable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nx Editor Plugins
&lt;/h2&gt;

&lt;p&gt;Nx also offers powerful Editor Plugins to improve the developer experience. For example. you can use &lt;a href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console" rel="noopener noreferrer"&gt;Nx Console&lt;/a&gt; for VS Code. Then adding another Expo app to this workspace will be one click away:&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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2AG92QDpZR_aoU4H6XuzrJBg.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%2Fmiro.medium.com%2Fmax%2F1260%2F1%2AG92QDpZR_aoU4H6XuzrJBg.png" alt="Nx Console"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;These are some of the features Nx has to offer in comparison with Yarn Workspace.&lt;/p&gt;

&lt;p&gt;Hopefully, after reading this blog, I have persuaded you to convert your Yarn workspace to Nx, or at least be willing to try Nx out. If not, you can read more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nx.dev/migration/adding-to-monorepo" rel="noopener noreferrer"&gt;Adding Nx to Lerna/Yarn/PNPM/NPM Workspace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.nrwl.io/lerna-yarn-nx-faster-build-times-better-dev-ergonomics-2ec28463d3a5" rel="noopener noreferrer"&gt;From Lerna/Yarn to Nx: Faster Build Times and Better Dev Ergonomics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Where to go from here?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;join the community Slack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;follow Nx on Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;learn more about Nx at &lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;https://nx.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;subscribe to the &lt;a href="https://youtube.com/c/Nrwl_io" rel="noopener noreferrer"&gt;Nx Youtube channel&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nx</category>
      <category>yarn</category>
      <category>monorepo</category>
      <category>expo</category>
    </item>
    <item>
      <title>Testing React Native apps with Jest</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Fri, 06 May 2022 16:30:48 +0000</pubDate>
      <link>https://forem.com/nx/testing-react-native-apps-with-jest-51ab</link>
      <guid>https://forem.com/nx/testing-react-native-apps-with-jest-51ab</guid>
      <description>&lt;h2&gt;
  
  
  How to write unit and e2e tests for React Native apps using Jest in an Nx workspace
&lt;/h2&gt;

&lt;p&gt;In my previous &lt;a href="https://dev.to/nx/share-code-between-react-web-react-native-mobile-with-nx-12eb"&gt;blog&lt;/a&gt;, I finally finished writing my awesome Nx React Native App. The app is running fine. Can I just commit my changes and call it a wrap?&lt;/p&gt;

&lt;p&gt;No. As a disciplined developer, I know that finishing writing application code is only a job half done; the other half is writing tests.&lt;/p&gt;

&lt;p&gt;This blog will go through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to write unit tests for React Native components&lt;/li&gt;
&lt;li&gt;How to write e2e tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example Repo: &lt;a href="https://github.com/xiongemi/studio-ghibli-search-engine" rel="noopener noreferrer"&gt;https://github.com/xiongemi/studio-ghibli-search-engine&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Unit Testing with Nx React Native
&lt;/h2&gt;

&lt;p&gt;To run unit tests, simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nx test &amp;lt;your app or lib&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you’re using Visual Studio Code, you can use &lt;a href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console" rel="noopener noreferrer"&gt;Nx Console&lt;/a&gt; to run the test command:&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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2A8vG3Qbp-vDyPFSkMEgQ2SA.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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2A8vG3Qbp-vDyPFSkMEgQ2SA.png" alt="Test command in Nx Console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should see the unit test results in your terminal:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Test Suites: 10 failed, 1 passed, 11 total
Tests:       9 failed, 1 passed, 10 total
Snapshots:   0 total
Time:        9.84 s, estimated 21 s
Ran all test suites.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is what a starter unit test looks like:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Testing framework: &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;jest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Testing library: &lt;a href="https://callstack.github.io/react-native-testing-library/" rel="noopener noreferrer"&gt;@testing-library/react-native&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To write a unit test:&lt;/p&gt;

&lt;p&gt;In your component, you can add &lt;code&gt;testID&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;&amp;lt;Headline testID='title'&amp;gt;{film.title}&amp;lt;/Headline&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then in the test file, you can use function &lt;code&gt;getByTestId&lt;/code&gt; to query &lt;code&gt;testID&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;const { getByTestId } = render(&amp;lt;your component&amp;gt;);
expect(getByTestId('title')).toHaveTextContent(...);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can view more queries here: &lt;a href="https://callstack.github.io/react-native-testing-library/docs/api-queries" rel="noopener noreferrer"&gt;https://callstack.github.io/react-native-testing-library/docs/api-queries&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first time running the unit tests is unlikely to pass. There are usually a few errors I run into, I either have to fix the code and tests, or I need to mock some library.&lt;/p&gt;
&lt;h3&gt;
  
  
  Troubleshooting
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Error: Jest failed to parse a file
&lt;/h4&gt;

&lt;p&gt;If you are using libraries that contain native code, such as &lt;code&gt;react-native-paper&lt;/code&gt; or &lt;code&gt;@react-navigation/native&lt;/code&gt;, you are likely to run into the below error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jest encountered an unexpected token&lt;br&gt;
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To fix this, add that library name to &lt;code&gt;transformIgnorePatterns&lt;/code&gt; in the &lt;code&gt;jest.config.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;transformIgnorePatterns: [
  'node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base)',
],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Error: Animated
&lt;/h4&gt;

&lt;p&gt;If you use React Native’s Animated library or you use a material library like &lt;code&gt;react-native-paper&lt;/code&gt; or &lt;code&gt;react-native-elements&lt;/code&gt;, you are likely to get the below warning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;console.warn&lt;br&gt;
      Animated: &lt;code&gt;useNativeDriver&lt;/code&gt; is not supported because the native animated module is missing. Falling back to JS-based animation. To resolve this, add &lt;code&gt;RCTAnimation&lt;/code&gt; module to this app, or remove &lt;code&gt;useNativeDriver&lt;/code&gt;. Make sure to run &lt;code&gt;bundle exec pod install&lt;/code&gt; first. Read more about autolinking: &lt;a href="https://github.com/react-native-community/cli/blob/master/docs/autolinking.md" rel="noopener noreferrer"&gt;https://github.com/react-native-community/cli/blob/master/docs/autolinking.md&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the test-setup file under your app or lib, add below mock:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jest.mock(
  '../../node_modules/react-native/Libraries/Animated/NativeAnimatedHelper'
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Error: Is your component inside a screen in a navigator?
&lt;/h4&gt;

&lt;p&gt;If you use &lt;code&gt;@react-navigation&lt;/code&gt; library for navigation, and inside your component, there are hooks from this library like &lt;code&gt;useNavigation&lt;/code&gt; and &lt;code&gt;useRoute&lt;/code&gt;, you are likely to get this error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Couldn't find a route object. Is your component inside a screen in a navigator?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The easiest way to fix this is to mock the &lt;code&gt;@react-navigation/native&lt;/code&gt; library like below in test-setup file under your app or lib:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h4&gt;
  
  
  Error: Could not find “store”
&lt;/h4&gt;

&lt;p&gt;If your component is a smart component that uses Redux Store, you are going to get this error when testing that component:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Could not find "store" in the context of "Connect(Results)". Either wrap the root component in a , or pass a custom React context provider to  and the corresponding React context consumer to Connect(Results) in connect options&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To fix this, you need to wrap your component inside &lt;code&gt;&amp;lt;Provider store={store}&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, you need to install &lt;code&gt;redux-mock-store&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;# npm
npm install redux-mock-store @types/redux-mock-store --save-dev

# yarn
yarn add redux-mock-store @types/redux-mock-store --dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The test would become:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Example unit test with different store states:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here are how to write unit tests for React Native components and some common errors you are likely to run into.&lt;/p&gt;

&lt;p&gt;Now with all the unit tests in place, you need to write e2e tests.&lt;/p&gt;




&lt;h2&gt;
  
  
  E2E Testing with Nx React Native
&lt;/h2&gt;

&lt;p&gt;When generating an Nx React Native app, you should see a folder ends with e2e created.&lt;/p&gt;

&lt;p&gt;To run the e2e tests against Debug build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In one terminal, run &lt;code&gt;nx start &amp;lt;your app&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In another terminal, run:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# iOS
nx test-ios &amp;lt;your app-e2e&amp;gt;

# Android
nx test-android &amp;lt;your app-e2e&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you want to run the e2e test against Release build, run:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# iOS
nx test-ios &amp;lt;your app-e2e&amp;gt; --prod

# Android
nx test-android &amp;lt;your app-e2e&amp;gt; --prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Test framework: &lt;a href="https://github.com/wix/Detox" rel="noopener noreferrer"&gt;Detox&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Test runner: &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;jest&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Generally, the e2e tests should follow the below pattern:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;For example, my app’s starter page looks like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2ALdob3R4V50WG4gP-UzKAOg.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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2ALdob3R4V50WG4gP-UzKAOg.png" alt="Stater page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is my e2e test to check whether it displays the heading:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;For my component, I added &lt;code&gt;testID&lt;/code&gt; in order to be queried by e2e tests:&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;SafeAreaView testID="search-page"&amp;gt;
...
&amp;lt;Headline testID="heading"&amp;gt;Studio Ghibli Search Engine&amp;lt;/Headline&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For example, my app has a flow that users can search text like &lt;code&gt;totoro&lt;/code&gt; and go to the film details:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AFUBUwq53wrrCCfdi9_ENvA.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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AFUBUwq53wrrCCfdi9_ENvA.png" alt="Search flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The e2e test looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;You can read more about matchers and actions in Detox here: &lt;a href="https://wix.github.io/Detox/docs/api/matchers" rel="noopener noreferrer"&gt;https://wix.github.io/Detox/docs/api/matchers&lt;/a&gt;.&lt;/p&gt;




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

&lt;p&gt;Here is how to test Nx React Native apps. With Nx, you do not need to explicitly install any testing library like Jest or Detox. So you can dive right in and focus on writing the tests rather than spending time on setup.&lt;/p&gt;

&lt;p&gt;Check out my previous blog about Nx React Native:&lt;br&gt;
&lt;a href="https://dev.to/nx/share-code-between-react-web-react-native-mobile-with-nx-12eb"&gt;https://dev.to/nx/share-code-between-react-web-react-native-mobile-with-nx-12eb&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Where to go from here?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;join the community Slack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;follow Nx on Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;learn more about Nx at &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;https://nx.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;subscribe to the &lt;a href="https://youtube.com/c/Nrwl_io" rel="noopener noreferrer"&gt;Nx Youtube channel&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nx</category>
      <category>reactnative</category>
      <category>jest</category>
      <category>detox</category>
    </item>
    <item>
      <title>Use Storybook with Nx React Native</title>
      <dc:creator>Emily Xiong</dc:creator>
      <pubDate>Fri, 29 Apr 2022 18:48:50 +0000</pubDate>
      <link>https://forem.com/nx/use-storybook-with-nx-react-native-2p62</link>
      <guid>https://forem.com/nx/use-storybook-with-nx-react-native-2p62</guid>
      <description>&lt;p&gt;In my previous &lt;a href="https://emilyxiong.medium.com/share-code-between-react-web-react-native-mobile-with-nx-fe5e22b5a755" rel="noopener noreferrer"&gt;blog&lt;/a&gt;, I wrote about how to develop Nx React Native applications. However, as developers, we are constantly searching for ways to make the developer experience better.&lt;/p&gt;

&lt;p&gt;This blog will show how to add Storybook to Nx React Native applications. With Nx, you don’t need to go through &lt;a href="https://storybook.js.org/tutorials/intro-to-storybook/react-native/en/get-started/" rel="noopener noreferrer"&gt;this long guideline&lt;/a&gt; to set up the Storybook, you can quickly get it running.&lt;/p&gt;

&lt;p&gt;Example Repo: &lt;a href="https://github.com/xiongemi/studio-ghibli-search-engine" rel="noopener noreferrer"&gt;https://github.com/xiongemi/studio-ghibli-search-engine&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Storybook:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AbDKKjnrt2D6XIBDnWN1z2Q.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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AbDKKjnrt2D6XIBDnWN1z2Q.png" alt="Storybook View (left: Android, right: iOS)"&gt;&lt;/a&gt;&lt;/p&gt;


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

&lt;p&gt;First, you need to add &lt;code&gt;@nrwl/storybook&lt;/code&gt; to your existing Nx React Native workspace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# npm
npm install @nrwl/storybook --save-dev

# yarn
yarn add --dev @nrwl/storybook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then you need to generate the storybook configuration for your app or lib:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nx g @nrwl/react-native:storybook-configuration &amp;lt;your app or lib&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As shown in the example below, 3 folders got generated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.storybook&lt;/code&gt; at workspace root&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.storybook&lt;/code&gt; in your app or lib&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;storybook&lt;/code&gt; in your app (Note: this folder is for creating the Storybook UI component. It will only be created for the app, you will not see this for lib.)
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1352%2F1%2Aq1sX4VQKdRzQpye6Qcs2Ow.png" alt="Folders created"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you choose to automatically generate &lt;code&gt;*.stories&lt;/code&gt; file, you should see the default story looks like below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;To gather the stories you created, run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nx storybook &amp;lt;your app or lib&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You should see in the terminal saying:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Writing to &amp;lt;your workspace&amp;gt;/.storybook/story-loader.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In your &lt;code&gt;&amp;lt;your workspace&amp;gt;/.storybook/story-loader.js&lt;/code&gt;, it should list your stories created under your app or lib similar to the below example:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Also, notice that in your app’s main file, the import of the App changed to &lt;code&gt;storybook/toggle-storybook&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;import App from './storybook/toggle-storybook';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  View Storybook for App
&lt;/h2&gt;

&lt;p&gt;To view the storybook on the simulator/emulator/device, start the app like you usually do:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# iOS
nx run-ios &amp;lt;your app&amp;gt;

# Android
nx run-android &amp;lt;your app&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In your simulator/emulator/device, open the Debug Menu by entering &lt;code&gt;d&lt;/code&gt; in terminal. You should see the menu option &lt;code&gt;Toggle Storybook&lt;/code&gt; in the Debug Menu:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AaziO6KSwVhtXWwfyADGbAA.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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AaziO6KSwVhtXWwfyADGbAA.png" alt="Screenshot of Debug menu (left: Android, right: iOS)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When switching on the toggle, you should see the list of your component stories:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AKYn3sPUpBU_ewRh2zJ7niQ.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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AKYn3sPUpBU_ewRh2zJ7niQ.png" alt="Storybook View (left: Android, right: iOS)"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  View Storybook for Lib
&lt;/h2&gt;

&lt;p&gt;Note: the storybook can only be viewed inside an app. To view the storybook for lib in the workspace, you need to first set up the storybook for an app in the workspace.&lt;br&gt;
Then run the command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nx storybook &amp;lt;your lib&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This should update the &lt;code&gt;.storybook/story-loader.js&lt;/code&gt; with stories in your lib.&lt;br&gt;
Then just run the command to start your app, you should see the storybook for your lib.&lt;/p&gt;
&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Error: Couldn’t find a navigation object
&lt;/h3&gt;

&lt;p&gt;If you are using the library &lt;code&gt;@react-navigation/native&lt;/code&gt; and you are using hooks like &lt;code&gt;useNavigtion&lt;/code&gt; and &lt;code&gt;useRoute&lt;/code&gt; inside your component, you are likely to get the below error: " Couldn’t find a navigation object".&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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AoKNqqay19gpvIRgW1QGbkA.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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AoKNqqay19gpvIRgW1QGbkA.png" alt="Render Error for Couldn’t find a navigation object"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The easiest way is just to mock this library and create a decorator for it:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Then in your story, you just need to add the above &lt;code&gt;NavigationDecorator&lt;/code&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now, this error should go away and you should see your component in your storybook.&lt;/p&gt;

&lt;p&gt;If your component is using the &lt;code&gt;useRoute&lt;/code&gt; hook and expecting certain routing parameters, then you need to customize the mock &lt;code&gt;NavigationDecorator&lt;/code&gt; for your component. For example, below is a component that is expecting an id from the route parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const route = useRoute&amp;lt;RouteProp&amp;lt;{ params: { id: string } }&amp;gt;&amp;gt;();
const id = route.params?.id;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The mock &lt;code&gt;NavigationDecorator&lt;/code&gt; will become:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Error: Could not find “store”
&lt;/h3&gt;

&lt;p&gt;If you are using Redux store and your component is stateful and connected to the store, you are likely to get the below error:&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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AT-Lj4PjuAlb_TbpSU5_1PQ.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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AT-Lj4PjuAlb_TbpSU5_1PQ.png" alt="Render Error for Could not find “store”"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The simple solution is to mock the store. First, you need to install the library &lt;a href="https://github.com/reduxjs/redux-mock-store" rel="noopener noreferrer"&gt;redux-mock-store&lt;/a&gt; and its typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# npm
npm install redux-mock-store @types/redux-mock-store --save-dev

# yarn
yarn add redux-mock-store @types/redux-mock-store --dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Similarly, like how you mock up the navigation, you need to mock up the store. The below example mocks the store with the initial root state:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;You can add this store decorator to your story:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Error: Actions must be plain objects
&lt;/h3&gt;

&lt;p&gt;If you use an async action (for example, an action created using &lt;code&gt;createAsyncThunk&lt;/code&gt; from &lt;code&gt;@reduxjs/toolkit&lt;/code&gt;), you would likely run into the below error: Actions must be plain objects.&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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AsJXG_eFpItyPt7ilyF19fw.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%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AsJXG_eFpItyPt7ilyF19fw.png" alt="Render Error for Actions must be plain objects"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now to resolve this, add &lt;code&gt;thunk&lt;/code&gt; to mock store middleware:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





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

&lt;p&gt;Here are how to use Storybook with Nx React Native and some common errors you may run into. With Nx React Native, you can quickly view Storybook with a toggle option in Debug Menu. It allows developers to interact and test with components during development.&lt;/p&gt;

&lt;p&gt;Check out my previous blog about Nx React Native:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/nx/share-code-between-react-web-react-native-mobile-with-nx-12eb"&gt;Share code between React Web &amp;amp; React Native Mobile with Nx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Where to go from here?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://go.nrwl.io/join-slack" rel="noopener noreferrer"&gt;join the community Slack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/nxdevtools" rel="noopener noreferrer"&gt;follow Nx on Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;learn more about Nx at &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;https://nx.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;subscribe to the &lt;a href="https://youtube.com/c/Nrwl_io" rel="noopener noreferrer"&gt;Nx Youtube channel&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nx</category>
      <category>reactnative</category>
      <category>storybook</category>
      <category>monorepo</category>
    </item>
  </channel>
</rss>
