<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Hanna Sobolewska on Medium]]></title>
        <description><![CDATA[Stories by Hanna Sobolewska on Medium]]></description>
        <link>https://medium.com/@hanna.sobolewska?source=rss-c7a039345e64------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*z2PvY3t0R6rwSVxa</url>
            <title>Stories by Hanna Sobolewska on Medium</title>
            <link>https://medium.com/@hanna.sobolewska?source=rss-c7a039345e64------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 08:55:59 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@hanna.sobolewska/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[React Native EU 2023 and a Glimpse Into Conference History]]></title>
            <link>https://medium.com/call-stack/react-native-eu-2023-and-a-glimpse-into-conference-history-30974c3e6f1d?source=rss-c7a039345e64------2</link>
            <guid isPermaLink="false">https://medium.com/p/30974c3e6f1d</guid>
            <category><![CDATA[community]]></category>
            <category><![CDATA[react-native-conference]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[react-native-eu]]></category>
            <dc:creator><![CDATA[Hanna Sobolewska]]></dc:creator>
            <pubDate>Fri, 17 Mar 2023 10:34:20 GMT</pubDate>
            <atom:updated>2023-03-17T10:35:58.198Z</atom:updated>
            <content:encoded><![CDATA[<p>by <a href="https://www.callstack.com/blog-author/aleksandra-pytko-wlodarczyk">Aleksandra Pytko-Włodarczyk</a></p><figure><img alt="post-conference picture of attendees" src="https://cdn-images-1.medium.com/max/1024/1*k4xEnuqrBaPLJSAf9Phuig.jpeg" /></figure><p>Do you ever get a feeling that time flies even faster these days? We sure do, and we bet September will come sooner than we think, so it’s time for a big announcement: <strong>React Native EU is back for a 100% in-person edition</strong>!</p><p>This year, we’re meeting on September 7–8 at Wrocław Congress Center in Poland, just like we did in the old days. The date might deem distant now, but before you know it, spring and summer will pass, so why not <a href="https://www.react-native.eu/?utm_campaign=React_Native_EU&amp;utm_source=Callstack_website&amp;utm_medium=blog&amp;utm_content=RNEU2023_history">save your spot now at a discount price</a>? There are 8 blind birds tickets left, so don’t think too long.</p><p>Some of you might not be familiar with or haven’t had a chance to attend React Native EU yet, though. So before we shed more light on the 2023 edition, let us explain why it’s a go-to event for React Native developers and how it evolved over the years.</p><h3>What does React Native EU stand for?</h3><p>Our React Native conference is the biggest community-driven event of this kind in Europe. Every September, <strong>we give top software development experts the floor to discuss hot topics in the React Native world, from recent tech trends to case studies</strong>. The best part is that as the participant, you get to not only listen to but also network with the speakers — and there’s no better way to learn than through interaction.</p><p>Among the things that set React Native EU apart are:</p><ul><li><strong>Full focus on React Native.</strong> You won’t find there web, backend, or general-purpose talks. But if you’re looking for expert experience-based React Native insights, you’ve come to the right place.</li><li><strong>Expert speakers. </strong>Attending our conference, you get to meet and learn from the biggest names in the React Native community. Every year, we invite speakers from Meta, Microsoft, Stripe, Shopify, and other companies that live and breathe this technology.</li></ul><figure><img alt="panel of experts sitting and talking on stage" src="https://cdn-images-1.medium.com/max/1024/1*A-CKLPgZfcS_zbvEczzHFA.jpeg" /></figure><ul><li><strong>Practical tech content. </strong>Our speakers solve all sorts of complex problems with React Native at work, and they’re here to share lessons learned with you. Don’t take our word for it, and <a href="https://www.react-native.eu/all-talks?utm_campaign=React_Native_EU&amp;utm_source=Callstack_website&amp;utm_medium=blog&amp;utm_content=RNEU2023_history">check out talks from previous editions</a>.</li><li><strong>Opportunity to meet Core Contributors. </strong>Among our speakers, you’ll find the creators and maintainers of important libraries and projects. The presence of Core Contributors makes React Native EU a perfect place to learn about the latest development and most promising trends.</li><li><strong>Networking with like-minded attendees. </strong>By attending our React Native conference, you become a part of the community. You get to create it and develop meaningful relationships with people of similar interests from all over the world.</li></ul><figure><img alt="group of people talking" src="https://cdn-images-1.medium.com/max/1024/0*q_hxD-0KMKNQYJ8k.jpg" /></figure><ul><li><strong>The atmosphere and entertainment. </strong>At React Native EU, we work hard and play hard, so you can expect a grand reception and afterparty, local food and drinks, not to mention tourist attractions offered by Wrocław. We can guarantee you won’t get bored, and you’ll make some great memories of the #RNEUvibe.</li></ul><figure><img alt="group of people singing" src="https://cdn-images-1.medium.com/max/1024/0*w9VxMq_nb9wDI_Rp.jpg" /></figure><p>Not that you know what to expect, how about taking a sentimental journey through the conference’s history?</p><h3>A glimpse into React Native EU’s history</h3><p>React Native EU conference was born out of engagement in React Native community, love for <a href="https://www.callstack.com/open-source">Open Source</a>, and the desire to shape the framework’s future direction. To quote <a href="https://www.callstack.com/team/mike-grabowski">Mike Grabowski</a>, Callstack’s cofounder:</p><blockquote>There are lots of tricky things with React Native, partially because of iOS and Android ecosystems. There are lots of unanswered questions hanging around, or just people struggling to find answers for problems that may seem trivial to us. This conference is the place they can visit, get answers to questions and go home start writing their next cool startup.</blockquote><h3>The birth and growth of React Native EU</h3><p>The first three editions of our React Native conference took place on-site in Wrocław, Poland. Back then, meeting in person was to be expected; but soon, the event landscape was about to change.</p><p>React Native EU grew quickly; in 2019, it gathered a record number of 360 attendees. It also quickly proved to deliver top quality in all regards. On the one hand, there was top-notch tech expertise shared by Facebook, Callstack, AutoZone, Expo, and Microsoft experts; on the other, the unparalleled experience shaped by the historic venue, the entertainment (including the legendary karaokes), and other amenities.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fm0GfmlGFh3E%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dm0GfmlGFh3E&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fm0GfmlGFh3E%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/3afa5805a2d913509841822f22c85d44/href">https://medium.com/media/3afa5805a2d913509841822f22c85d44/href</a></iframe><p>2019 also featured the first edition of the <strong>Core Contributor Summit as organized by Callstack</strong>. The event aims at bringing React Native contributors and having them join forces on pushing for the improvement of the technology.</p><figure><img alt="big group of attendees smiling" src="https://cdn-images-1.medium.com/max/1024/0*mmM5nGsnY3O9LJuM.jpeg" /></figure><p>Although the event isn’t a part of React Native EU program, it happens right before the conference. The biggest perk of such timing is that Core Contributors who participate in the summit share knowledge at our conference, allowing attendees to meet and learn from them. This way, <strong>developers taking part in RNEU can get inspired, learn from, and simply hang out with the people behind the technology they’re using on a daily basis</strong>.</p><h3>Moving online: React Native EU in 2020 and 2021</h3><p>2020 was a year like no other for obvious reasons. As the pandemic hit, the world shifted to online, and so did our conference. This way, we <strong>could give React Native enthusiasts an opportunity to learn and network with fellow developers regardless of travel restrictions</strong>. The location changed, but our core values remained the same. As always, the 2020 and 2021 virtual editions were focused on the community, core contributors, and high-quality practical tech insights.</p><p>The biggest advantage of <a href="https://www.callstack.com/blog/react-native-eu-2020-virtual-edition-summary">going online</a> was undoubtedly the <strong>unprecedented scale of the event</strong>. As the distance was no longer an issue, we welcomed thousands of attendees from all around the globe, from the USA, UK, and France to Turkey and Brazil. In 2021, the number of guests rose to eight thousand, which was pretty impressive for both Callstack as organizers and the attendees, who got to meet even more like-minded individuals!</p><p>Even though our attendees could not high-five each other in person, they had <strong>plenty of networking opportunities thanks to a dedicated conference Discord channel</strong>. That’s where speakers hang out and heated Q&amp;A debates took place. To give back to this part of the community that didn’t make it to the 2020 edition, we published <a href="https://www.callstack.com/blog/qa-sessions-from-react-native-eu-2020">the most interesting questions and answers on our blog</a>.</p><h3>One foot online and one foot in Wrocław: hybrid RNEU 2022</h3><p>2022 marked yet another turn in React Native EU history. As the world was slowly getting over the pandemic, we decided to hold a hybrid event: we invited the public to participate online, welcomed most speakers and Callstackers in person, and brought the <a href="https://reactnative.dev/blog/2022/11/22/react-native-core-contributor-summit-2022">Core Contributor Summit</a> back to Wrocław. This reminded us of the best part of attending conferences as we used to know them: <strong>having a chance to hang out and have fun together</strong>.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FYlo_DNPO4-o%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DYlo_DNPO4-o&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FYlo_DNPO4-o%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/c4dc950336748e054967139bafbac8ce/href">https://medium.com/media/c4dc950336748e054967139bafbac8ce/href</a></iframe><p>Here’s how <a href="https://www.callstack.com/team/lukasz-chludzinski">Łukasz Chludziński</a>, the host of <a href="https://www.callstack.com/podcast-react-native-show">React Native Show Podcast</a>, remembers last year’s conference:</p><blockquote>2022 edition was my first time as a full-time host, and being there in person felt awesome. Even though it was a hybrid event, you could feel that those who joined us were hungry for talking, meeting, and learning. The energy was great, and I can’t wait to feel it this year when everybody’s once again in Wrocław.</blockquote><h3>Moving back to Wrocław: React Native EU 2023</h3><p>This year, our React Native conference returns to its roots: a fully on-site edition taking place on September 7–8 in Wrocław. <strong>Tickets are already on sale, and you can </strong><a href="https://www.react-native.eu/?utm_campaign=React_Native_EU&amp;utm_source=Callstack_website&amp;utm_medium=blog&amp;utm_content=RNEU2023_history"><strong>buy them on React Native EU website</strong></a><strong> at a hefty discount.</strong></p><figure><img alt="React Native EU conference banner" src="https://cdn-images-1.medium.com/max/658/0*JKqQ9aJepZpXp2EK.png" /></figure><p>The big reveals are yet to come, but here’s what you expect for sure from React Native EU 2023:</p><ul><li><strong>React Native Superstars speakers</strong>, discussing real-life case studies and recent development in technology. We’ll let you know about the lineup in spring, but trust us; you should be already excited.</li><li><strong>High-tech content only</strong>, laser-focused on various aspects of React Native, from performance and UX to testing and native aspects.</li><li><strong>Networking as we used to know it before the pandemic</strong>: in-person, with plenty of opportunities to get to know the attendees as React Native development experts and simply cool people to hang out with.</li><li><strong>Wrocław as the ultimate meeting place.</strong> Our venue will be once again the historical building of Centennial Hall, in the close vicinity of the famous Pergola, Szczytnicki Park, and Japanese Garden. And after the talks, you’re free to explore the vibrant city of Wrocław and its attractions.</li><li><strong>The unique #RNEUvibe.</strong> What do we mean by that? The after party, karaoke, chill-out zone, local food and drinks… It’s impossible to put into words, but once you experience it, you’ll want to go back year by year.</li></ul><p>Most of all, the on-site edition is an opportunity for us to contribute to the community revival after three years of primarily offline meetings. We aim to <strong>give you all a chance to mingle and strengthen relationships right at the center of Europe</strong> — and we can’t wait for that to happen!</p><figure><img alt="post-conference picture of attendees" src="https://cdn-images-1.medium.com/max/1024/0*EXRoRzgRlvrMOLR0.jpg" /></figure><p>Call for papers is opening soon, and we’re waiting for you to discuss React Native topics dear to your heart. If you’re excited about sharing high-tech insights with fellow developers, <a href="https://www.react-native.eu/#callforpapers">subscribe to our conference newsletter</a> and be the first to know about the CFP opening.</p><h3>Save your spot for React Native EU 2023</h3><p>Are you as excited about sharing React Native knowledge and learning from industry thought-leaders as we are? If so, <a href="https://ti.to/react-native-eu/2023">buy your ticket now</a> and save your spot for React Native EU 2023! We can’t wait to welcome you to Wrocław ❤️️</p><p><em>This article was originally published at </em><a href="https://www.callstack.com/blog/react-native-eu-glimpse-into-conference-history"><em>callstack.com</em></a><em> on March 1, 2023.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=30974c3e6f1d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/call-stack/react-native-eu-2023-and-a-glimpse-into-conference-history-30974c3e6f1d">React Native EU 2023 and a Glimpse Into Conference History</a> was originally published in <a href="https://medium.com/call-stack">Callstack Engineers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Experiment With the New Architecture of React Native]]></title>
            <link>https://medium.com/call-stack/experiment-with-the-new-architecture-of-react-native-9dfc03803adc?source=rss-c7a039345e64------2</link>
            <guid isPermaLink="false">https://medium.com/p/9dfc03803adc</guid>
            <category><![CDATA[new-architecture]]></category>
            <category><![CDATA[react-native]]></category>
            <dc:creator><![CDATA[Hanna Sobolewska]]></dc:creator>
            <pubDate>Mon, 27 Feb 2023 15:12:11 GMT</pubDate>
            <atom:updated>2023-02-27T15:17:20.182Z</atom:updated>
            <content:encoded><![CDATA[<p>by <a href="https://www.callstack.com/blog-author/oskar-kwasniewski">Oskar Kwaśniewski</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ps8dmuUoQcegodBg9SUV0A.jpeg" /></figure><p>The following article is part of <a href="https://www.callstack.com/campaigns/download-the-ultimate-guide-to-react-native-optimization">The Ultimate Guide to React Native Optimization</a>. Including valuable insights from React Native Core Team, it explains the benefits of experimenting with the New Architecture of React Native early on.</p><p><strong>Why is this important?</strong></p><p>It might be that your app is using an old architecture without the concurrent features of React 18. Or perhaps it’s better to say “current” architecture since it’s still mostly used by production apps. Either way, if you went for New Architecture, you could be leveraging the capabilities of the new rendering system inside your app — and this could greatly benefit your product and improve business results. In this blog post, we’re going to explain what New Architecture is and how it can improve your React Native project.</p><p>In other blog posts based on The Ultimate Guide to React Native Optimization, we touch on the following performance-related topics:</p><ul><li><a href="https://www.callstack.com/blog/optimize-android-application-size-with-gradle-settings">Optimizing your Android application’s size with Gradle Settings</a></li><li><a href="https://callstack.com/blog/optimize-android-app-startup-time-with-hermes/">Optimizing your Android app startup time with Hermes</a></li><li><a href="https://www.callstack.com/blog/automate-dependency-management-with-autolinking">Automating your dependency management with `Autolinking`</a></li><li><a href="https://callstack.com/blog/how-to-debug-faster-and-better-with-flipper/">Debugging faster and better with Flipper</a></li><li><a href="https://www.callstack.com/blog/always-run-the-latest-version-of-react-native">Why Is It Essential to Always Run The Latest Version of React Native?</a></li></ul><p>Check them out! Now let’s jump into the main topic.</p><h3>Old vs. New Architecture</h3><p>Both new and old architecture are based on the communication between JavaScript and the native side. Currently, this communication is handled by the bridge. Let’s go over its limitations to understand better the problems that the New Architecture is trying to solve:</p><ul><li>It is asynchronous: the JavaScript side submits data to a bridge and waits for the data to be processed by the native side.</li><li>It’s single-threaded, so it’s important not to overload the JS thread and execute animations on the UI thread.</li><li>It adds additional overhead when it comes to the serialization of data from JSON objects.</li></ul><p>The bridge is still working fine for most use cases. However, when we start to send a lot of data over the bridge, it may become a bottleneck for our app. This issue can be seen when rendering a lot of components in a long list. When the user scrolls fast, there will be a blank space caused by the communication between the JS and native sides being asynchronous. Essentially, we are having a “traffic jam” on our bridge with objects waiting to be serialized. The same issue with the bridge being “overloaded” can be seen in <a href="https://www.callstack.com/training/working-with-native-modules">native modules</a> sending a lot of data back and forth.</p><p>This bottleneck, together with providing a type-safe way of communicating between native and JS, are the main things that the new architecture is trying to solve. However, not everything about new architecture is as good as it may seem. We will also get into the drawbacks that it brings.</p><h3>What is New Architecture?</h3><p>Starting from React Native 0.68, developers can leverage new capabilities of the framework. The <a href="https://www.callstack.com/blog/migrating-a-react-native-library-to-the-new-architecture">New Architecture</a> relies on a series of tools, which are key components to the new experience.</p><p>Two most important ones are Fabric and TurboModules. The first one is a new rendering system, and the second one is a new way of writing native modules. We will get into details later in this section.</p><p>Codegen and JSI are two new tools improving the developer experience. They are essential to understand how the new architecture works. Codegen drastically improves DX by generating a lot of native boilerplate code and ensuring type safety. And JSI, a C++ API for interacting with any JS engine.</p><p>Note: Prior to React Native v0.71+ it’s possible but way harder to deploy the New Architecture in an app. So that’s the version we are suggesting for you to upgrade.</p><h3>Codegen</h3><p>A code generation tool that makes JS a source of truth by automating the compatibility between JS and the native side. It allows writing statically typed JS (called JS Spec), which is then used to generate the interface files needed by Fabric native components and TurboModules. Spec consists of a set of types written in TypeScript or Flow that defines all the APIs provided by the native module.</p><p><strong>Codegen ensures type-safety and compile-time type safety, which means</strong> <strong>smaller code and faster execution</strong> as both realms can trust each other around validating the data every time. To find out more about it, refer to the <a href="https://reactnative.dev/docs/new-architecture-library-intro#writing-the-javascript-spec">docs</a>.</p><h3>JSI</h3><p>JSI is the foundation of the New Architecture, a C++ API for interacting with any JS engine. In contrast to the bridge, which was asynchronous, <strong>JSI is synchronous, which allows for invoking native functions faster</strong>. It lets JavaScript hold references to C++ host objects and invoke methods directly on them. This removes the major overhead of asynchronous communication between JS and native by serializing objects using the bridge.</p><h3>Fabric</h3><p>Fabric is React Native’s new concurrent rendering system, a conceptual evolution of the legacy render system. The core principle is to unify more render logic in C++ to better leverage interoperability between platforms. Host Components like View, Text, etc. are now lazily initialized, resulting in faster startups. <strong>Fabric allows us to take advantage of the features introduced in React 18</strong>.</p><h3>TurboModules</h3><p>This is a new way of writing native modules that also leverages the power of JSI, <strong>allowing for synchronous and an order of magnitude faster data transfer from native to JS and vice versa</strong>.</p><p>It is a rewrite of the communication layer between JavaScript and platform native modules like Bluetooth, Biometrics, etc. It also allows for writing native code for both platforms using C++ and introduces the lazy loading of modules to speed up your app startup time.</p><h3>Bridgeless mode</h3><p>For the time being, React Native is not removing the bridge completely; it’s still there, allowing developers to gradually adopt new architecture and JSI. However, usage of the bridge needs to be explicitly stated (by importing it), so not yet migrated modules won’t work.</p><p>Meta is planning to soon allow apps to run in completely bridge-less mode, which will result in faster app startup due to removing the overhead of loading the bridge every time the app starts.</p><h3>How to turn on New Architecture</h3><p>To turn on the New Architecture in your app, you need to update your app to at least React Native 0.68; however, we recommend upgrading to at least React Native 0.71+ because a lot of improvements have been added.</p><p>To migrate your app to the New Architecture, follow these steps:</p><ol><li>Upgrade your app to at least React Native 0.71+, you can use <a href="https://react-native-community.github.io/upgrade-helper/">https://react-native-community.github.io/upgrade-helper/</a></li><li>Check all third-party libraries that your app depends on; the important thing is that <strong>all of them need to be migrated</strong>! This might be a long-time blocker for a lot of apps out there. Components that are not yet compatible will show a red box — Unimplemented component: &lt;ComponentName&gt; — and you will likely notice them. In that case, please let the library maintainers know about it, as this will speed up the adoption.</li><li>[Android] Set newArchEnabled=true in gradle.properties.</li><li>[iOS] Run RCT_NEW_ARCH_ENABLED=1 pod install inside the iOS folder.</li></ol><h3>Benefits of moving React Native app to New Architecture</h3><p>Now that you know how New Architecture works, let’s go over its benefits.</p><h3>Performance</h3><p>Due to the synchronous nature of the new architecture, while communicating with the native side, there will be some performance improvements. <strong>The app’s startup time will be significantly reduced as every native module will be lazily-loaded</strong>. Once the bridgeless mode is available, it will also remove the overhead of loading the bridge at startup. However, not every scenario proves this; in some of the benchmarks, architecture performance is worse.</p><p>Meta’s goal was not to make new architecture X times faster than the old one. Apart from removing major bottlenecks, they wanted to create a new solid foundation, allowing for new capabilities that could not be developed using previous architecture. Migration of the Facebook app took over a year, and they haven’t noticed any significant performance improvements or regressions that are perceivable by the end user. However, this doesn’t mean that performance improvements won’t come in the future. Now that they reworked internals, they have a great foundation to build upon.</p><p>Let’s go over some performance benchmarks by <a href="https://github.com/Almouro">Alexandre Moureaux</a> from BAM. Here is a link to the source: <a href="https://github.com/reactwg/react-native-new-architecture/discussions/85">https://github.com/reactwg/react-native-new-architecture/discussions/85</a></p><h4>Benchmark of rendering 10K views</h4><p>In this case, new architecture proves more efficient than the old one. Using on average less CPU but more RAM.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/0*KVZkGYuY0_0TbV8j.png" /></figure><h4>Benchmark of rendering 2K Text components</h4><p>The old architecture is faster in this scenario because of heavier UI thread consumption.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*18dod56SO4MVHxvk.png" /></figure><p>The official response from the React Native team is that their internal benchmarks while rolling out the New Architecture to users were neutral across all React Native surfaces in the Facebook app on both Android and iOS. As stated by Samuel Susla in <a href="https://github.com/reactwg/react-native-new-architecture/discussions/85#discussioncomment-3969000">this discussion thread</a>, “In the last years, we conducted dozens of tests in production on millions of devices to assure performance was neutral.”</p><p>So in most use cases, <strong>you can expect a neutral performance impact without any performance regressions</strong>. And keep in mind that the New Architecture is getting better every single day, with many developers contributing to the repository, so the results may be totally different by the time you are reading this.</p><h3>Future readiness</h3><p><a href="https://www.callstack.com/podcasts/react-native-new-architecture-ep-17">New Architecture</a> allows your app to leverage Concurrent React features. This improves UI responsiveness, provides Suspense for data fetching to handle complex UI loading schemes, and ensures your app is ready for any further React innovations built on top of its new concurrent engine introduced in React 18.</p><p>Let’s see how we can leverage React18’s startTransition API to prioritize between two state updates. In our example, a button click can be considered an urgent update, whereas the NonUrgentUI can be considered a non-urgent update. To tell React about a non-urgent update, we can wrap the setState in the startTransition API. This allows React to prepare a new UI and show the old UI until a new one is prepared.</p><p>In our example, we wrapped setNonUrgentValue in start-Transition and told React that nonUrgentValue is a transition and not so urgent, it may take some time. We’ve also added a conditional backgroundColor. When you run this example, you will see that once you click on the button, the view will retain its old UI, e.g., if we start at value 1, the UI will be green.</p><p>Once you click on the button, the Value text UI will be updated, but the UI for the container will remain green until the transition is completed, and the color will change to red due to the new UI being rendered. That’s the magic of React’s concurrent rendering.</p><p>To understand it better, assume that wrapping an update in startTransition renders it in a different universe. We don’t see that universe directly, but we can get a signal from it using the isPending variable returned from the useTransition hook. Once the new UI is ready, both universes merge together to show the final UI.</p><pre>import React from &quot;react&quot;;<br>import { Button, StyleSheet, Text, View } from &quot;react-native&quot;;<br>const dummyData = Array(10000).fill(1);<br>const NonUrgentUI = ({ value, isPending }) =&gt; {<br>  const backgroundStyle = {<br>    backgroundColor: value % 2 === 0 ? &quot;red&quot; : &quot;green&quot;,<br>  };<br>  return (<br>    &lt;View&gt;<br>      &lt;Text&gt;Non urgent update value: {isPending ? &quot;PENDING&quot; : value}&lt;/Text&gt;<br>      &lt;View style={[styles.container, backgroundStyle]}&gt;<br>        {dummyData.map((_, index) =&gt; (<br>          &lt;View key={index} style={styles.item} /&gt;<br>        ))}<br>      &lt;/View&gt;<br>    &lt;/View&gt;<br>  );<br>};<br>const ConcurrentStartTransition = () =&gt; {<br>  const [value, setValue] = React.useState(1);<br>  const [nonUrgentValue, setNonUrgentValue] = React.useState(1);<br>  const [isPending, startTransition] = React.useTransition();<br>  const handleClick = () =&gt; {<br>    const newValue = value + 1;<br>    setValue(newValue);<br>    startTransition(() =&gt; {<br>      setNonUrgentValue(newValue);<br>    });<br>  };<br>  return (<br>    &lt;View&gt;<br>      &lt;Button onPress={handleClick} title=&quot;Increment value&quot; /&gt;<br>      &lt;Text&gt;Value: {value}&lt;/Text&gt;<br>      &lt;NonUrgentUI value={nonUrgentValue} isPending={isPending} /&gt;<br>    &lt;/View&gt;<br>  );<br>};<br>export default ConcurrentStartTransition;<br>const styles = StyleSheet.create({<br>  container: {<br>    flexDirection: &quot;row&quot;,<br>    flexWrap: &quot;wrap&quot;,<br>  },<br>  item: {<br>    width: 10,<br>    height: 10,<br>  },<br>});</pre><p><a href="https://gist.github.com/pytqqq/05dad67523f113844ff4c5627752f4e5#file-show-the-final-ui-tsx">Show the final UI.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>To understand it better, let’s visualize the code snippet we just went through. The image below shows a comparison of when we use startTransition and when we don’t. Looking at the image, we see that React flushes the urgent update right off, which happens due to calling setValue without wrapping it in startTransition.</p><p>Next, we see that React shows the old UI (viewed in green) for the UI that depends on the nonurgent updates, which means the updates that are wrapped in startTransition. We also see a <strong><em>Pending</em></strong> text displayed; this is a way for React18 to tell us that the new UI depending on this state is not yet ready. Once it’s ready, React flushes it and we don’t see the <strong><em>Pending</em></strong> text anymore, and the view color changes to red.</p><p>On the other hand, if we don’t use startTransition, React tries to handle both updates as urgent and flushes once both are ready. This certainly has a few downsides, such as the app trying to render some heavy UI all at once, which may cause jarring effects for the users. With React18, we can handle this by delaying the updates that are not urgent.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xb7LOxWMqwXa6ojs.png" /></figure><p>There are some other noticeable features in React18 that you might want to check out by playing with the linked sandboxes from React’s official website. See <a href="https://codesandbox.io/s/jovial-frost-30embe">useDeferredValue</a> and <a href="https://codesandbox.io/s/nice-shaw-k6t10j?file=/src/index.js">startTransition with Suspense</a>.</p><h3>Maintenance &amp; Support</h3><p>The React Native core team is committed to offer support for the 3 latest versions of React Native (you can check the support policy <a href="https://github.com/reactwg/react-native-releases#releases-support-policy">here</a>) and the React core team plans new features built on the concurrent rendering engine.<strong> It’s important to not stay behind, as the cost of paying the tech debt, will get higher in time.</strong> It’s worth calling out that React Native is no different to any other software project in this regard. Not updating dependencies may not only cause your team to spend more time on this task when it’s unavoidable. It can also expose your app to security vulnerabilities already patched in the upstream.</p><p>The React Native team has dedicated capacity to help the community solve their app and library problems regarding new architecture adoption in close cooperation. Although it’s not stable yet, it’s worth considering starting to plan your migration early on, so you can identify the problems and blockers that your app may be facing. 2023 is the best time to try it, evaluate, ask for support, and give feedback.</p><p>You can get a head start with fine support from the React Native core engineers in solving your app’s build and runtime issues preventing you from migration. Once the new architecture gets stable and turned on by default, the core team will surely focus on the further development of React Native, and hence the migration support time will be reduced.</p><h3>Need help with performance? Give us a shout!</h3><p>If you’re struggling with improving your app performance, get in touch with us. Our <a href="https://www.callstack.com/react-native-development-company">React Native development company</a> is an official Meta partner and community leader. We’ve delivered high-quality solutions for dozens of international clients, from startups to enterprises, and created some cool Open Source projects like <a href="https://www.callstack.com/open-source/re-pack">Re.Pack</a> or <a href="https://www.callstack.com/open-source/reassure">Reassure</a>. Now’s the time we help your business grow.</p><p><em>This article was originally published at </em><a href="https://www.callstack.com/blog/experiment-with-new-architecture-of-react-native"><em>callstack.com</em></a><em> on February 14, 2023.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9dfc03803adc" width="1" height="1" alt=""><hr><p><a href="https://medium.com/call-stack/experiment-with-the-new-architecture-of-react-native-9dfc03803adc">Experiment With the New Architecture of React Native</a> was originally published in <a href="https://medium.com/call-stack">Callstack Engineers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Optimize Your React Native App’s JavaScript Bundle]]></title>
            <link>https://medium.com/call-stack/optimize-your-react-native-apps-javascript-bundle-f8303a355568?source=rss-c7a039345e64------2</link>
            <guid isPermaLink="false">https://medium.com/p/f8303a355568</guid>
            <category><![CDATA[react-native]]></category>
            <dc:creator><![CDATA[Hanna Sobolewska]]></dc:creator>
            <pubDate>Fri, 24 Feb 2023 17:14:35 GMT</pubDate>
            <atom:updated>2023-02-24T17:14:35.334Z</atom:updated>
            <content:encoded><![CDATA[<p>by <a href="https://www.callstack.com/blog-author/jakub-binda">Jakub Binda</a> &amp; <a href="https://www.callstack.com/blog-author/andrew-andilevko">Andrew Andilevko</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E-kDAMD1-cSegQyH3yJo3g.jpeg" /></figure><p>The following article is part of <a href="https://www.callstack.com/campaigns/download-the-ultimate-guide-to-react-native-optimization">The Ultimate Guide to React Native Optimization</a> and explains how you can optimize your React Native app’s performance using different bundlers, like Re.Pack, `react-native-esbuild,` and `rnx-kit.`</p><p><strong>Why is this important?</strong></p><p>React Native application’s logic is mostly located in the JavaScript code, which runs in the JavaScript engine (JavaScriptCore or Hermes). But before loading JavaScript code into the app, it should be bundled, usually into a single JS file or sometimes to multiple files. React Native provides a built-in tool for JavaScript code bundling called <a href="https://facebook.github.io/metro/">Metro</a>. Sometimes, though, the final bundle becomes too large — and that’s where performance issues begin.</p><p>In other blog posts based on The Ultimate Guide to React Native Optimization, we touch on the following topics related to improving performance through understanding the React Native implementation details:</p><ul><li><a href="https://www.callstack.com/blog/external-javascript-libraries-for-react-native">Picking the right external libraries for your app</a></li><li><a href="https://www.callstack.com/blog/optimize-battery-drain-in-react-native-apps">Optimizing battery drain with mobile-dedicated libraries</a></li><li><a href="https://callstack.com/blog/find-the-balance-between-native-and-javascript/">Finding the balance between native and JavaScript</a></li><li><a href="https://www.callstack.com/blog/60fps-animations-in-react-native">Animating at 60FPS</a></li><li><a href="https://www.callstack.com/blog/improve-react-native-performance-with-higher-ordered-components">Improving React Native performance with high-order components</a></li></ul><p>Be sure to check them out later. Now, let’s move on to the topic of optimizing your React Native app’s JavaScript bundle.</p><h3>Using alternative bundlers to optimize performance</h3><p>Metro takes in an entry file and various options and gives you back a single JavaScript file that includes all your code and its dependencies, also known as a JavaScript bundle. According to official docs, Metro speeds up builds using a local cache of transformed modules out-of-the-box.</p><p><strong>Metro trades configurability for performance, whereas other bundles like </strong><a href="https://webpack.js.org/"><strong>Webpack</strong></a><strong> are the other way around. </strong>So when your project needs custom loaders, use symlinks or the proven Webpack configuration for bundling JavaScript code and splitting app logic.</p><p>There are a few alternative bundlers that could be used in React Native apps and provide more configuration features. In this article, we’ll take a closer look at Re.Pack, `react-native-esbuild,` and `rnx-kit` and consider their benefits and limitations.</p><h3>Re.Pack</h3><p><a href="https://www.callstack.com/open-source/re-pack">Re.Pack</a> is a Webpack-based toolkit to build your React Native application with full support of the Webpack ecosystem of loaders, plugins, and support for various features like symlinks, aliases, <a href="https://www.callstack.com/blog/implementing-code-splitting-in-react-native-with-re-pack">code splitting</a>, etc. It is the successor to Haul, which served a similar purpose but balanced a different set of tradeoffs and developer experience. By the way, we’re proud to say that Re.Pack it brought to you by our <a href="https://www.callstack.com/react-native-development-company">React Native development company</a> — and we put in every effort to make it as valuable and developer-friendly as possible.</p><h4>Benefits of using Re-Pack in your React Native project</h4><p>The ecosystem part of Webpack is crucial for many developers, since it’s the most popular bundler on the web, making the community behind loaders and plugins its key advantage. <strong>Thanks to that pluggability, it provides ways to improve the build process and Webpack’s overall performance</strong>. At least for the parts that are not connected to the internal module graph building and processing. Such parts would be, e.g., JavaScript and TypeScript transpilation or code minification. You can replace Babel transpiler and Terser minifier with faster alternatives like <a href="https://esbuild.github.io/">ESBuild</a> thanks to the <a href="https://github.com/esbuild-kit/esbuild-loader">esbuild-loader</a> or swc with <a href="https://swc.rs/docs/usage/swc-loader">swc-loader</a>.</p><p>Another Webpack feature that <strong>helps our apps achieve better performance is reducing the amount of code in the final bundle with tree shaking</strong>. Tree shaking is a dead code elimination technique done by analyzing the import and export statements in the source code and determining which code is actually used by the application. Webpack will remove unused code from the final bundle, resulting in a smaller and more efficient application. The code that’s eligible for tree shaking needs to be written in ECMAScript modules (import and export statements) and mark itself as <a href="https://github.com/webpack/webpack/blob/main/examples/side-effects/README.md">side-effect free</a> through `package.json sideEffects: false` clause.</p><p>The <a href="https://github.com/facebook/metro/issues/1">very first issue</a> on Metro bundler’s GitHub is about symlink support. It remains open today, as there are various reasons Metro is blocked from introducing this functionality with the desired DX. There are ways to mitigate that particular shortcoming, but they require extra configuration. Webpack, on the other hand, as virtually any other bundler, and doesn’t have this issue.<strong> Re.Pack uses the Webpack bundler under the hood, so it provides symlinks functionality out-of-the-box</strong>, which could be invaluable from the developer experience point of view of some workflows like monorepos.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FI0PCYQQbJRk%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DI0PCYQQbJRk&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FI0PCYQQbJRk%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/0587ab80ad6c9eae555616134ed3fe47/href">https://medium.com/media/0587ab80ad6c9eae555616134ed3fe47/href</a></iframe><p>Re.Pack also offers the ability to <strong>use asynchronous chunks to split your bundle into multiple files and load them on-demand, which can improve initial loading times</strong> if you’re using the JavaScriptCore engine. However, it won’t provide that much value when used with <a href="https://www.callstack.com/blog/technical-guide-integrating-hermes-with-react-native">Hermes</a>, which leverages the memory mapping technique for dynamic reading only the necessary parts of the bundle’s bytecode directly from the RAM. But there’s a twist to that! Webpack doesn’t really care whether you load the dynamic chunk from the filesystem or remote. Hence, it allows for dynamic loading code that’s never been there in the app bundle in the first place, directly from a remote server or a CDN. Now, this can help you with reducing not only the initial load time, but also the precious app size.</p><p>On top of that, Webpack 5 introduced support for the concept of <a href="https://www.callstack.com/blog/module-federation-with-re-pack-3">Module Federation</a>. It’s a functionality that <strong>allows code-splitting and sharing the split code parts (or chunks) between independent applications</strong>.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FzWQ-WfVxs-8%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DzWQ-WfVxs-8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FzWQ-WfVxs-8%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/26972056c53253cf7b02291273e14d20/href">https://medium.com/media/26972056c53253cf7b02291273e14d20/href</a></iframe><p>It also helps distributed and independent teams to ship large applications faster. Giving them the freedom to choose any UI framework they like and deploy independently while still sharing the same build infrastructure. Re.Pack 3 supports this functionality out-of-the-box.</p><h4>Where Metro works out better than Re.Pack</h4><p>All these configurations and flexibility affect the build process. The <strong>build speed is a little bit longer</strong> than the default Metro bundler due to customization options. Also, the <strong>Fast Refresh functionality is limited</strong> compared to the Metro bundler. The Hot Module Replacement and React Refresh features require the full application to be reloaded with Webpack and Re.Pack, but they are supported by Metro.</p><p>If you don’t need the huge customization that the Webpack ecosystem offers or don’t plan to split your app code, then you may as well keep the default Metro bundler.</p><h3>react-native-esbuild</h3><p>The next bundler that can help you optimize your React Native app’s performance is <a href="https://github.com/oblador/react-native-esbuild">react-native-esbuild</a>, which comes with speed, tree shaking, compatibility, and configurability. Let’s take a closer look at this tool.</p><h4>Why it’s worth considering react-native-esbuild for your React Native project</h4><p>One of the main benefits of <a href="https://github.com/oblador/react-native-esbuild">react-native-esbuild</a> is <strong>fast builds</strong>. It uses the <a href="https://esbuild.github.io/">ESBuild bundler</a> under the hood, which greatly improves bundling performance even without caching. It also provides some features like tree shaking and is much more configurable compared to the Metro bundler.</p><p>ESBuild has its own ecosystem with plugins, custom transformers, and env variables. This loader is enabled by default for `.ts,` `.tsx,` `.mts,` and `.cts` files, which means <strong>ESBuild has built-in support for parsing TypeScript syntax and discarding the type annotations</strong>. However, ESBuild does not do any type checking, so you will still need to run type check in parallel with ESBuild to check types. This is not something ESBuild does itself.</p><h4>The drawbacks of react-native-esbuild</h4><p>Unfortunately, `react-native-esbuild` has some tradeoffs, so it is very important to select the right bundler by paying attention to them as well. <strong>It doesn’t support Hermes</strong>, which could be a crucial point for some projects. And <strong>it does not have Fast Refresh or Hot Module Replacement</strong>, but this library supports live reload instead.</p><h3>rnx-kit</h3><p>Last but not least, we’d like to discuss Microsoft’s <a href="https://microsoft.github.io/rnx-kit/">rnx-kit</a>. It’s an interesting extension to Metro. `rnx-kit` is a package with a huge variety of scalable React Native development tools. It also has a custom bundler that works on top of the Metro bundler, enhancing it.</p><h4>The pros of enhancing Metro with rnx-kit</h4><p>As you already know, Metro does not support symlinks. `rnx-kit` provides the ability to fully work with symlinks. One more benefit compared to Metro is <strong>the tree shaking functionality out-of-the-box</strong>.</p><p>Metro supports TypeScript source files, but it only transpiles them to JavaScript. Metro does not do any type-checking. `rnx-kit` solves this problem. Through the configuration, <strong>you can enable type-checking</strong>. Warnings and errors from TypeScript appear on the console.</p><p>Also, `rnx-kit` <strong>provides duplicate dependencies and cyclic dependencies detection out-of-the-box</strong>. This could be very useful in reducing the size of the bundle, which leads to better performance and prevents cyclic dependencies issues.</p><h3>Ship less JavaScript to users and save devs’ time when bundling</h3><p>The choice of a bundle tool depends on the specific case. It is impossible to select only one bundler for all the apps. If you need customization options provided by the Webpack ecosystem or plan to split your app code, then we would suggest using Re.Pack for its widely customizable configuration, a huge amount of loaders, plugins maintained by the community, and a lot of features like symlinks, aliases, etc. compared to other bundle tools.</p><p>If the Webpack ecosystem feels overhead, then it is better to stay with the default Metro bundler or try to use other bundler options like `react-native-esbuild` and `rnx-kit,` which also provides some benefits like decreased build time, using esbuild under the hood, symlinks, and typescript support out-of-the-box. But be careful and always pay attention to the tradeoffs that come with a new bundling system.‍</p><p>If you need help with performance, stability, user experience, or other complex issues, <a href="https://www.callstack.com/contact-us">contact us</a>! As React Native Core Contributors and active <a href="https://www.callstack.com/open-source">Open Source contributors</a>, we will be happy to help.</p><p><em>This article was originally published at </em><a href="https://www.callstack.com/blog/optimize-react-native-apps-javascript-bundle"><em>callstack.com</em></a><em> on February 13, 2023.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f8303a355568" width="1" height="1" alt=""><hr><p><a href="https://medium.com/call-stack/optimize-your-react-native-apps-javascript-bundle-f8303a355568">Optimize Your React Native App’s JavaScript Bundle</a> was originally published in <a href="https://medium.com/call-stack">Callstack Engineers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Profiling React Native Apps With iOS and Android Tools]]></title>
            <link>https://medium.com/call-stack/profiling-react-native-apps-with-ios-and-android-tools-16580ba8247c?source=rss-c7a039345e64------2</link>
            <guid isPermaLink="false">https://medium.com/p/16580ba8247c</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Hanna Sobolewska]]></dc:creator>
            <pubDate>Thu, 23 Feb 2023 14:11:15 GMT</pubDate>
            <atom:updated>2023-02-24T16:50:43.495Z</atom:updated>
            <content:encoded><![CDATA[<p>by <a href="https://www.callstack.com/blog-author/piotr-trocki">Piotr Trocki</a> &amp; <a href="https://www.callstack.com/blog-author/eduardo-graciano">Eduardo Graciano</a></p><figure><img alt="developer coding on desktop and mobile" src="https://cdn-images-1.medium.com/max/1024/1*gp5wCgt68ncmwmwDmWr3ZA.jpeg" /></figure><p>The following article is a part of <a href="https://callstack.com/blog/the-ultimate-guide-to-react-native-optimization/">The Ultimate Guide to React Native Optimization</a> and describes React Native profiling on iOS and Android.</p><p><strong>Why is this important?</strong></p><p>With users becoming more sensitive to delays, even a 0.1 sec of improvement can increase your conversion rate by 10.1%. That’s why profiling has become one of the main steps in our development life cycle. Using the right profiling tools allows for spotting the source of performance problems and makes it easier to find a solution that actually makes a difference — and satisfied users mean better business results.</p><p>In other blog posts based on The Ultimate Guide to React Native Optimization, we touch on the following stability-related topics:</p><ul><li><a href="https://www.callstack.com/blog/how-continuous-integration-can-improve-react-native-apps">The role of Continuous Integration (CI) in improving React Native apps</a></li><li><a href="https://www.callstack.com/blog/ship-over-the-air-when-in-an-emergency">Over-The-Air (OTA) updates</a></li><li><a href="https://www.callstack.com/blog/shipping-fast-with-continuous-deployment">Shipping Fast with Continuous Deployment</a></li><li><a href="https://www.callstack.com/blog/consistently-improve-app-performance-with-dmaic-and-reassure">Making your app consistently fast with DMAIC and Reassure</a></li></ul><p>Check them out later, and now let’s jump into the ins and outs of React Native profiling with native tools for iOS and Android.</p><h3>Profiling iOS</h3><p>Profiling is essential to understanding the runtime performance of the app through analysis that measures the memory or time complexity, frequency, and duration of function calls, etc. Getting all this information helps you to track down and provide proper solutions to keep your app healthy and your users engaged.</p><p>Xcode provides some basic tools to do the first report. You can monitor the CPU, Memory, and Network.</p><figure><img alt="CPU, Memory and Network listed" src="https://cdn-images-1.medium.com/max/456/1*4gP2Qo_f4TtLEYmK3I6jLw.png" /></figure><p>CPU Monitor measures the amount of work done. Memory Monitor is for observing the use of the app. All iOS devices use SSD for permanent storage, accessing this data is slower compared to RAM. Disk Monitor is for understanding your app’s disk-writing performance. Network Monitor analyzes your iOS app’s TCP/IP and UDP/IP connections. You can tap on each of them to find more information.</p><p>It also provides an extra monitor that isn’t shown by default but can help you inspect your UI — it’s the View Hierarchy. When the app is running, and you are on the screen you want to inspect, click on Debug View Hierarchy.</p><figure><img alt="Xcode base profiler view" src="https://cdn-images-1.medium.com/max/956/1*FO41vDu23XGJDQutgreW4w.png" /></figure><p>This will show your current UI in a 2D/3D model and the view tree.</p><figure><img alt="tree view of xcode base profiler" src="https://cdn-images-1.medium.com/max/1024/0*D6o_oe_XjUzzsSy0.png" /></figure><p>This will help you to detect overlappings (you can’t see a component) or if you want to flatten your component tree. Even though RN does a view flattening, it sometimes can’t do it with all of them, so here we can do some optimization focusing on specific items.</p><figure><img alt="tree view of Focused" src="https://cdn-images-1.medium.com/max/1024/0*8mmY_yN1Uaf1W7cT.png" /></figure><p>Let’s say we have a TODO list app, and when the Add button is pressed, it adds the new item to the list. However, it takes a couple of seconds to show up on the list because there is some logic before the item is added. Let’s go to our dev toolbox and pick up our first instrument, so we can confirm and measure the delay.</p><h3>Profiling and debugging React Native app with iOS Instruments</h3><p><a href="https://developer.apple.com/videos/play/wwdc2019/411/">Instruments</a> is a debugging and profiling tool that comes prepackaged with Xcode and is literally a box of tools, each serving a different purpose. You choose from a list of templates, and you choose any of them depending on your goal: improving performance or battery life or fixing a memory problem.</p><p>We are going to use Time Profiler. Let’s dive into it. With Xcode open, we go to Open Developer Tool -&gt; Instruments. Then, scroll down to find the Time Profiler tool.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*n9EgSp5WFI11bS9rGq9E7A.png" /></figure><p>It will open a new window. To start profiling your app, click on the drop-down menu and select your device and the app.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/740/0*x4Hw3gbrSncrnNQK.png" /></figure><p>When the app opens, start using it normally, or in this case, add a new TODO item.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*NRfEzg6INNGCVjUI.png" /></figure><p>After playing around and adding the new TODO item, we can see there is a big blue rectangle, which means there is something that is taking a lot of time to finish. Let’s take a look at the threads.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Qche31hk5I0FWzT7.png" /></figure><p>You can expand by pressing option+click over the chevron, which will expand to display useful information. At least for now, it is showing the memory address, but we will need to find another way to find where the problem is.</p><h3>Combining with a tool specific for JS Context tracking</h3><p>Let’s use Flipper and pair it with a monitor called Hermes Debugger (RN). With the app open and running, we go to Flipper, select the running app if not selected already, and go to Hermes Debugger (RN) -&gt; Profiler</p><figure><img alt="Hermes Debugger profiler" src="https://cdn-images-1.medium.com/max/1024/0*COg1rpTRIyNCL0rQ.png" /></figure><p>We click start, so the profiler begins. We do the same flow and actions as before when profiling with Time Profiler. When we stop, we will see all the data collected.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*vY5wFteyBS1m_v77.png" /></figure><p>By default, the data will be sorted bottom-up with the heavy tasks at the top. We can see that a function called doFib is taking ~14 sec to complete, it is a good start, let’s go into that function and see what we can do. The fixes will vary depending on your code.</p><p>After applying a possible fix, we first check Time Profiler again. We click on the record button and start using the app; in our case, let’s add a new TODO item.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*WWjS_6g-dzSdRI_z.png" /></figure><p>As we can see, the fix we applied did work, we aren’t seeing the big blue rectangle like before. This is a good sign. Let’s continue with our profiling path to check how it looks in Flipper.</p><p>Start profiling the app one more time using Hermes Debugger (RN) -&gt; Profiler.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Ndv5Qqh-GbeamIW_.png" /></figure><p>We don’t see the doFib function anymore, only other expected RN tasks.</p><h3>Profiling Android</h3><p>In the event of any performance issues, we mostly use React Profiler to troubleshoot and resolve our problems. Since most of the performance problems originate from the JS realm, we don’t usually need to do anything beyond that. But sometimes, we’ll encounter a bug or performance issue that comes directly from the Android runtime. In such a case, we’ll need a fine profiling tool to help us gather the following metrics from the device:</p><ul><li>CPU</li><li>memory</li><li>network</li><li>battery usage</li></ul><p>Based on that data, we can check whether our app consumes more energy than usual or, in some cases, uses more CPU power than it should. It is useful especially to check the executed code on lower-end (LE) Android devices. Some algorithms can run faster on some devices, and the end user will not spot any glitches, but we have to remember some customers can use LE devices, and the algorithm or function can be too heavy for their phones. High-end devices will handle it because their hardware is powerful.</p><h3>Profiling your React Native app with Android Profiler in Android Studio</h3><p>Android Studio is the IDE developed by JetBrains. It is officially supported by Google and the official IDE, which can be used to develop any Android app. It is very powerful and contains lots of functionalities in one place. One of those tools is Android Profiler, which, as the name suggests, comes in handy if you’re in need of React Native profiling on Android.</p><p>If you have not installed Android Studio yet, you can install it using <a href="https://developer.android.com/studio">this link</a>.</p><p>To open the Profiler, choose View &gt; Tool Windows &gt; Profiler from the Android Studio menu bar:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/974/0*7vHwbkR0vvaxmgqA.png" /></figure><p>Or click Profile in the toolbar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/980/0*cKY2lIGqbl6mdGzZ.png" /></figure><p>Before you start profiling the app, please remember:</p><ul><li>Run the app on an actual Android device that is affected, preferably a lower-end phone or emulator if you don’t have one. If your app has runtime monitoring set up, use a model that is either the most used by users or the one that’s affected by a particular issue.</li><li>Turn off development mode. You must be sure that the app uses a JS bundle instead of the metro server, which provides that bundle. To turn it off, please share your device, click on Settings and find JS Dev Mode:</li></ul><figure><img alt="screenshot JS dev mode" src="https://cdn-images-1.medium.com/max/884/0*gxfG3yz2o1YSiOiz.png" /></figure><p>After that, go to the Profiler tab and add a new profiler session:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*p1g7H3KCqdJOwvl3.png" /></figure><p>Wait for the session to attach to your app and start performing actions that could cause some performance issues, like swiping, scrolling, navigating, etc. Once you’re done, you should see some metrics like these:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Sn2rUSrkJ28NPIGy.png" /></figure><p>Each greenfield React Native app has only one Android Activity. If your app has more than one, it’s most likely a brownfield one. Read more about the brownfield approach here. In the above example, we don’t see anything interesting. Everything works fine without any glitches. Let’s check each metric:</p><ul><li>The CPU metric is strictly correlated to energy consumption because the CPU needs more energy to do some computations.</li><li>The memory metric is not changing while using the app, which is expected. Memory usage can grow, e.g., when opening new screens, and drop when the garbage collector (GC) releases free memory, e.g., when navigating out of a screen. When memory increases unexpectedly and keeps on growing, it may indicate a memory leak, which we want to avoid, as it can crash the app with out-of-memory (OOM) errors.</li><li>The network section has been moved to a separate <a href="https://developer.android.com/studio/debug/network-profiler">tool</a> called the Network Tab. In most cases, this metric is not needed, because it is mostly related to the backend infrastructure. If you would like to profile a network connection, you can find more information <a href="https://developer.android.com/studio/debug/network-profiler">here</a>.</li><li>The energy section gives hints on when our app’s energy usage is low, medium, or high, impacting the daily experience of using the app.</li></ul><h4>Use Android Profiler in action</h4><p>In the previous example, we could see some relations between each metric:</p><figure><img alt="screenshot of android profiler in action" src="https://cdn-images-1.medium.com/max/316/0*z5g5yFp0O9V46Thv.png" /></figure><p>To see a more detailed view, we have to double-click on the tab. Now we can see more details. When the user started to do some touch action (swiping in the above example), we could see more CPU work. Each app will have its own signature of CPU spikes and lows. It’s important to build an intuition about it, by interacting with it and pairing certain activities, like touch events, with the increased usage. In other words, some spikes are expected, because the work needs to be done. The problem starts when CPU usage is very high for extended periods or in unexpected places.</p><p>Let’s imagine you would like to pick the best list or scroll view component for your React Native app, which has the best performance on a lower-end device. You noticed the current solutions could be revamped or improved, and you started working on this. In your experiment, you would like to check how your solution works for LE devices using the above-described solution. When you double-clicked on CPU, you could spot the below data:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*yZPxBBTRl18Dij4y.png" /></figure><p>Here you can see the mqt_js <a href="https://github.com/facebook/react-native/blob/8bd3edec88148d0ab1f225d2119435681fbbba33/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadImpl.java#L210">thread</a> is used almost all the time and does some heavy computation because your computations are done on the JS side. You can start thinking about how to improve it. There are multiple options to check:</p><ul><li>Replace the bridge with JSI in terms of communication — do tests if JSI is faster than the bridge.</li><li>Move some part of the code to the native side — on the native side you have more control over threads execution and can schedule some work to not block the JS or UI thread.</li><li>Use a different native component — replace the native scroll view with your custom solution.</li><li>Use shadow nodes — do some expensive calculation with C++ and pass it to the native side.</li></ul><p>You can try out all of those solutions and compare the effect between each other. The profiler will provide you with a metric, and based on that, you can decide which approach fits best to your particular problem.</p><p>There’s more info about the Android Profiler <a href="https://developer.android.com/studio/profile/android-profiler?gclsrc=ds&amp;gclsrc=ds">here</a>.</p><h4>System Tracing with Android Studio CPU Profiler</h4><p>Using the Android Studio CPU Profiler, we can also make a system tracing. We can check when the appropriate function has been called. We can triage all threads and see which function is the costliest, which affects the UX. To enable system tracing, click on the CPU section and select System Trace Recording.</p><figure><img alt="system tracing view" src="https://cdn-images-1.medium.com/max/1024/0*yswEiSljuVgx1qJK.png" /></figure><p>After some interaction, you should be able to see all the threads with details:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*QXk29_eV4j8lOIzn.png" /></figure><p>You can also save your data by clicking the Save Button:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/856/0*mdWsWVrdMcIxZnJh.png" /></figure><p>And use the data in a different tool, e.g., <a href="https://ui.perfetto.dev/">Perfetto</a>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*sfbOX-Y0iO15R2Hg.png" /></figure><p>You’ll also want to check the official <a href="https://reactnative.dev/docs/profiling#profiling-android-ui-performance-with-systrace">Android Profiling guide</a> by the React Native core team. They use different tools, but the outcome will be the same. The guide provides case studies and how to spot an issue on different threads:</p><ul><li>UI thread</li><li>JS thread</li><li>Native module thread</li><li>Render Thread (only Android)</li></ul><p>You can find more about threading models in the <a href="https://www.callstack.com/blog/experiment-with-new-architecture-of-react-native">New Architecture blog post</a>.</p><h3>Flipper performance plugin for Android</h3><p>We already know <a href="https://www.callstack.com/blog/debugging-with-flipper">Flipper can be quite handy in hunting performance issues</a>. One of the most interesting plugins to help us out on Android is <a href="https://github.com/bamlab/flashlight">android-performance-profiler</a>. It can be used as a standalone tool or on a CI. It can generate beautiful reports, so this tool can be used to do some sophisticated experiments.</p><p>Here is a picture of an example experiment:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*a28RWd_V54b0GavG.png" /></figure><p>Comparison of the new vs. old architecture of React Native by Almouro. <a href="https://github.com/Almouro/fabric-test">Source</a>.</p><p>You can also automate your experiments with e2e tests and generate reports locally or on a CI. Those reports can be used to compare solutions with each other.</p><h3>Profiling improves your app understanding</h3><p><a href="https://techjury.net/blog/app-usage-statistics/#gref">70% of users</a> will leave your app if the response to a given action takes too long. And once they do, they aren’t likely to return ever again, which can seriously harm your business. For that reason alone, profiling your React Native application with native tools for iOS and Android may turn out a game changer — for both your organization and your user base.</p><p>In this article, we’ve shown how to profile your app with tools like Instruments, Flipper, and Hermes Debugger for iOS, and Android Profiler and Flipper for Android.<strong> </strong>If you need help with tracking down and solving your performance issues, drop our <a href="https://www.callstack.com/react-native-development-company">React Native development company</a> a line — our senior devs will surely know how to help.</p><p><em>This article was originally published at </em><a href="https://www.callstack.com/blog/profiling-react-native-apps-with-ios-and-android-tools"><em>callstack.com</em></a><em> on February 15, 2023.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=16580ba8247c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/call-stack/profiling-react-native-apps-with-ios-and-android-tools-16580ba8247c">Profiling React Native Apps With iOS and Android Tools</a> was originally published in <a href="https://medium.com/call-stack">Callstack Engineers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Consistently Improve App Performance With DMAIC and Reassure]]></title>
            <link>https://medium.com/call-stack/consistently-improve-app-performance-with-dmaic-and-reassure-7a7dd360ee64?source=rss-c7a039345e64------2</link>
            <guid isPermaLink="false">https://medium.com/p/7a7dd360ee64</guid>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[react-native-testing]]></category>
            <dc:creator><![CDATA[Hanna Sobolewska]]></dc:creator>
            <pubDate>Wed, 22 Feb 2023 17:45:37 GMT</pubDate>
            <atom:updated>2023-02-22T17:45:37.091Z</atom:updated>
            <content:encoded><![CDATA[<p>by Tomasz Misiukiewicz</p><figure><img alt="screen with a diagram showing improved performance" src="https://cdn-images-1.medium.com/max/1024/1*NiDEeH6Az8rDSW7OntYJyw.jpeg" /></figure><p>The following article is part of <a href="https://www.callstack.com/campaigns/download-the-ultimate-guide-to-react-native-optimization">The Ultimate Guide to React Native Optimization</a> and explains how the DMAIC process and tools like Reassure can help keep your app performant over time.</p><p><strong>Why is this important?</strong></p><p>You want your React Native app to perform well and fast at all times to keep the user experience optimal. That’s impossible unless you make performance regression monitoring a part of your app development and maintenance process. In this article, we explain how the DMAIC process can help your React Native team consistently improve app performance. We also look at the tools you can use to ensure your app remains performant as it grows, mainly Reassure.</p><p>In other blog posts based on The Ultimate Guide to React Native Optimization, we touch on the following stability-related topics:</p><ul><li><a href="https://www.callstack.com/blog/how-continuous-integration-can-improve-react-native-apps">Continuous Integration (CI) in improving React Native apps</a></li><li><a href="https://www.callstack.com/blog/ship-over-the-air-when-in-an-emergency">Over-The-Air (OTA) updates</a></li><li><a href="https://www.callstack.com/blog/shipping-fast-with-continuous-deployment">Shipping Fast with Continuous Deployment</a></li><li><a href="https://www.callstack.com/blog/run-tests-for-key-pieces-of-your-app">Running tests for key pieces of your app</a></li><li><a href="https://www.callstack.com/blog/profiling-react-native-apps-with-ios-and-android-tools">Profiling React Native apps with iOS and Android tools</a></li></ul><h3>Why should you keep improving app performance?</h3><p>Customers have very little patience for slow apps. According to the <a href="https://unbounce.com/page-speed-report/">Unbounce report</a>, nearly 70% of consumers admit that page speed influences their willingness to buy. Good examples here are Walmart and Amazon — both of these companies noticed an increase in revenue by up to 1% for every 100 milliseconds of load time improvement.</p><p>Performance has a noticeable impact on your business goals, yet it’s often the case that after fixing one performance issue, the app sooner or later gets slow again. As such a scenario can take a toll on your organization, you need to not only fix performance issues, but also make sure they don’t happen again.</p><h3>Use DMAIC process to consistently improve React Native app performance</h3><p>You want your React Native app to perform well and fast at all times, but how do you achieve this goal? From the technical perspective, it boils down to avoiding guesswork and making data-informed decisions. We should also remember that improving performance is a process; <strong>it’s impossible to fix everything at once, but small steps can provide big results</strong>.</p><p>Developing an app is a process, and so is performance improvement. Most important, though, every process can be optimized.<strong> In the case of improving React Native app performance and performance regression monitoring, one of the most effective ways of doing so is following the DMAIC methodology.</strong> It’s a very data-driven and well-structured approach comprising the following steps: Define, Measure, Analyze, Improve, and Control. Let’s see how we can apply each phase in our apps.</p><h3>Define</h3><p>In this phase of the DMAIC process, we should focus on <strong>defining the problem, what we want to achieve, opportunities for improvement, etc</strong>. Listening to the customers’ expectations and feedback in this phase is essential, as it helps better understand their needs, preferences, and problems.</p><p>Next, it is very important to measure it somehow. Let’s say the customer wants a fast checkout. After analyzing the components, we know that we need a swift checkout process, a short wait time, and smooth animations and transitions to achieve this. All of these points can be decomposed into measurable CTQs (Critical-to-Quality). For example, a short wait time can be decomposed into a quick server response and a low number of server errors. Another handy tool is analyzing common user paths. With good tracking, we can understand what parts of the app are mostly used by the users.</p><p><strong>Choosing priorities and defining the order in which we will optimize things should conclude this phase</strong>. Any tools and techniques for prioritizing will definitely help here. If you want to improve app performance efficiently, setting measurable goals and putting them in the project scope should be your go-to’s at this stage.</p><h3>Measure</h3><p>Since we already know our direction, it’s time to assess the starting point. <strong>It’s all about collecting as much data as possible to get the actual picture of the problem.</strong> We need to ensure the measurement process is precise. Creating a data collection plan and engaging the development team to build the metrics is really helpful. Then, it’s time to do some profiling.</p><p>When profiling in React Native, the main question is whether to do this on JavaScript or the native side. It heavily depends on the app’s architecture, but most of the time, it’s a mix of both. One of the most popular tools is <strong>React Profiler</strong>, which allows us to wrap a component to measure the render time and the number of renders. It’s very helpful because many performance issues come from unnecessary rerenders.</p><p>Discover how to use it here:</p><pre>import React, { Profiler } from &quot;react&quot;;<br>import { View } from &quot;react-native&quot;;<br><br>const Component = () =&gt; (<br>  &lt;Profiler id=&quot;Component&quot; onRender={(...args) =&gt; console.log(args)}&gt;<br>    &lt;View /&gt;<br>  &lt;/Profiler&gt;<br>);<br><br>export default Component;</pre><p><a href="https://gist.github.com/pytqqq/fb8c980e076b5a0e2064008fa4fa3246#file-using-react-profiler-api-tsx">Using React Profiler API.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>It will output the data:</p><pre>{<br>  id: &quot;Component&quot;,<br>  phase: &quot;mount&quot;,<br>  actualDuration: 1.3352311453,<br>  baseDuration: 0.95232323318,<br>  ...<br>}</pre><p><a href="https://gist.github.com/pytqqq/ba403701d3828797d1b5e46ba8ab7b27#file-output-of-the-react-profiler-api-tsx">Output of the React Profiler API.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>The second tool is a library created by Shopify called <a href="https://shopify.github.io/react-native-performance/"><strong>React Native Performance</strong></a>. It allows you to place some markers in the code and measure the execution time. There is also a pretty nice <strong>Flipper plugin</strong> that helps to visualize the output:</p><figure><img alt="charts showing blank spaces" src="https://cdn-images-1.medium.com/max/446/1*5yVKQzHLqYB0ru-INgw2qQ.png" /><figcaption>Source: <a href="https://shopify.github.io/react-native-performance/docs/guides/flipper-react-native-performance">https://shopify.github.io/react-native-performance/docs/guides/flipper-react-native-performance</a></figcaption></figure><p><a href="https://www.callstack.com/blog/debugging-with-flipper">Speaking of Flipper</a>, it has some more plugins that help us to measure the app performance and speed up the development process. We can use <a href="https://github.com/bamlab/react-native-flipper-performance-monitor">React Native Performance Monitor Plugin</a> for a Lighthouse-like experience or <a href="https://shopify.github.io/react-native-performance/docs/guides/react-native-performance-lists-profiler/">React Native Performance Lists Profiler Plugin</a>.</p><p>On the native side, the most common method is using <strong>Native IDEs: Xcode and Android Studio</strong>. There are plenty of useful insights which can be analyzed and lead to some conclusions and results.</p><p>The most important aspect of the measure phase is measurement variation. <strong>Due to different environments, we have to be very careful when profiling.</strong> Even if the app is run on the same device, some external factors might affect performance measurements. That’s why we should base all the measurements on release builds.</p><h3>Analyze</h3><p>This phase of the DMAIC process aims to <strong>find the root cause of our problem</strong>. It’s a good idea to start with a list of things that could potentially cause the issue. A little brainstorming with a team can be helpful here.</p><p>One of the most popular tools to define a problem is called a cause and effect diagram. It looks like a fish, and we should draw it from right to left. We start from the head that contains the problem statement (we should already have it based on the define phase). Then, we identify all the potential major causes of the problem and assign them to the fish bones. Next, we assign all the possible causes to each major cause. Since there are many things that can impact app performance, it’s important to narrow our list down. Try to outline and focus on the most important factors.</p><p>Finally, it’s time to <strong>test the hypothesis</strong>. For example, if the main problem is low FPS, and the potential major cause is related to list rendering, we can think of some improvements in the area of images in the list items. We need to design a test that will help us accept or reject the hypothesis — it will probably be some kind of proof of concept. Next, we interpret the results and assess whether it improves our React Native app performance or not. Then, we make a final decision.</p><figure><img alt="Cause and effect diagram example" src="https://cdn-images-1.medium.com/max/1024/1*Dq52uGQSyj-yy0NTaR7G6w.png" /><figcaption>Cause and effect diagram example</figcaption></figure><h3>Improve</h3><p>Now that we know our goal and how we want to achieve it, <strong>it’s time to actually improve your app performance</strong>. Before starting, it’s a good idea to hold another brainstorming session and identify potential solutions. Depending on the root cause, there might be a lot of them. Based on the last example with images on the list item, we can think about implementing proper image caching and reducing unnecessary renders.</p><p>After outlining the solutions, it’s time to pick the best one. Sometimes the solution that gives the best effects might be extremely costly, e.g., when it involves architectural changes. Once you implement the solution, don’t forget to test it properly!</p><h3>Control</h3><p>The last step in the DMAIC process is the control phase. <strong>We need to make sure that everything works well now.</strong> As you know by now, app performance will degrade if it is not under control. People tend to blame devices, technology, or even users for it, but it’s not that simple. So what do we need to do to keep the performance of our React Native app on a high level?</p><p>We need to make sure that we have a control plan. We can use some of our work from the previous phases to make it. We should point out focal points, some measurement characteristics, acceptable ranges for indicators, and testing frequency. Additionally, it is a good practice to write down some procedures and what to do if we spot issues.</p><h4>Performance regression monitoring as a part of the development process</h4><p>The most important aspect of the control phase is monitoring regressions. Until recently, it was quite difficult to do that effectively in React Native, but now we have plenty of options to improve our monitoring.</p><p>One way to keep track of the performance improvements we introduce in our apps is through <strong>real-time monitoring tools</strong> like <a href="https://firebase.google.com/docs/perf-mon">Firebase Performance Monitoring</a> or <a href="https://docs.sentry.io/product/performance/">Sentry Performance Monitoring</a>.</p><p>Another way to implement performance regression monitoring is through <strong>automated testing, </strong>which we’d like to explore in greater detail. Profiling, measuring, and running on various devices is a manual and time-consuming job that developers avoid doing. However, it gets too easy to unintentionally introduce performance regressions that would only get caught during QA, or worse, by your users. <strong>Thankfully, we can write automated performance regression tests in JavaScript for React and React Native with </strong><a href="https://www.callstack.com/open-source/reassure"><strong>Reassure</strong></a>.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F8pTQKBHFs-8%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D8pTQKBHFs-8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F8pTQKBHFs-8%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/53fb94756a4ebebf04383c91199d3abc/href">https://medium.com/media/53fb94756a4ebebf04383c91199d3abc/href</a></iframe><p>Reassure allows you to automate React Native app performance regression testing on CI or a local machine. Just like you write your <a href="https://www.callstack.com/blog/run-tests-for-key-pieces-of-your-app">integration and unit tests</a> that automatically verify that your app is still working correctly, <a href="https://www.callstack.com/blog/app-performance-monitoring">you can write performance tests that verify that your app is still performant</a>. You can think about it as a React performance testing library. In fact, Reassure is designed to reuse as much of your <a href="https://github.com/callstack/react-native-testing-library">React Native Testing Library</a> tests and setup as possible as it’s designed by its maintainers and creators.</p><p>It works by measuring certain characteristics — render duration and render count — of the testing scenario you provide and comparing that to the stable version measured beforehand. It repeats the scenario multiple times to reduce the impact of random variations in render times caused by the runtime environment. Then it applies a statistical analysis to figure out whether the code changes are statistically significant or not. As a result, it generates a human-readable report summarizing the results and displays it on CI or as a comment to your pull request.</p><p>The simplest test you can write would look something like this:</p><pre>import React from &quot;react&quot;;<br>import { View } from &quot;react-native&quot;;<br>import { measurePerformance } from &quot;reassure&quot;;<br><br>const Component = () =&gt; {<br>  return &lt;View /&gt;;<br>};<br><br>test(&quot;mounts Component&quot;, async () =&gt; {<br>  await measurePerformance(&lt;Component /&gt;);<br>});</pre><p><a href="https://gist.github.com/pytqqq/beb14efb274145ba7e526b78ffc59d79#file-testing-rented-times-of-component-during-mounting-tsx">Testing rented times of Component during mounting.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>This test will measure the render times of Component during mounting and the resulting sync effects. Let’s take a look at a more complex example, though. Here we have a component that has a counter and a slow list component:</p><pre>import React from &quot;react&quot;;<br>import { Pressable, Text, View } from &quot;react-native&quot;;<br>import { SlowList } from &quot;./SlowList&quot;;<br><br>const AsyncComponent = () =&gt; {<br>  const [count, setCount] = React.useState(0);<br><br>  const handlePress = () =&gt; {<br>    setTimeout(() =&gt; setCount((c) =&gt; c + 1), 10);<br>  };<br><br>  return (<br>    &lt;View&gt;<br>      &lt;Pressable accessibilityRole=&quot;button&quot; onPress={handlePress}&gt;<br>        &lt;Text&gt;Action&lt;/Text&gt;<br>      &lt;/Pressable&gt;<br><br>      &lt;Text&gt;Count: {count}&lt;/Text&gt;<br><br>      &lt;SlowList count={200} /&gt;<br>    &lt;/View&gt;<br>  );<br>};</pre><p><a href="https://gist.github.com/pytqqq/70c7d6d7298c898ff70d7d93601b36fe#file-component-with-a-counter-slow-list-component-tsx">Component with a counter &amp; slow list component.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>And the performance test looks as follows:</p><pre>import React from &quot;react&quot;;<br>import { screen, fireEvent } from &quot;@testing-library/react-native&quot;;<br>import { measurePerformance } from &quot;reassure&quot;;<br>import { AsyncComponent } from &quot;../AsyncComponent&quot;;<br>test(&quot;AsyncComponent&quot;, async () =&gt; {<br>  const scenario = async () =&gt; {<br>    const button = screen.getByText(&quot;Action&quot;);<br><br>    fireEvent.press(button);<br>    await screen.findByText(&quot;Count: 1&quot;);<br><br>    fireEvent.press(button);<br>    await screen.findByText(&quot;Count: 2&quot;);<br><br>    fireEvent.press(button);<br>    fireEvent.press(button);<br>    fireEvent.press(button);<br>    await screen.findByText(&quot;Count: 5&quot;);<br>  };<br><br>  await measurePerformance(&lt;AsyncComponent /&gt;, { scenario });<br>});</pre><p><a href="https://gist.github.com/pytqqq/55ef3439f90ed70cd9a233fc276a56d1#file-test-for-component-with-counter-slow-list-components-tsx">Test for component with counter &amp; slow list components.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>When run through its CLI, Reassure will generate a performance comparison report. It’s important to note that to get a diff of measurements, we need to run it twice. The first time with a `— — baseline flag`, which collects the measurements under the `.reassure/ directory`.</p><figure><img alt="performance tests" src="https://cdn-images-1.medium.com/max/857/1*7UMUP6M666kQJIV4IlyJ-A.png" /></figure><p>After running this command, we can start optimizing our code and see how it affects the performance of our component. Normally, we would keep the baseline measurement and wait for performance regressions to be caught and reported by Reassure. In this case, we’ll skip that step and jump straight into optimizing because we just noticed a nice possibility to do so. And since we have our baseline measurement for reference, we can actually verify our assumptions and whether the improvement was objective or only subjective.</p><p>The possibility we noticed is that the <strong>`</strong>&lt;SlowList/&gt;<strong>`</strong> component can be memoized, as it doesn’t depend on any external variables. We can leverage <strong>`</strong>useMemo<strong>`</strong> for that case:</p><pre>const slowList = useMemo(() =&gt; &lt;SlowList count={200} /&gt;, []);</pre><p><a href="https://gist.github.com/pytqqq/6b57df334cebb3e49ac4fe16d6510cf1#file-slowlist-memoized-tsx">Slowlist memoized.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Once we’re done, we can run Reassure a second time. Now without the ` — — baseline flag`.</p><figure><img alt="performance comparison" src="https://cdn-images-1.medium.com/max/1024/0*uKRhFwn44dTu1l1N.png" /></figure><p>Now that Reassure has two test runs to compare — the current and the baseline — it can prepare a performance comparison report. As you can notice, thanks to applying memoization to the <strong>`</strong>SlowList<strong>`</strong> component rendered by <strong>`</strong>AsyncComponent<strong>`</strong>, the render duration went from 78.4 ms to 26.3 ms, which is roughly a 66% performance improvement.</p><p>Test results are assigned to certain categories:</p><ul><li><strong>Significant Changes To Render Duration</strong> shows a test scenario where the change is statistically significant and should be looked into as it marks a potential performance loss/improvement.</li><li><strong>Meaningless Changes To Render Duration</strong> shows test scenarios where the change is not statistically significant.</li><li><strong>Changes To Render Count</strong> shows test scenarios where the render count did change.</li><li><strong>Added Scenarios</strong> shows test scenarios that do not exist in the baseline measurements.</li><li><strong>Removed Scenarios</strong> shows test scenarios that do not exist in the current measurements.</li></ul><p>When connected with <a href="https://danger.systems/js/">Danger JS</a>, Reassure can output this report as a GitHub comment, which helps catch the regressions during code review.</p><figure><img alt="performance comparison report" src="https://cdn-images-1.medium.com/max/778/0*-A0CJ4efMxudOdwD.png" /></figure><p>You can discover more use cases and examples in the <a href="https://callstack.github.io/reassure/docs/api/">docs</a>.</p><h3>DMAIC process and performance regression monitoring help make your React Native app consistently fast</h3><p>When working on an app, regardless of its size, it’s essential to have a clear path for reaching our goals. <strong>The main benefit of using DMAIC methodology when optimizing React Native applications is a structured and direct approach. </strong>Without it, verifying what works (and why) may be difficult. Sometimes our experience and intuition are just enough. But that’s not always the case.</p><p>Making a process like this a part of <a href="https://www.callstack.com/react-native-development-company">React Native development</a> allows us to focus on problem-solving and constantly increase productivity. <strong>Thanks to the DMAIC approach, performance optimization becomes a part of your normal development workflow.</strong> It brings your React Native app closer to being performant by default and allows spotting performance issues even before they hit your users.</p><p>No software is flawless. Bugs and performance issues will happen even if you’re the most experienced developer on the team. But we can take action to mitigate those risks by using automated tools like Sentry, Firebase, or Reassure. Use them in your project to enjoy the additional confidence they bring to your projects and the improved UX they deliver to your users.</p><p>If you’re looking for a tech partner who can improve the performance of your application in a well-thought-out process, <a href="https://callstack.com/contact-us/">contact us</a>.</p><p><em>This article was originally published at </em><a href="https://www.callstack.com/blog/consistently-improve-app-performance-with-dmaic-and-reassure"><em>callstack.com</em></a><em> on February 8, 2023.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7a7dd360ee64" width="1" height="1" alt=""><hr><p><a href="https://medium.com/call-stack/consistently-improve-app-performance-with-dmaic-and-reassure-7a7dd360ee64">Consistently Improve App Performance With DMAIC and Reassure</a> was originally published in <a href="https://medium.com/call-stack">Callstack Engineers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[React Native Paper 5.0 — What’s New?]]></title>
            <link>https://medium.com/call-stack/react-native-paper-5-0-whats-new-6e0df8c075e9?source=rss-c7a039345e64------2</link>
            <guid isPermaLink="false">https://medium.com/p/6e0df8c075e9</guid>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[open-source]]></category>
            <category><![CDATA[component-libraries]]></category>
            <category><![CDATA[components]]></category>
            <category><![CDATA[react-native-paper]]></category>
            <dc:creator><![CDATA[Hanna Sobolewska]]></dc:creator>
            <pubDate>Mon, 16 Jan 2023 09:44:36 GMT</pubDate>
            <atom:updated>2023-01-16T09:44:36.349Z</atom:updated>
            <content:encoded><![CDATA[<h3>React Native Paper 5.0 — What’s New?</h3><p>by <a href="https://www.callstack.com/team/lukasz-walczak">Luke Walczak</a></p><figure><img alt="four screens of apps on the phone" src="https://cdn-images-1.medium.com/max/1024/1*8ZwCvFu3QxFO-NOBIIYRng.jpeg" /></figure><p>React Native Paper 5.0 is out! We have been working on the new version of React Native Paper for some time, and finally, the team can present the results of their work.</p><h3>What’s new in React Native Paper 5.0?</h3><p>Before reading the article, take a look at React Native Paper demo I prepared, where I show how the new version of the library works.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FltOccWcwnxw&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DltOccWcwnxw&amp;image=http%3A%2F%2Fi.ytimg.com%2Fvi%2FltOccWcwnxw%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/4aa4e99c0c082bc571d0c1806b73f6a1/href">https://medium.com/media/4aa4e99c0c082bc571d0c1806b73f6a1/href</a></iframe><p>React Native Paper 5.0 is all about adopting the new Material Design 3, aka Material You, into the library. The new design system generation was released in October 2021 after intense work and effort to make Material You follow a more expressive approach to design.</p><p>Version 5.0 brings support for the following Material Design iteration branded as Material You (in fact, Material Design v3 or, in short, MD3) into the `react-native-paper library`. We refined all components according to the official design kit on Figma and adjusted in terms of visuals by changes in colors, typography, and animations.</p><p>‍<em>Does it mean that v4 won’t be supported anymore?</em></p><p>Technically that’s true — there will be no more releases of v4. Practically, it’s false since Paper version 5.0 supports Material Design generations 2 and 3. Users can keep their existing design with the latest Paper release.</p><p>You can think about React Native Paper v5 as an extended and modified (mainly in terms of theming and typography related to Material You) v4.</p><p>Introducing Material You (MD3) into `react-native-paper` doesn’t mean dropping previous Material Design (MD2)! On the contrary, both of them will be supported, but not simultaneously.</p><p>‍<em>How to establish which version the app should follow?</em></p><p>To specify which design system components should follow in the app, there is a newly created property in the theme called version, which can accept only one of two values:</p><ul><li><strong>3</strong> — <strong>(default)</strong> new Material You <em>(MD3)</em>,</li><li><strong>2</strong> — previous Material Design <em>(MD2)</em>.</li></ul><pre>theme: {<br> /* … */<br> version: 3 | 2<br>}</pre><p><a href="https://gist.github.com/marta-pinkowska/a07f8f47b6509b07f2c931b9ffe1e46e#file-react-native-paper-tsx">react.native.paper.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><h3>Helpers</h3><p>We meet the needs of library users and help them configure the theme in a smooth and hassle-free way. That’s why we have created new helper functions and adapted existing ones that will help in this process.</p><h3>adaptNavigationTheme</h3><p>From React Native Paper 5.0 theme colors structure follows the Material Design 3 colors system, which differs significantly from the previous Paper’s theme and React Navigation theme.</p><p>However, to simplify adapting React Navigation theme colors and to use the ones from React Native Paper, we created the `adaptNavigationTheme` helper.</p><p>The function accepts navigation-compliant themes in both modes and returns their equivalents adjusted to Material Design 3. The adapted theme can then be passed to `NavigationContainer` so React Navigation’s UI elements match React Native Paper color scheme.</p><figure><img alt="screenshots with React Navigation home" src="https://cdn-images-1.medium.com/max/948/1*mjA9mFJVBn4StTaXkp__4A.png" /><figcaption>React Navigation’s UI elements not following Paper Theme vs React Navigation’s UI matches Paper Theme.</figcaption></figure><h3>configureFonts</h3><p>In the latest version, we based the fonts in the theme on the `variant` keys, e.g., `displayLarge` or `bodyMedium`. Each variant defines appropriate text styles for type role and size and can be applied by props into `text` component throughout the whole library.</p><p>To make it easier to make theme font changes in terms of modifying individual variants or adding entirely new ones, we adjusted the existing utility called `configureFonts`.</p><p>As of today, the function accepts the config object with font modification appropriate to the Material Design version, where the output is an adjusted theme font object.</p><h3>createDynamicThemeColors (currently not in the library)</h3><p>Within Paper documentation in the `Theming` section, you can find the tool for generating two color schemes, `lightScheme` and `darkScheme`, based on the provided source color.</p><p>Created schemes follow the Material Design 3 color system and cover colors structure from the Paper theme.</p><p>Copied color schemes from the generated JSON can be then used by passing them to the colors in the theme object.</p><figure><img alt="Team green team red" src="https://cdn-images-1.medium.com/max/948/1*_r3givsWE5br1EsRLpPg-g.png" /><figcaption>Examples using generated color schemes based on the source color red and green respectively.</figcaption></figure><h3>New versions means new components</h3><p>The new version of the React Native Paper comes with new components:</p><ul><li>`SegmentedButtons`</li><li>`Tooltip`</li><li>`Drawer.CollapsedItem`</li></ul><p>Let’s take a closer look at each component!</p><h3>SegmentedButtons</h3><p>`SegmentedButtons` is a new component introduced in the latest version. However, it can be understood as a refined version of `ToggleButton`.</p><p>It allows you to:</p><ul><li>select options,</li><li>switch views, or</li><li>sort elements.</li></ul><p>It’s intended to support single and multi-select variants and provide many customization options.</p><figure><img alt="Customization options" src="https://cdn-images-1.medium.com/max/948/1*by5D9avFYUHgmsd-sIihGQ.png" /><figcaption>Various Segmented Buttons configurations along with single and multi-select examples.</figcaption></figure><h3>Tooltip</h3><p>Tooltip is a component displayed upon tapping and holding a screen element or component used to present an informative text label identifying an element, such as a description of its function.</p><p>It is one of the components that were missing in the library also in the previous version and, about which there were often questions, so it was high time to introduce it for both Material Design systems!</p><figure><img alt="Tooltips" src="https://cdn-images-1.medium.com/max/948/1*FfLNhhmxcqRTma8gmxiNeg.png" /><figcaption>Displayed Tooltip saying “Search” on both Material Design version 2 and 3.</figcaption></figure><h3>Drawer.CollapsedItem (Navigation Rail)</h3><p>`Drawer.CollapsedItem` is a newly created side navigation component that can be used within Drawer, representing a destination in the form of an action item with an icon and optionally label.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/948/1*nROIt1nk42LUMWMXOyhS5w.png" /><figcaption>Drawer Collapsed Item in the app horizontal layout.</figcaption></figure><h3>React Native Paper 4.0 vs React Native Paper 5.0</h3><p>Now that we know what’s new in the React Native Paper 5.0, let’s take a closer look at the differences between React Native Paper 4.0 and 5.0.</p><h3>BottomNavigation (Navigation Bar)</h3><p>In the latest version, Bottom Navigation is taller and doesn’t have a shadow. Active states are represented with filled icons and a contrasting pill-shaped active indicator, while inactive states are represented with outlined icons.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/948/1*MwgslPg5BXujbMQPOEgxdA.png" /><figcaption>Bottom Navigation in both Material Design versions.</figcaption></figure><h3>Appbar (Top App Bar)</h3><p>According to the Material You, there are now four types of top app bar:</p><ul><li>`center-aligned`</li><li>`small`</li><li>`medium`</li><li>`large`</li></ul><p>Each of them has larger default text and height. Similarly to `BottomNavigation` there is no drop shadow by default.</p><figure><img alt="Screenshots with titles listed" src="https://cdn-images-1.medium.com/max/948/1*vxOJpdTkLH3dnu8C-mvFGQ.png" /><figcaption>Appbar in both Material Design versions.</figcaption></figure><h3>Button</h3><p>From the perspective of visual changes `Button` received fully rounded corners, taller height and inner text is sentence case. Button is one of the several components which received new variants or modes — three new types were introduced: `elevated`, `filled` and `filled-tonal`.</p><p>In terms of naming, we were looking for some compromise, between being consistent with the codebase and MD that’s why:</p><ul><li>since the `filled` type replaced what was previously known as a `contained` button, we decided to stick to that naming, and filled is still named `contained`,</li><li>accordingly, `filled-tonal` received the name `contained-tonal`.</li></ul><figure><img alt="Screenshots with buttons" src="https://cdn-images-1.medium.com/max/948/1*6JObQAq0R4PyphWLqL3Tiw.png" /><figcaption>Button in both Material Design versions.</figcaption></figure><h3>Migration guide</h3><p>To ease the transition to the new version, we prepared a <a href="https://callstack.github.io/react-native-paper/introducing-v5-with-material-you.html">migration guide to React Native Paper</a> 5.0, covering all of the breaking changes.</p><h3>Summary</h3><p>React Native Paper 5.0 offers new versions of new components such as segmented buttons, tooltip, and drawer collapsed item, as well as helpers to make the developers’ experience smoother and more enjoyable. Test it for yourself! And if you have any questions about the library, reach out to us via the official <a href="https://twitter.com/rn_paper">Twitter page for React Native Paper.</a></p><p><em>This article was originally published at </em><a href="https://www.callstack.com/blog/react-native-paper-5-0"><em>callstack.com</em></a><em> on December 6, 2022.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6e0df8c075e9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/call-stack/react-native-paper-5-0-whats-new-6e0df8c075e9">React Native Paper 5.0 — What’s New?</a> was originally published in <a href="https://medium.com/call-stack">Callstack Engineers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Migrating a React Native Library to the New Architecture]]></title>
            <link>https://medium.com/call-stack/migrating-a-react-native-library-to-the-new-architecture-5bb7d04328cf?source=rss-c7a039345e64------2</link>
            <guid isPermaLink="false">https://medium.com/p/5bb7d04328cf</guid>
            <category><![CDATA[new-architecture]]></category>
            <category><![CDATA[react-native]]></category>
            <dc:creator><![CDATA[Hanna Sobolewska]]></dc:creator>
            <pubDate>Mon, 07 Nov 2022 10:00:31 GMT</pubDate>
            <atom:updated>2022-11-07T10:00:31.988Z</atom:updated>
            <content:encoded><![CDATA[<p>by Oskar Kwaśniewski</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*c86G8lAhkh-lOHn7vMSH0A.jpeg" /></figure><h3>Introduction</h3><p>This article is a bird’s-eye view of migrating a React Native library to the New Architecture. At first, I wanted to go into the details. However, due to the pace of changes and ever-evolving new patterns, I decided to walk you through the migration steps with the helpful resources I found.</p><p>I had the pleasure of working on migrating <a href="https://github.com/callstack/react-native-slider/releases/tag/v4.3.0">react-native-slider</a> and also the Android part of <a href="https://github.com/callstack/react-native-pager-view">react-native-pager-view</a>.</p><h3>What’s the New Architecture?</h3><p>If you are following things that happen in the React Native world, I’m sure you heard about the New Architecture, including Fabric and Turbo Modules.</p><p>If you are new to the “New Architecture” world, check out Lorenzo’s at React Native Wrocław Meetup this year.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FsdQHzjV90ow%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DsdQHzjV90ow&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FsdQHzjV90ow%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/46262e1c76f95f605137f5986951878d/href">https://medium.com/media/46262e1c76f95f605137f5986951878d/href</a></iframe><p>There is also a <a href="https://www.callstack.com/podcasts/react-native-new-architecture-ep-17">podcast episode on the New Architecture</a> in which <a href="https://www.callstack.com/team/lukasz-chludzinski">Łukasz Chludziński</a> talks with <a href="https://twitter.com/cortinico">Nicola Corti</a>, a member of the React Native core team.</p><h3>What’s Fabric?</h3><p>Fabric is React Native’s <strong>new concurrent rendering system</strong>, a conceptual evolution of the legacy render system. It allows for all the features React 18+ brings to the table. Fabric is one of the 4 pillars of the New Architecture that React Native core team is working on since 2018.</p><p>Thanks to Fabric, instead of using the bridge which communicated with serialised JSON messages, we can communicate using JSI (second pillar), which is a C++ API for interacting with any JS engine. Ultimately JSI is going to replace the bridge (it’s the “bridgeless” project) but for now they live side by side, which is good because it can speed up your migration when you stumble upon some edge case which is not supported yet.</p><p>The third pillar is Turbo Modules. It’s an interface on top of JSI, that leverages Codegen (the last pillar) to generate C++ code from our TypeScript or Flow spec.</p><p>If you want to try out the new Architecture in your app make sure to follow this <a href="https://reactnative.dev/docs/new-architecture-app-intro">guide</a>.</p><h3>Steps to migrate a library</h3><ol><li>Writing TypeScript spec for Codegen</li><li>Migrating deprecated JavaScript APIs</li><li>Extending react-native-codegen generated interfaces on native platforms (Android / iOS)</li><li>Done ✅</li></ol><p>This may seem like a lot of work but with the documentation getting better and more developers getting involved in the process, it becomes easier every day. It is also worth noting that the first two steps can be done even before migrating to the New Architecture — when preparing your library for migration.</p><h3>Using an official migration guide for library creators</h3><p>There is an official migration guide that you can follow: <a href="https://github.com/react-native-community/RNNewArchitectureLibraries">React Native New Architecture Libraries</a>. It has examples creating simple Fabric component and also a Turbo Module. There is also <a href="https://github.com/react-native-community/RNNewArchitectureLibraries">another guide</a> for migrating your whole app for the New Architecture.</p><p>These examples really help to get you going with the migration. However, most of the time you will end up browsing the source code of other libraries (at least I did). So another helpful resource is a <a href="https://github.com/react-native-community/RNNewArchitectureApp">list of already migrated libraries</a>.</p><h3>Creating a library from scratch</h3><p>If you want to create a new library or just <strong>scaffold a New Architecture setup</strong> for your existing library, you can use <a href="https://github.com/callstack/react-native-builder-bob">react-native-builder-bob</a> which recently received a lot of new features!</p><p>Here is a screenshot of scaffolding a new library with create-react-native-library. As you can see, there are new options for Turbo Modules.</p><figure><img alt="scaffolding a new library" src="https://cdn-images-1.medium.com/max/1024/1*o8s_H5LPjuz_tUV7ZjgnnQ.jpeg" /></figure><p>We have used it to scaffold the New Architecture inside react-native-pager-view which was way faster than creating all the necessary setup by hand. Fabric support will be added soon, but it may be already there as you are reading the article 😄. So go ahead and give Bob a try!</p><h3>1. Writing TypeScript spec</h3><p>Now<strong> let’s start with the migration part</strong>. The goal of this step is to write a specification of your module which is a <strong>set of types written in Flow or TypeScript</strong> that defines all the APIs provided by the native module. Using a spec allows <strong>CodeGen</strong> (code generation tool for React Native) to generate native code for each platform during build time. To find more about it, refer to the <a href="https://reactnative.dev/docs/new-architecture-library-intro#writing-the-javascript-spec">docs</a>.</p><p>Here is how the generated files look like for Android.</p><figure><img alt="generated files on Android" src="https://cdn-images-1.medium.com/max/1024/1*lFOH1klCoq2P7iPYTjcFYQ.png" /></figure><p>It sounds so good in theory. In reality, however, not everything is working as expected (yet!). Let’s go over a few issues I’ve stumbled upon.</p><h4>Unsupported props between platforms</h4><p>As for now CodeGen doesn’t support platform specific specs, so keep in mind that you need to define types for every platform in your spec file. If you have any props that’s not supported on iOS it’s not a problem because you can skip it inside updateProps method:</p><pre>- (void)updateProps:(const Props::Shared &amp;)props oldProps:(const Props::Shared &amp;)oldProps<br>{<br> const auto &amp;oldScreenProps = *std::static_pointer_cast&lt;const RNCSliderProps&gt;(_props);<br> const auto &amp;newScreenProps = *std::static_pointer_cast&lt;const RNCSliderProps&gt;(props);</pre><pre>if (oldScreenProps.step != newScreenProps.step) {<br> slider.step = newScreenProps.step;<br> }</pre><pre>// Handle only supported props here<br>}</pre><p><a href="https://gist.github.com/callstack-bot/4dbbd74a4ddc70cd7d23394f7e111936#file-snippet-1-javascript">snippet 1.javascript</a> hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p><em>snippet </em><a href="https://github.com/callstack/react-native-slider/blob/98d5960e4e43b2876ae9a23b99f8d1ab363d5274/package/ios/RNCSliderComponentView.mm#L144"><em>source code</em></a></p><p>However, Android handles props a little bit differently. It generates setters for all of the props which need to be overwritten.</p><p>The best way to tackle this problem is to override those setters with empty functions like here:</p><pre>// iOS only prop<br><a href="http://twitter.com/Override">@Override</a><br>public void setVertical(ReactSlider view, boolean value) {}</pre><p><a href="https://gist.github.com/callstack-bot/7c0815418741bc4d1b5493c41a78e553#file-snippet-2-javascript">snippet 2.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><h4>Union types</h4><p>Typescript union types are not yet supported by Codegen, but we can get around this limitation by using a Codegen <a href="https://reactnative.dev/docs/new-architecture-library-intro#codegen-helper-types">helper type</a> named WithDefault&lt;&gt;.</p><p>Here is what this “hack” looks like in react-native-pager-view</p><pre>overScrollMode?: WithDefault&lt;’auto’ | ‘always’ | ‘never’, ‘auto’&gt;;</pre><p><a href="https://gist.github.com/callstack-bot/b520768c36361c103d987d2dacfe0481#file-snippet-3-javascript">snippet 3.javascript</a> hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>If you ever get stuck, you can go through these resources:</p><ul><li>react-native source code (features a lot of fabric components)</li><li><a href="https://github.com/reactwg/react-native-new-architecture/discussions/6">Working Group for the New Architecture</a> — features a list of already migrated libraries.</li></ul><p>It’s also worth mentioning that Meta is working on <a href="https://github.com/facebook/react-native/issues/34872">making Codegen support more advanced</a>.</p><h3>2. Migrating deprecated APIs</h3><p>Both projects I’ve worked on haven’t used any of the deprecated APIs. However, one of the most used ones is setNativeProps. It fundamentally breaks the model of the New Architecture leading to skipping all the rendering steps and desynchronising UI between React Native and what’s shown to the user. You can read more about it on <a href="https://github.com/reactwg/react-native-new-architecture/discussions/77">github</a>.</p><p>If you happen to use <a href="https://reactnative.dev/docs/new-architecture-library-intro#preparing-your-javascript-codebase-for-the-new-react-native-renderer-fabric">one of the APIs from this list</a> though, it should be pretty straightforward to just replace them. You can find helpful resources in the <a href="https://github.com/reactwg/react-native-new-architecture/discussions">Working Group discussion on the New Architecture</a>.</p><h3>3. Implementing Codegen generated interfaces on native platforms (Android / iOS)</h3><p>This step is probably the most time consuming and it depends on the complexity of your library.</p><p>Android part is easier since we are having two source sets (newarch / oldarch) which get loaded accordingly to a newArchEnabled flag in build.gradle and then a one SharedImpl file which you can share between implementations.</p><p>However, iOS is based on creating a new .mm files which are implementing Codegen generated protocols. Depending on what’s your library doing you may need to create separate implementations for new / old arch or share code between them.</p><h4>Using Swift</h4><p>Both of the libraries I’ve worked on haven’t used Swift. But, unfortunately, it’s not officially supported at the moment. The official Meta team statement is that they are “looking into it.” Codegen generates native ObjC++ files (.mm) which are tricky to reference from Swift files.</p><p>There is a great twitter thread from Mateusz Mędrek on his experiences.</p><h3>Mateusz Mędrek on Twitter: &quot;That #reactnative #Fabric &amp; #TurboModules migration was a big pain, especially that I had Kotlin and Swift code to migrate, so it&#39;s a big relief to have it done. And there is lots of completely undocumented stuff I wish I knew that would made it a lot easier to migrate pic.twitter.com/CSChN7GJcT / Twitter&quot;</h3><p>That #reactnative #Fabric &amp; #TurboModules migration was a big pain, especially that I had Kotlin and Swift code to migrate, so it&#39;s a big relief to have it done.</p><h4>Using Kotlin</h4><p>When we were migrating react-native-pager-view I had lots of build issues which resulted from using Kotlin. Due to mixing Java with Kotlin, Codegen created files which were not included. So we have added a temporary workaround which may be useful in case you are also using Kotlin in your library. Check it out here:</p><h4>Custom component state with C++</h4><p>In some use cases Codegen isn’t enough — it’s a good starting point but It wasn’t designed to cover all the edge cases. So if your native component would like to update its frames in a <a href="https://reactnative.dev/architecture/render-pipeline">synchronous way</a>, you will need to add custom C++ state.</p><p>I haven’t added custom shadow nodes to react-native-slider in C++ yet (it’s scary but it’s on my to do list 😄). We have lots of great <a href="https://www.callstack.com/team">developers</a> working on improving the New Architecture here at Callstack. My colleague <a href="https://www.callstack.com/team/piotr-trocki">Piotr Trocki</a> together with <a href="https://twitter.com/cortinico">Nicola Corti</a> created a <a href="https://github.com/callstack/fabric-library-with-custom-cpp-example">sample repository</a> which will help you set this up. Right know the guide only covers Fabric, yet there is already an <a href="https://github.com/callstack/fabric-library-with-custom-cpp-example/issues/2">open issue</a> to support Turbo Modules.</p><p>If you are afraid of C++ you can make use of the good old bridge as it’s still being initialized. But keep in mind that one day there will be bridgeless mode added.</p><h3>Build times</h3><p>While I was working on migration of react-native-slider we were using react-native 0.69 which had a major flaw in terms of build times. When it was time to create a fresh build without any cache, I could go and make myself a coffee ☕️ and then go for a walk. It took around 15–20 minutes. The good thing is that the community have added an — active-arch-only flag which will decrease your build times even 3x. And the core team is actively working on bringing the build times down by leveraging <a href="https://github.com/react-native-community/discussions-and-proposals/pull/508">prebuilt artifacts</a> outside of NPM.</p><h3>Oskar Kwaśniewski on Twitter: &quot;In the latest nightly version of React Native there is a huge boost in build speed using new arch on Android 🚀🏎️Combined with the `--active-arch-only` flag we went from around 9 minutes to ONLY 3 minutes 👀🔥Try it out yourself with: `yarn android --active-arch-only` pic.twitter.com/ZhgpAHSbeC / Twitter&quot;</h3><p>In the latest nightly version of React Native there is a huge boost in build speed using new arch on Android 🚀🏎️Combined with the `--active-arch-only` flag we went from around 9 minutes to ONLY 3 minutes 👀🔥Try it out yourself with: `yarn android --active-arch-only` pic.twitter.com/ZhgpAHSbeC</p><p>Also keep in mind that you will need a pretty good machine to play around with new architecture. I saw few comments to my tweet indicating that building app (using new architecture) took them <strong>around 30 minutes</strong>. Of course once the build is cached it will be faster.</p><h3>4. Now it’s time to release a migrated library</h3><p>Every migrated library brings us closer and closer to finally enable the New Architecture in the production apps. Meta is using Fabric in their Facebook app since last year, but most of us are probably still blocked by the libraries that don’t have support for the New Architecture yet. If you want to track the status of migration for libraries, there is a <a href="https://github.com/reactwg/react-native-new-architecture/discussions/6">dedicated discussion page</a>. And if you are working on migrating your library, also add it there so it will be listed in the React Native Directory as a library that <a href="https://reactnative.directory/?newArchitecture=true">supports the New Architecture</a>.</p><figure><img alt="React Native Directory" src="https://cdn-images-1.medium.com/max/1024/1*0G9GTLDS1iLBv_qx4_20JQ.png" /></figure><h3>Try React Native Slider with Fabric</h3><ol><li>Create a new app using React Native CLI: npx react-native init NewArchApp</li><li>Add a React Native slider yarn add react-native-slider</li><li>[iOS] Run RCT_NEW_ARCH_ENABLED=1 pod install inside ios folder</li><li>[Android] Set newArchEnabled=true in gradle.properties</li></ol><p>In the New Architecture mode, components that are not yet compatible will show a red box: Unimplemented component: &lt;ComponentName&gt;, and you will likely notice them. In that case, please let the library maintainers know about it.</p><p>Here is an example of not yet fabric ready LottieAnimationView:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ssmUBqQfwsJR9Imt3VZ9ZA.png" /></figure><h3>Summary</h3><p>Even though the React Native New Architecture is out there for a good while now, it’s still a challenge to do migrations, especially Fabric. The React Native core team put a good amount of work into making this effort easier. There’s a lot new documentation and up-to-date repositories on how to migrate both libraries and apps. And it’s still not enough. We keep finding the gaps in the official docs and often need to dive into the source code and commit history to figure out the rationale behind some API decisions.</p><p><a href="https://github.com/cortinico">Nicola Corti</a> from the core team frequently mentions at conferences and podcasts that now it is the best time for apps to migrate. That’s because now <strong>they have a dedicated capacity to help the community solve their app and library problems</strong> in a close cooperation. They can’t promise whether they’ll have this capacity in a year from now.</p><p>At Callstack, together with my fellow developers, we often took this opportunity to reach out directly to the core team members, be it around the New Architecture’s autolinking, or migrating Slider, PagerView and Bob. And they are always utterly helpful, even though not available on-demand.</p><p>Although this may not be the best time for your app to adopt the New Architecture, I strongly encourage you to <em>try</em>. Turn on the build flag, check which components and modules are missing support. Post your problems and findings in a <a href="https://github.com/reactwg/react-native-new-architecture?utm_campaign=This%20Week%20In%20React&amp;utm_medium=email&amp;utm_source=Revue%20newsletter">github discussion group</a>. The New Architecture is the biggest thing that has happened to React Native since its inception. Get involved 🙂</p><p><em>This article was originally published at </em><a href="https://www.callstack.com/blog/migrating-a-react-native-library-to-the-new-architecture"><em>callstack.com</em></a><em> on November 3, 2022.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5bb7d04328cf" width="1" height="1" alt=""><hr><p><a href="https://medium.com/call-stack/migrating-a-react-native-library-to-the-new-architecture-5bb7d04328cf">Migrating a React Native Library to the New Architecture</a> was originally published in <a href="https://medium.com/call-stack">Callstack Engineers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Stripe Identity: ID Authentication Made Simple]]></title>
            <link>https://medium.com/call-stack/stripe-identity-id-authentication-made-simple-881408383474?source=rss-c7a039345e64------2</link>
            <guid isPermaLink="false">https://medium.com/p/881408383474</guid>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[security]]></category>
            <dc:creator><![CDATA[Hanna Sobolewska]]></dc:creator>
            <pubDate>Fri, 04 Nov 2022 10:56:44 GMT</pubDate>
            <atom:updated>2022-11-04T10:56:44.013Z</atom:updated>
            <content:encoded><![CDATA[<p>by <a href="https://www.callstack.com/team/jan-jaworski">Jan Jaworski</a></p><figure><img alt="application scanning a man’s face" src="https://cdn-images-1.medium.com/max/1024/1*LQdE5b4DDE8aP_KwP1EFOQ.jpeg" /></figure><h3>What is Stripe Identity?</h3><p>There’s no easier way to verify identities than <a href="https://stripe.com/identity">Stripe Identity</a>. It lets you programmatically confirm the identity of users around the globe by scanning an image of an official form of ID, so you can prevent attacks from fraudsters while minimizing friction for legitimate payments.</p><p>Stripe Identity is an <a href="https://www.callstack.com/open-source?utm_campaign=Stripe_program&amp;utm_source=medium&amp;utm_content=blog_post">open source</a> React Native wrapper for the native Stripe SDKs. The idea is to compare your Face ID with images of you and your IDs by means of biometric technology.</p><p>With the Stripe Identity React Native SDK, you can confidently verify the authenticity of ID documents from over 33 countries in your React Native application.</p><h3>How to use the Stripe Identity React Native SDK</h3><p>To verify your user’s identity, you need to have a document upload sheet displayed in your application. There are few steps to do that. First of all, you have to install <a href="https://github.com/stripe/stripe-identity-react-native">Stripe Identity React Native SDK</a>.</p><p>The next step is to set up a server to create a <em>VerificationSession</em>, which is the programmatic representation of the verification. For security reasons, the <em>VerificationSession</em> API is not directly accessible from the mobile client. Instead, your server provides the SDK with an ephemeral key — a short-lived API key with restricted access to the <em>VerificationSession</em> API.</p><p>You can think of an ephemeral key as a session authorizing the SDK to retrieve and update a specific VerificationSession object for the duration of the session. After successfully creating a VerificationSession and ephemeral key, send the VerificationSession id and ephemeral key secret to the client to show the document upload sheet.</p><p>The third step is to show the “document upload” sheet to the user. With Stripe Identity React Native, you can do this in two ways — via a hook called useStripeIdentity, or a method called presentIdentityVerificationSheet. That depends on whether you want to use it in functional or class-based components.</p><p>You can find example code in the <a href="https://github.com/stripe/stripe-identity-react-native">repository</a> or <a href="https://github.com/stripe/stripe-identity-react-native">integration guide</a>.</p><h3>Getting started with the useStripeIdentity hook</h3><p>The easiest way to use the SDK is to import the useStripeIdentity hook directly in a functional component. You should pass the necessary information you fetched from your server directly to the hook.</p><pre>import React from &quot;react&quot;;<br>import { View, Button, Text, Image } from &quot;react-native&quot;;<br>import { useStripeIdentity } from &quot;<a href="http://twitter.com/stripe/stripe-identity-react-nat">@stripe/stripe-identity-react-nat</a>ive&quot;;</pre><pre>// brand logo that needs to be passed to Stripe Identity hook<br>import logo from &quot;./assets/{{YOUR_BRAND_LOGO}}.png&quot;;</pre><pre>// simplified example of fetch function for Stripe Identity<br>// it can be replaced with more robust implementation that handles error handling, analytics, etc.<br>// other fetching libraries like Axios can be used as a replacement for native fetch()<br>const fetchVerificationSessionParams = async () =&gt; {<br> try {<br>   const data = await fetch(<br>     `${YOUR_SERVER_BASE_URL}/create-verification-session`,<br>     {<br>       method: &quot;POST&quot;,<br>       headers: {<br>         &quot;Content-Type&quot;: &quot;application/json&quot;<br>       }<br>     }<br>   );<br>   const json = await data.json();<br>   return json;<br> } catch (e) {<br>   return {};<br> }<br> };</pre><pre>// options needed to make correct request to Stripe Identity<br>const fetchOptions = async () =&gt; {<br> const response = await fetchVerificationSessionParams();<br> return {<br>   sessionId: response.id,<br>   ephemeralKeySecret: response.ephemeral_key_secret,<br>   brandLogo: Image.resolveAssetSource(logo)<br> };<br>};</pre><pre>function VerifyScreen() {<br> // hook provided by Stripe Identity SDK allows API consumers to get important states and values without too much work from their side.<br> const { status, present, loading } = useStripeIdentity(fetchOptions);</pre><pre>return (<br>   &lt;View&gt;<br>     &lt;Button title=&quot;Verify&quot; disabled={loading} onPress={present} /&gt;<br>     &lt;Text&gt;Status: {status}&lt;/Text&gt;<br>   &lt;/View&gt;<br> );<br>}</pre><p><a href="https://gist.github.com/callstack-bot/3bae84b3a6a30b6ccb2b383641c158b1#file-code-snippet-1-javascript">code snippet 1.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>The hook returns 3 fields: <strong>status</strong> (FlowCompleted, FlowCanceled, FlowFailed), <strong>loading</strong> boolean, or <strong>error</strong>, and a method: present. Use the <strong>present</strong> method to display a document verification sheet. Clicking the verify button will open a native modal view.</p><h3>Using the Stripe Identity SDK without hooks</h3><p>If you use class-based components or prefer to implement the SDK without using hooks in your RN application, you can import an async method called <em>presentIdentityVerificationSheet</em> and prepare your own implementation. You will pass the same parameters as with functional components.</p><p>This method returns a status and an optional error.</p><pre>import React from &quot;react&quot;;<br>import { View, Button, Text } from &quot;react-native&quot;;<br>import { presentIdentityVerificationSheet } from &quot;<a href="http://twitter.com/stripe/stripe-identity-react-nat">@stripe/stripe-identity-react-nat</a>ive&quot;;</pre><pre>const fetchVerificationSessionParams = async () =&gt; {<br> //  same implementation as in function component<br>};</pre><pre>const fetchOptions = async () =&gt; {<br> //  same implementation as in function component<br>};</pre><pre>class VerifyScreen extends React.Component {<br> constructor(props) {<br>   super(props);<br>   this.state = { loading: false, status: undefined, error: undefined };<br> }</pre><pre>present = async () =&gt; {<br>   // without provided hooks implementation user has to manage error and loading states manually<br>   this.setState({ loading: true });<br>   const options = await fetchOptions();<br>   this.setState({ loading: false });<br>   const { status, error } = await presentIdentityVerificationSheet(options);<br>   this.setState({ status, error });<br> };</pre><pre>render() {<br>   return (<br>     &lt;View&gt;<br>       &lt;View&gt;<br>         {this.state.loading ? (<br>           &lt;View&gt;<br>             &lt;Text&gt;Loading...&lt;/Text&gt;<br>           &lt;/View&gt;<br>         ) : (<br>           &lt;Button title=&quot;Verify Identity&quot; onPress={this.present} /&gt;<br>         )}<br>       &lt;/View&gt;<br>       &lt;Text&gt;Status: {this.state.status}&lt;/Text&gt;<br>     &lt;/View&gt;<br>   );<br> }<br>}</pre><p><a href="https://gist.github.com/callstack-bot/c4a926e875fe4053fd007a6f7cc38d5b#file-code-snippet-2-javascript">code snippet 2.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><h3>Verifying results</h3><p>Based on the status (FlowCompleted, FlowCancelled, FlowFails), you’ll need to handle these outcomes in your application. Please refer to the <a href="https://stripe.com/docs/identity/handle-verification-outcomes">official documentation</a> to read more about setting up a webhook flow.</p><h3>Error handling</h3><p>When implementing such a critical feature for your app, it is important to correctly implement error handling and provide users with clear information about the source of the issue and how they should proceed. If the error is on their side, your application should tell the user what to do to fix the problem. If the problem is due to code or server issues, there should be a clear message saying it.</p><p>Stripe Identity SDK provides a number of statuses and messages that can be used to create robust error handling implementation in your application.</p><p>Both useStripeIdentity and presentIdentityVerificationSheet provide you with information about the errors.</p><h3>TypeScript support</h3><p>Stripe Identity React Native SDK provides TypeScript support — it’s actually written in TypeScript. If you use it in your RN project, you can also use the types that SDK provided — <em>StripeError</em> and <em>IdentityVerificationSheetStatus</em>. Both can be useful while using the method presentIdentityVerificationSheet.</p><h3>Stripe Identity features</h3><p>Stripe Identity SDK offers a number of features that allow you to quickly introduce identity verification in your app. It ensures a secure and law-compliant implementation that should cover most of you and your users’ needs.</p><h3>Simplified security</h3><p>It’s simple for you to securely collect your user’s personally identifiable information (PII) such as identity document images. Sensitive PII data is sent directly to Stripe Identity instead of passing through your server. More information in the <a href="https://stripe.com/docs/security">integration security guide</a>.</p><h3>Automatic document capture</h3><p>We automatically capture images of the front and back of government-issued photo ID to ensure a clear and readable image.</p><h3>Prebuilt UI</h3><p>We provide <a href="https://stripe.com/docs/security">IdentityVerificationSheet</a>, a prebuilt UI that combines all the steps required to collect ID documents, selfies, and ID numbers into a single sheet that displays on top of your app.</p><h3>Automated verification</h3><p>Stripe Identity’s automated verification technology looks for patterns to help determine if an ID document is real or fake and uses distinctive physiological characteristics of faces to match your users’ selfies to photos on their ID document.</p><p>Collected identity information is checked against a global set of databases to confirm that it exists. Learn more about the <a href="https://stripe.com/docs/identity/verification-checks">verification checks</a> supported by Stripe Identity, <a href="https://stripe.com/docs/identity/verification-checks">accessing verification results</a>, or integration guide on <a href="https://stripe.com/docs/identity/access-verification-results">handling verification outcomes</a>.</p><h3>Summary</h3><p>Stripe Identity was born to make the ID verification process faster and more efficient. Thanks to the technology used, online businesses can easily confirm their users’ identities. It’s a great convenience and, most importantly, a viable safety measure that should be widely adopted.</p><p><em>This article was originally published at </em><a href="https://www.callstack.com/blog/stripe-identity-id-authentication-made-simple"><em>callstack.com</em></a><em> on October 28, 2022.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=881408383474" width="1" height="1" alt=""><hr><p><a href="https://medium.com/call-stack/stripe-identity-id-authentication-made-simple-881408383474">Stripe Identity: ID Authentication Made Simple</a> was originally published in <a href="https://medium.com/call-stack">Callstack Engineers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Setting up React Native Monorepo with Yarn Workspaces]]></title>
            <link>https://medium.com/call-stack/setting-up-react-native-monorepo-with-yarn-workspaces-4692d6c331d3?source=rss-c7a039345e64------2</link>
            <guid isPermaLink="false">https://medium.com/p/4692d6c331d3</guid>
            <category><![CDATA[app-development]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[monorepo]]></category>
            <dc:creator><![CDATA[Hanna Sobolewska]]></dc:creator>
            <pubDate>Mon, 17 Oct 2022 11:34:45 GMT</pubDate>
            <atom:updated>2023-01-31T17:01:04.686Z</atom:updated>
            <content:encoded><![CDATA[<p>by Oskar Kwaśniewski</p><figure><img alt="Laptop screen with lines of code" src="https://cdn-images-1.medium.com/max/1024/1*DdvbJ1SOr5qVHiniNgXsvg.jpeg" /></figure><h3>What is a monorepo?</h3><p>A monorepo is a single repository that holds a multitude of projects with all their code and assets. While the projects can be related, they can be used independently by different teams.</p><p>Working with monorepos is very useful, especially when developing big and complex applications like <a href="https://www.callstack.com/blog/why-have-a-super-app">super apps</a>. Monorepos enable sharing the logic between a web app and a mobile app, for example.</p><p>In this article, we’re going to set up a basic structure for a monorepo in React Native.</p><h3>Why use monorepo in React Native?</h3><p>Thanks to react-native-web we can share every component so there’s no need to duplicate the code many times. This means easier dependency management, shorter CI times, and better collaboration between teams since the code can be shared.</p><p>The main advantage though is the possibility of sharing packages between React and React Native. Most of the time we decide to share only business logic, but thanks to React Native Web, we can also share some of the UI components.</p><h3>Setting up Yarn workspaces</h3><p>While setting up a monorepo, we have two options: we can either hoist the packages to the root level or prevent them from hoisting. Yarn workspaces have an option named nohoist which allows us to specify packages that aren’t hoisted. It depends on your use case but most of the time <strong>it’s better to hoist packages to the root level</strong>.</p><p>Alternatively, you can use<a href="https://docs.npmjs.com/cli/v7/using-npm/workspaces"> npm workspaces</a>, it <em>should</em> work the same.</p><h3>Why it’s better to avoid using nohoist</h3><p>Preventing packages from hoisting takes back the main advantage of monorepos which is sharing `node_modules` between repositories. When nohoist option is turned on, most of the time packages are duplicated inside the root level `node_modules` and inside the project level `node_modules`. Downloading packages multiple times can lead to longer CI/CD runs and higher costs.</p><h3>Rearranging the project structure</h3><p>In order to set up yarn workspaces, we need to restructure our project to suit the structure below. Projects need to be divided into separate folders and we should have root level `package.json`.</p><pre>your-project packages web // &lt;- React app mobile // &lt;- React Native app shared // &lt;- Shared (includes files shared between mobile/web)</pre><p><a href="https://gist.github.com/callstack-bot/153f4e4e15791065fd01dd57cb426730#file-plain1-txt">plain1.txt </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Next, you should create a package.json file in the root directory of our project with this command: `$ yarn init -y`</p><p>It should look like this:</p><pre>{ “private”: “true”, “name”: “example-app”, “version”: “1.0.0”, “workspaces”: [ “packages/*” ]}</pre><p><a href="https://gist.github.com/callstack-bot/00a07fe6d69f1d9fa9270db86bc3a2a4#file-codesnippet1-json">codesnippet1.json </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Note that private: true is required because workspaces are not meant to be published.</p><p>In the workspaces section, we define a <strong>work tree</strong>. We can pass there <strong>an array of glob patterns that should be used to locate the workspaces</strong>. So in the example above, every folder inside packages is defined as a workspace.</p><h3>Creating a React Native project</h3><p>Use command below to create a React Native project inside the `packages` folder:</p><pre>$ npx react-native init ExampleApp — directory mobile — template react-native-template-typescript</pre><p><a href="https://gist.github.com/callstack-bot/f666e8c6ada815b30444b70e6e1e4e19#file-plain2-txt">plain2.txt </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>In order for our app to work in a monorepo structure, we need to make sure that config files are pointing to the root level `node_modules` due to package hoisting.</p><h4>iOS setup</h4><ol><li>Change paths at the top of your Podfile</li></ol><pre>- require_relative ‘../node_modules/react-native/scripts/react_native_pods’- require_relative ‘../node_modules/@react-native-community/cli-platform-ios/native_modules’+ require_relative ‘../../../node_modules/react-native/scripts/react_native_pods’+ require_relative ‘../../../node_modules/@react-native-community/cli-platform-ios/native_modules’ target ‘ExampleApp’ do…</pre><p><a href="https://gist.github.com/callstack-bot/b6f07259a08e8af8f4b678266c724fd4#file-path1-diff">path1.diff </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><ol><li>Regenerate Pods, by entering the command below in the packages/mobile folder:</li></ol><pre>$ cd ios &amp;&amp; pod install</pre><p><a href="https://gist.github.com/callstack-bot/dc54172d5b9e2fb78e96b8c0ac95723c#file-plain3-txt">plain3.txt </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><ol><li>Next open Xcode and inside Project settings &gt; Build Phases open “Bundle React Native code and images”</li></ol><p>Change the path of the script:</p><pre>set -e<br><br>- WITH_ENVIRONMENT=&quot;../../node_modules/react-native/scripts/xcode/with-environment.sh&quot;<br>- REACT_NATIVE_XCODE=&quot;../../node_modules/react-native/scripts/react-native-xcode.sh&quot;<br>+ WITH_ENVIRONMENT=&quot;../../../node_modules/react-native/scripts/xcode/with-environment.sh&quot;<br>+ REACT_NATIVE_XCODE=&quot;../../../node_modules/react-native/scripts/react-native-xcode.sh&quot;<br><br>/bin/sh -c &quot;$WITH_ENVIRONMENT $REACT_NATIVE_XCODE&quot; path2.diff hosted with ❤ by GitHub</pre><p><a href="https://gist.github.com/callstack-bot/47fa581379143d26ffb8b941d97f6969#file-path2-diff">path2.diff </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>It should look like this:</p><figure><img alt="XCode Build phases settings" src="https://cdn-images-1.medium.com/max/1024/0*uKJ11OfAg0t6Bgk_.png" /></figure><h4>Android setup</h4><p><strong>React Native ≥ 0.71</strong></p><p>Uncomment the line with reactNativeDir and point it to root node_modules</p><pre>// packages/mobile/android/app/build.gradle<br><br>react { <br>+  hermesCommand = &quot;../../node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc&quot;<br>}</pre><p><a href="https://gist.github.com/callstack-bot/959430f8f3dfb5f0ada39058e732c16e#file-android-1-diff">android 1.diff </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>In top-level build.gradle add this:</p><pre>allprojects {<br>    project.pluginManager.withPlugin(&quot;com.facebook.react&quot;) {<br>        react {<br>            reactNativeDir = rootProject.file(&quot;../../../node_modules/react-native/&quot;)<br>            codegenDir = rootProject.file(&quot;../../../node_modules/react-native-codegen/&quot;)<br>        }<br>    }<br>}</pre><p><a href="https://gist.github.com/callstack-bot/394a81925dab92be914fdfedac3d6bf0#file-android-2-shell">android 2.shell </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>and inside: packages/mobile/android/settings.gradle</p><pre>+ apply from: file(&quot;../../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle&quot;); applyNativeModulesSettingsGradle(settings)<br>+ includeBuild(&#39;../../../node_modules/react-native-gradle-plugin&#39;)</pre><p><a href="https://gist.github.com/callstack-bot/31ebc8fe1081b3d18d6dda7c5460f946#file-android-3-diff">android 3.diff </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>‍<br><strong>React Native ≤ 0.71</strong></p><ol><li>Fix paths inside `packages/mobile/android/build.gradle`</li></ol><p>Change url of the React Native Android binaries, and Android JSC in the `allprojects` section:</p><pre>allprojects { repositories { maven { // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm- url(https://medium.com/node_modules/react-native/android%E2%80%9D)+ url(https://medium.com/node_modules/react-native/android%E2%80%9D) } maven { // Android JSC is installed from npm- url(https://medium.com/node_modules/jsc-android/dist%E2%80%9D)+ url(https://medium.com/node_modules/jsc-android/dist%E2%80%9D) } … }}</pre><p><a href="https://gist.github.com/callstack-bot/0f6d4ce0be60e41092ed684831768865#file-code-snippet2-diff">code snippet2.diff </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>2. Fix `packages/mobile/android/settings.gradle`</p><p>Here we also need to change paths to the root `node_modules` folder.</p><pre>rootProject.name = &#39;example-app&#39;<br>- apply from: file(&quot;../node_modules/@react-native-community/cli-platform-android/native_modules.gradle&quot;); applyNativeModulesSettingsGradle(settings)<br>- includeBuild(&#39;../node_modules/react-native-gradle-plugin&#39;)<br>+ apply from: file(&quot;../../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle&quot;); applyNativeModulesSettingsGradle(settings)<br>+ includeBuild(&#39;../../../node_modules/react-native-gradle-plugin&#39;)<br>include &#39;:app&#39;<br>if (settings.hasProperty(&quot;newArchEnabled&quot;) &amp;&amp; settings.newArchEnabled == &quot;true&quot;) {<br>    include(&quot;:ReactAndroid&quot;)<br>-   project(&quot;:ReactAndroid&quot;).projectDir = file(&#39;../node_modules/react-native/ReactAndroid&#39;)<br>+   project(&quot;:ReactAndroid&quot;).projectDir = file(&#39;../../../node_modules/react-native/ReactAndroid&#39;)<br>    include(&quot;:ReactAndroid:hermes-engine&quot;)<br>-   project(&quot;:ReactAndroid:hermes-engine&quot;).projectDir = file(&#39;../node_modules/react-native/ReactAndroid/hermes-engine&#39;)<br>+   project(&quot;:ReactAndroid:hermes-engine&quot;).projectDir = file(&#39;../../../node_modules/react-native/ReactAndroid/hermes-engine&#39;)<br>}</pre><p><a href="https://gist.github.com/callstack-bot/912dc87a0fcaf5f3b3268ce802aea09d#file-path3-diff">path3.diff </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>3. Next go to `packages/mobile/android/app/build.gradle`</p><p>Inside the `project.ext.react` we need to add property `cliPath` so it will override the default location of the cli.</p><pre>project.ext.react = [+ cliPath: “../../../../node_modules/react-native/cli.js”,]</pre><p><a href="https://gist.github.com/callstack-bot/a138c380342986006c11453c81fa450a#file-plain4-txt">plain4.txt </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>In the same file, change this line: `apply from: “../../node_modules/react-native/react.gradle”` to point to root level `node_modules` as well.</p><pre>- apply from: “../../node_modules/react-native/react.gradle”+ apply from: “../../../../node_modules/react-native/react.gradle”</pre><p><a href="https://gist.github.com/callstack-bot/869f2e7ac507c6dbfb753454eccf2cc7#file-path4-diff">path4.diff </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>And also change: `inside packages/mobile/android/app/build.gradle`</p><pre>- apply from: file(“../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle”); applyNativeModulesAppBuildGradle(project)+ apply from: file(“../../../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle”); applyNativeModulesAppBuildGradle(project)</pre><p><a href="https://gist.github.com/callstack-bot/c49912a600849eaaaa91fb3a0c488707#file-path5-diff">path5.diff </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>If you are using or planning to use the new architecture, we also need to change a few lines in the `isNewArchitectureEnabled()` if statement**.**</p><pre>if (isNewArchitectureEnabled()) {<br>            // We configure the NDK build only if you decide to opt-in for the New Architecture.<br>            externalNativeBuild {<br>                ndkBuild {<br>                    arguments &quot;APP_PLATFORM=android-21&quot;,<br>                        &quot;APP_STL=c++_shared&quot;,<br>                        &quot;NDK_TOOLCHAIN_VERSION=clang&quot;,<br>                        &quot;GENERATED_SRC_DIR=$buildDir/generated/source&quot;,<br>                        &quot;PROJECT_BUILD_DIR=$buildDir&quot;,<br>-                       &quot;REACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid&quot;,<br>-                       &quot;REACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build&quot;,<br>-                       &quot;NODE_MODULES_DIR=$rootDir/../node_modules&quot;<br>+                       &quot;REACT_ANDROID_DIR=../../node_modules/react-native/ReactAndroid&quot;,<br>+                       &quot;REACT_ANDROID_BUILD_DIR=../../node_modules/react-native/ReactAndroid/build&quot;,<br>+                       &quot;NODE_MODULES_DIR=../../node_modules&quot;<br>                    cFlags &quot;-Wall&quot;, &quot;-Werror&quot;, &quot;-fexceptions&quot;, &quot;-frtti&quot;, &quot;-DWITH_INSPECTOR=1&quot;<br>                    cppFlags &quot;-std=c++17&quot;<br>                    // Make sure this target name is the same you specify inside the<br>                    // src/main/jni/Android.mk file for the `LOCAL_MODULE` variable.<br>                    targets &quot;okwasniewskionboarding_appmodules&quot;<br>                }<br>            }</pre><p><a href="https://gist.github.com/callstack-bot/54c60198e445fe5d1d868682b1bf61ab#file-code-snippet3-diff">code snippet3.diff </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><h4>Configure Metro</h4><p>We’re almost done with setting up the project. The last thing in the React Native app is to add `watchFolders` so metro knows where the linked `node_modules` are. The shared modules are symlinked by yarn, and since<a href="https://github.com/facebook/metro/issues/1"> metro doesn’t follow symlinks</a> we need to explicitly say where the linked `node_modules` are.</p><pre>const path = require(“path”); // packages/mobile/metro.config.jsmodule.exports = { watchFolders: [ path.resolve(__dirname, ‘../../node_modules’) ],};</pre><p><a href="https://gist.github.com/callstack-bot/36f0d1e17290db96872b9ce62eed73fa#file-code-snippet4-javascript">code snippet4.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><h3>Setting up a shared package</h3><p>To keep it simple, we’re going to share only one function across React Native and React.</p><p>Inside the `packages/shared`, create a new `package.json` file with the command:</p><pre>$ yarn init -y</pre><p><a href="https://gist.github.com/callstack-bot/7324da94e7408a181f49567fc11e7b14#file-code-snippet5-javascript">code snippet5.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>The shared library is in typescript, so we need to set up a build step with the typescript compiler (tsc).</p><p>The build step uses `rimraf` which is a small utility for node that allows us to remove a folder, and then build the app with tsc.</p><p>`postinstall` indicates that our shared dependency will build automatically after installing.</p><pre>{ “name”: “@example-app/shared”, “version”: “1.0.0”, “main”: “dist/index.js”, “scripts”: { “build”: “rimraf dist &amp;&amp; tsc”, “postinstall”: “yarn build”, “watch”: “tsc — watch” }, “dependencies”: { “react-native”: “0.69.1”, “react”: “18.0.0” }, “devDependencies”: { “rimraf”: “³.0.2”, “typescript”: “⁴.4.4” }, “keywords”: [], “author”: “”, “license”: “ISC”}</pre><p><a href="https://gist.github.com/callstack-bot/e801f1937a8a0fd1bb88d717de1685ff#file-code-snippet6-json">code snippet6.json </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Note: The package name is really important, because it will indicate from where we will import our module.</p><p>It’s also important to add all packages and keep the <strong>exact same version</strong> used in a shared project and target projects.</p><p>Next we need to configure `tsconfig.json` where we can define our build settings.</p><p>Here is an example config file:</p><pre>// packages/shared/tsconfig.json<br>{<br>    &quot;compilerOptions&quot;: {<br>      &quot;target&quot;: &quot;es6&quot;,<br>      &quot;lib&quot;: [&quot;dom&quot;, &quot;dom.iterable&quot;, &quot;esnext&quot;],<br>      &quot;skipLibCheck&quot;: true,<br>      &quot;esModuleInterop&quot;: true,<br>      &quot;allowSyntheticDefaultImports&quot;: true,<br>      &quot;strict&quot;: true,<br>      &quot;forceConsistentCasingInFileNames&quot;: true,<br>      &quot;module&quot;: &quot;commonjs&quot;,<br>      &quot;outDir&quot;: &quot;dist&quot;, // &lt;- Directory of generated output<br>      &quot;moduleResolution&quot;: &quot;node&quot;,<br>      &quot;resolveJsonModule&quot;: true,<br>      &quot;experimentalDecorators&quot;: true,<br>      &quot;strictPropertyInitialization&quot;: false,<br>      &quot;declaration&quot;: true,<br>      &quot;jsx&quot;: &quot;react&quot;<br>    },<br>  }</pre><p><a href="https://gist.github.com/callstack-bot/8d9d72255b264de2fe5982e6875b1ee5#file-code-snippet7-json">code snippet7.json </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Next, let’s create an `index.ts` file inside the `packages/shared` folder.</p><pre>export const add = (a: number, b: number) =&gt; { return a + b;}</pre><p><a href="https://gist.github.com/callstack-bot/623e6fbe1b8241e730478b6c0b24585d#file-code-snippet8-javascript">code snippet8.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Run this command to build the package:</p><pre>$ yarn build</pre><p><a href="https://gist.github.com/callstack-bot/318d2e7c05bbe7576468a600d3a08355#file-code-snippet9-javascript">code snippet9.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Next, we need to add this package as a dependency in our react native project. So inside `packages/mobile/package.json` add `@example-app/shared` as a dependency.</p><p>Note that the version of the package must match the version specified inside packages/shared/package.json. Previously we defined that @example-app/shared version is 1.0.0.</p><pre>// packages/mobile/package.json</pre><pre>&quot;dependencies&quot;: {<br>    &quot;<a href="http://twitter.com/example">@example</a>-app/shared&quot;: &quot;1.0.0&quot;,<br>    ...<br>  },</pre><p><a href="https://gist.github.com/callstack-bot/854fa05f5f544019f109a0d5b691fd76#file-code-snippet10-json">code snippet10.json </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>And also inside the metro.config.js</p><pre>// packages/mobile/metro.config.js</pre><pre>module.exports = {<br>  watchFolders: [<br>    path.resolve(__dirname, &#39;../../node_modules&#39;),<br>+   path.resolve(__dirname, &#39;../../node_modules/@example-app/shared&#39;),<br>  ],<br>};</pre><p><a href="https://gist.github.com/callstack-bot/78f3941f89f05312b9cfcca628b22e86#file-code-snippet11-javascript">code snippet11.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Now, run this command in the root directory, so yarn will set up symlinks for your shared package.</p><pre>$ yarn</pre><p><a href="https://gist.github.com/callstack-bot/f6872dcef8424f3e30326430a86caf8b#file-code-snippet12-javascript">code snippet12.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Right now we should be able to import the add function inside React Native app.</p><pre>import React from &#39;react&#39;;<br>import {Text, TouchableOpacity, View} from &#39;react-native&#39;;<br>import {add} from &#39;<a href="http://twitter.com/example">@example</a>-app/shared&#39;;</pre><pre>const App = () =&gt; {<br>  return (<br>    &lt;View&gt;<br>      &lt;TouchableOpacity<br>        accessibilityRole=&quot;button&quot;<br>        onPress={() =&gt; {<br>          console.log(add(1, 2));<br>        }}&gt;<br>        &lt;Text&gt;Run Add function&lt;/Text&gt;<br>      &lt;/TouchableOpacity&gt;<br>    &lt;/View&gt;<br>  );<br>};</pre><pre>export default App;</pre><p><a href="https://gist.github.com/callstack-bot/5bc1162031483af83707c89aa8854e74#file-code-snippet13-javascript">code snippet13.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><h3>Setting up a React project</h3><p>In order to set up a React project, execute the command below inside `packages/web`:</p><pre>$ npx create-react-app . ExampleApp — template typescript</pre><p><a href="https://gist.github.com/callstack-bot/288c2cb2f518d623ee6f41a75fc542a5#file-code-snippet14-javascript">code snippet14.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Add `@example-app/shared` dependency:</p><pre>// packages/web/package.json”dependencies”: { “@example-app/shared”: “1.0.0”, … },</pre><p><a href="https://gist.github.com/callstack-bot/59500de36f12feadf226b26473b2433e#file-code-snippet15-json">code snippet15.json </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>And we can import and use the shared package:</p><pre>import React from &#39;react&#39;;<br>import {add} from &#39;<a href="http://twitter.com/example">@example</a>-app/shared&#39;;</pre><pre>const App = () =&gt; {<br>  return (<br>    &lt;div&gt;<br>      &lt;button onClick={() =&gt; console.log(add(1,2))}&gt;Run add function&lt;/button&gt;<br>    &lt;/div&gt;<br>  );<br>};</pre><pre>export default App;</pre><p><a href="https://gist.github.com/callstack-bot/68fa870f8ea07910622941afe92555a1#file-code-snippet16-javascript">code snippet16.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><h3>Sharing UI components with React Native Web</h3><p>In order to share UI components, we need React Native Web which provides a compatibility layer between React DOM and React Native.</p><h3>Installation steps</h3><p>Install react-native-web:</p><pre>$ yarn add react-native-web</pre><p><a href="https://gist.github.com/callstack-bot/72f809a51365c0b37ded819c5690e1cf#file-code-snippet17-txt">code snippet17.txt </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Install `babel-plugin-react-native-web`</p><pre>$ yarn add -D babel-plugin-react-native-web</pre><p><a href="https://gist.github.com/callstack-bot/7cdc04d0036a0a9d4768a7fef7cda4fa#file-code-snippet18-txt">code snippet18.txt </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><h3>Modify shared package to export React Native component</h3><p>First inside `packages/shared`, create a new file called `TestComponent.tsx`</p><pre>import { Text, View } from &quot;react-native&quot;;<br>import React from &quot;react&quot;;</pre><pre>const TestComponent = () =&gt; {<br>  return (<br>    &lt;View&gt;<br>      &lt;Text&gt;TestComponent&lt;/Text&gt;<br>    &lt;/View&gt;<br>  );<br>};</pre><pre>export default TestComponent;</pre><p><a href="https://gist.github.com/callstack-bot/da59241be3b409632424ee47865fe3d6#file-code-snippet-19-javascript">code snippet 19.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Next export it from the `index.ts file`:</p><pre>export const add = (a: number, b: number) =&gt; {<br> return a + b;<br>}</pre><pre>export { default as TestComponent } from &#39;./TestComponent.tsx&#39;<a href="https://gist.github.com/callstack-bot/bb1004a508e5d8ec8f671c27e15a66fe#file-code-snippet20-javascript">code snippet20.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></pre><p>Rebuild the shared package inside `packages/shared` folder:</p><pre>$ yarn build</pre><p><a href="https://gist.github.com/callstack-bot/f3f267e8708d9a0ef93a75230228b41a#file-code-snippet21-txt">code snippet21.txt </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>And now we should be able to use TestComponent inside a React app.</p><pre>import React from &#39;react&#39;;<br>import {add, TestComponent} from &#39;<a href="http://twitter.com/example">@example</a>-app/shared&#39;;</pre><pre>const App = () =&gt; {<br>  return (<br>    &lt;div&gt;<br>      &lt;button onPress={() =&gt; console.log(add(1,2))}&gt;Run add function&lt;/button&gt;<br>   &lt;TestComponent/&gt; // &lt;- React Native component inside React app! <br>    &lt;/div&gt;<br>  );<br>};</pre><pre>export default App;</pre><p><a href="https://gist.github.com/callstack-bot/21edfb919df3d7e480d2ff919aa555b7#file-code-snippet22-javascript">code snippet22.javascript </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><h3>To sum up</h3><p>Setting up a monorepo can be tricky, but it pays off in the long run! You can easily share all of your code and assets between React and React Native.</p><p>Using a monorepo is growing in popularity — there is even an open proposal to <a href="https://github.com/react-native-community/discussions-and-proposals/pull/480">migrate react-native repository to monorepo</a>. Find out more about <a href="https://github.com/okwasniewski/react-native-monorepo">React Native monorepo</a> on github.</p><p><em>This article was originally published at </em><a href="https://www.callstack.com/blog/setting-up-react-native-monorepo-with-yarn-workspaces"><em>callstack.com</em></a><em> on October 11, 2022.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4692d6c331d3" width="1" height="1" alt=""><hr><p><a href="https://medium.com/call-stack/setting-up-react-native-monorepo-with-yarn-workspaces-4692d6c331d3">Setting up React Native Monorepo with Yarn Workspaces</a> was originally published in <a href="https://medium.com/call-stack">Callstack Engineers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Comprehensive Guide to Mock Service Worker (MSW)]]></title>
            <link>https://medium.com/call-stack/a-comprehensive-guide-to-mock-service-worker-msw-6044e0225d4e?source=rss-c7a039345e64------2</link>
            <guid isPermaLink="false">https://medium.com/p/6044e0225d4e</guid>
            <category><![CDATA[reactjs]]></category>
            <category><![CDATA[testing]]></category>
            <category><![CDATA[app-development]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Hanna Sobolewska]]></dc:creator>
            <pubDate>Wed, 12 Oct 2022 10:32:11 GMT</pubDate>
            <atom:updated>2022-10-12T10:32:11.898Z</atom:updated>
            <content:encoded><![CDATA[<p>by <a href="https://www.callstack.com/team/aleksandra-desmurs-linczewska">Aleksandra Desmurs-Linczewska</a></p><figure><img alt="smiling woman typing on a computer" src="https://cdn-images-1.medium.com/max/1024/1*zyO12rMEqJrjjRN6GrffkA.jpeg" /></figure><p><a href="https://mswjs.io/">Mock Service Worker</a> is an API mocking tool that lets you mock by intercepting requests on the network level. You can reuse the same mock definition for testing, development, and debugging.</p><p>MSW is delightful to adopt. Plus, it makes testing components with network requests a pleasure.</p><p>In this article, I’d like to share some best practices for working with MSW for basic and more advanced problems.</p><h3>When to use a Mock Service Worker?</h3><p>Has this ever happened to you?</p><p>You’ve finally gotten the green light to spend some writing tests!</p><p>This sprint is calm, but you remembered all too clearly that disastrous release a few weeks ago. The entire team had to drop everything and fix bugs.</p><p>Your repo has around 20% test coverage, and everyone agrees that it’s too little, but there’s never enough time to write tests. You write your features, get an LGTM on the PR, and move on.</p><p>But this release will be different!</p><p>You have a dedicated task, a couple of story points, and a jug of coffee to get this done right. You know the feature you’re about to test very well; you wrote most of it. You set out to mock the component and pass some props.</p><p>The tests fail.</p><p>No worries, that was only the first try, my friend! You re-check what needs testing, add some missing mocks, and maybe throw a jest.spyOn in there. You’re so proud of your accomplishment!</p><p>yarn test — another fail.</p><p>You dig deeper and realize your component depends on a network request returning some data.</p><p>Ok, don’t panic.</p><p>Let’s see how other tests in the codebase manage this. You find tests mocking axios, other ones’ mock fetch, and wait; there are also some global files mocking resolved values and network errors?</p><p>You sweat a little, add <em>many</em> lines of code to your test, and ponder briefly if all of them are necessary. You notice tests unrelated to your changes started failing! You start feeling like the people in the first half of any infomercial.</p><figure><img alt="man eating popcorn" src="https://cdn-images-1.medium.com/max/300/1*hoIafrjp7HQW9rIRJNmWiA.gif" /></figure><p>…and you probably think: there has to be a better way! That’s when <strong>Mock Service Worker comes in handy</strong>.</p><h3>The basic guide to Mock Service Worker (MSW)</h3><p>Mock Service Worker intercepts real network requests that your tests make.</p><p>The components in your tests think they are talking with the <em>real</em> API, which means you can <strong>test their <em>real</em> functionality</strong> (as opposed to testing contained, mock functionality). If you don’t feel convinced about this approach just yet, I invite you to read Kent C. Dodd’s excellent blog post:<a href="https://kentcdodds.com/blog/stop-mocking-fetch"> Stop Mocking Fetch</a>.</p><p>Let’s see this magical library in action. As with any new dependency, you need to <strong>start by adding it to your project:</strong> ‘npm install msw — save-dev or yarn add msw — dev’</p><p>Once the installation finishes, you will have to <strong>define your request handlers</strong>.<a href="https://mswjs.io/docs/getting-started/mocks"> MSW documentation</a> suggests creating them in a file called mocks/handlers.js. Depending on your project, you can create REST or GraphQL handlers. MSW request handlers aim to <strong>hold instructions for specific API endpoints</strong>.</p><p>Let’s take a look at an example REST request handler:</p><pre>// src/mocks/handlers.js<br>import { rest } from “msw”;</pre><pre>export const handlers = [<br> // Handles a POST request<br> rest.post(“<a href="https://fancy-app.com/postToThisEndpoint">https://fancy-app.com/postToThisEndpoint</a>&quot;, (req, res, ctx) =&gt; {<br> return res(<br> // Respond with a 200 status code<br> ctx.status(200)<br> );<br> }),</pre><pre>// Handles a GET request<br> rest.get(“<a href="https://fancy-app.com/getSomeData">https://fancy-app.com/getSomeData</a>&quot;, (req, res, ctx) =&gt; {<br> return res(<br> ctx.status(200),<br> ctx.json({<br> data: “fancy data string”,<br> })<br> );<br> }),<br>];</pre><p><a href="https://gist.github.com/marta-pinkowska/2441ce919c1053770e0d4cad48cc779a#file-msw-test-tsx">msw.test.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>We start by importing the rest function from MSW, then create an array of API endpoints we want to handle.</p><p>We can add anything we would like to this array. We can mock an<strong> error response</strong>; we can mock <strong>correct or faulty data objects</strong>. Remember to use absolute request URLs since we will use those request handlers in a NodeJS environment.</p><p>The only caveat here is that if you add multiple handlers for one API endpoint, the last one in the array will be the only one that’s actually used. But more on that later.</p><p>Once you have a few handlers ready, it is time to let your test suite know about them. We will need to <strong>set up a request mocking server and run it with our tests</strong>. This may sound scary, but don’t worry; the server setup file is three lines long.</p><p>Let’s create a new file called server.js:</p><pre>// src/mocks/server.js<br>import { setupServer } from ‘msw/node’<br>import { handlers } from ‘./handlers’</pre><pre>// This configures a request mocking server with the given request handlers.<br>export const server = setupServer(…handlers)</pre><p><a href="https://gist.github.com/marta-pinkowska/cdd96667b9f2071c4f18a6545c9537fe#file-msw-test-2-tsx">msw.test.2.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>We have to import the ‘setupServer’ function from ‘msw/node’ and pass the previously created request handlers to that function.</p><p>I don’t know about you, but this is the simplest mock server setup I have ever seen!</p><p>The very last step is running the mock server when you run your tests.</p><p>This step depends heavily on your project setup. There are various ways to set up and configure Jest, and this blog post will not try to cover all of them.</p><p>Instead, I’ll talk about the setup I’ve seen the most often: using a dedicated setupTests.js file, which is called through Jest’s<a href="https://jestjs.io/docs/configuration"> setupFilesAfterEv</a>.</p><p>If that’s the case in your project, congratulations! You only need to add the following lines:</p><pre>// src/setupTests.js<br>import { server } from &#39;./mocks/server.js&#39;<br>// Establish API mocking before all tests.<br>beforeAll(() =&gt; server.listen())</pre><pre>// Reset any request handlers that we may add during the tests,<br>// so they don&#39;t affect other tests.<br>afterEach(() =&gt; server.resetHandlers())</pre><pre>// Clean up after the tests are finished.<br>afterAll(() =&gt; server.close())</pre><p><a href="https://gist.github.com/marta-pinkowska/81673bda4122af5fe207230af46dd2ad#file-msw-test-2-tsx">msw.test.2.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>If you prefer to test MSW quickly in a single test file, you can do so as well.</p><p>It is possible to <a href="https://mswjs.io/docs/getting-started/integrate/node#direct-usage">use the mock server directly</a> anywhere you would like. This means you can skip all the steps above (except for the installation, let’s not get carried away!) and write something like this in your test file:</p><pre>// __tests__/FancyPage.test.js<br>import { setupServer } from “msw/node”;<br>import { FancyComponentWithAPICall } from “../FancyComponentWithAPICall”;</pre><pre>const server = setupServer(<br> rest.get(“<a href="https://fancy-app.com/getSomeData">https://fancy-app.com/getSomeData</a>&quot;, (req, res, ctx) =&gt; {<br> return res(ctx.json({ data: “return this string” }));<br> })<br>);</pre><pre>describe(“&lt;FancyComponentWithAPICall /&gt;”, () =&gt; {<br> beforeAll(() =&gt; server.listen());<br> afterAll(() =&gt; server.close());<br> test(“displays data from backend”, async () =&gt; {<br> // Render components, perform requests, receive mocked responses.<br> });<br>});</pre><p><a href="https://gist.github.com/marta-pinkowska/5c6abaeb422dc7b6dbd69004068a6aa2#file-msw-test-4-tsx">msw.test.4.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>This has all been fun and games so far, don’t you think?</p><p>Going through the setup takes less than an hour. Honestly, going through the <a href="https://mswjs.io/docs/getting-started/install">official MSW documentation</a> takes less than an hour!</p><p>If you’re working on a project that’s not too big, you can stop reading now, pat yourself on the back, and look at all those green check marks on your tests.</p><h3>The advanced guide to Mock Service Worker</h3><p>If you are working on a big application, maybe a robust dashboard, or an e-commerce website, you realize the basic setup presented above won’t cut it.</p><p>The handlers array will soon become a 10-thousand-line mess. People may add mock servers in random tests, making debugging errors difficult.</p><p>My team and I have faced those issues, and here’s how we decided to tackle them.</p><p>As stated above, the biggest issue in a big app using MSW is the <strong>handlers’ files becoming unreadable</strong>. We tackled this issue by dividing the <strong>handlers’ files into separate, feature-related files</strong>.</p><p>Now, instead of a single, long ‘handlers.js’, we had something in the shape of the following structure:</p><pre>src<br>│<br>└───tools<br>| └───jest<br>│ │ commonMswHandlers.js<br>│ │ server.js <br>| | setupTests.js<br>│<br>└───featureA<br>│ │ FeatureA.js<br>| |<br>| └───__tests__<br>│ │ FeatureA.test.js<br>│ │<br>│ └───msw<br>│ │ mswHandlers.js<br>│ <br>└───featureB<br>│ │ FeatureB.js<br>| |<br>| └───__tests__<br>│ │ FeatureB.test.js<br>│ │<br>│ └───msw<br>│ │ mswHandlers.js</pre><p><a href="https://gist.github.com/marta-pinkowska/749641d0b87b15cf6fdb994770ff6fee#file-msw-test-5-tsx">msw-test.5.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>A few API endpoints which were commonly needed for the tests and did not clearly fit any feature were left in the ‘commonMswHandlers.js’ file.</p><p>Once we’ve effectively sliced the handlers array, we started wondering how these specific request handlers should be consumed. As we saw above, we could let the test authors import ‘setupServer’ with specific handlers directly in the test files.</p><p>However, this quickly became quite verbose. We decided to create helper functions in our ‘mswHandlers.js’ files. An example file would look like this:</p><pre>// src/FancyHomepageFeature/msw/mswHandlers.js</pre><pre>import { rest } from ‘msw’;<br>// import the server created for the entire test suite<br>// this mock server includes commonMswHandlers<br>import { server } from ‘../tools/jest/server’;</pre><pre>const homeHandlers = [<br> rest.get(‘<a href="https://fancy-app.com/homepage-data&#39;">https://fancy-app.com/homepage-data&#39;</a>, (req, res, ctx) =&gt; {<br> return res(<br> ctx.json({<br> contents: [<br> {<br> banner: ‘Fancy Banner’<br> },<br> ],<br> })<br> );<br> }),<br>];</pre><pre>export const setupHomeHandlers = () =&gt; {<br> server.use(…homeHandlers);<br>};</pre><p><a href="https://gist.github.com/marta-pinkowska/f8bd761b4db21f1248423bdbfc60b4c0#file-msw-test-6-tsx">msw.test.6.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>As you can see in the code above, we’re using the <a href="https://mswjs.io/docs/api/setup-server/use">server.use() function</a>. This function prepends request handlers to the current server instance. This means we are using everything that has been set up in the tools/jest/server.js file, and we’re adding a specific request handler for a specific URL.</p><p>Now, to use this helper function in a test, the test author would need to write something like this:</p><pre>// src/FancyHomepageFeature/__tests__/FancyHomePage.test.js<br>import { FancyHomePage } from &quot;../FancyHomePage&quot;;<br>import { setupHomeHandlers } from &quot;./msw/mswHandlers&quot;;</pre><pre>describe(&quot;&lt;FancyHomePage /&gt;&quot;, () =&gt; {<br>  beforeEach(() =&gt; setupHomeHandlers());<br>  test(&quot;displays homepage data&quot;, async () =&gt; {<br>    // Render homepage with backend data<br>  });<br>});</pre><p><a href="https://gist.github.com/marta-pinkowska/f3fbcb053710b376643a98215b7f31e0#file-msw-test-7-tsx">msw.test.7.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>The test author must import the server helper and run it in a ‘beforeEach’ block.</p><p>Tests in this particular test suite will now look into the ‘homeHandlers’ array when the components need something from the *<a href="https://fancy-app.com/homepage-data*">https://fancy-app.com/homepage-data*</a> endpoint, while other test suites remain unaffected by this change.</p><h3>Testing errors</h3><p>What if you would like to test that your website can handle network errors on specific endpoints?</p><p>Let’s add another helper function to the ‘FancyHomepageFeature/msw/mswHandlers.js’ file:</p><pre>// src/FancyHomepageFeature/msw/mswHandlers.js</pre><pre>import { rest } from &#39;msw&#39;;<br>import { server } from &#39;../tools/jest/server&#39;;</pre><pre>//...</pre><pre>export const setupFaultyHomeHandlers = () =&gt; {<br>  server.use(<br>    rest.get(&#39;<a href="https://fancy-app.com/homepage-data&#39;">https://fancy-app.com/homepage-data&#39;</a>, (_req, res, ctx) =&gt; {<br>      return res(ctx.status(200), ctx.json({weirdDataType: &#39;something went wrong&#39;}));<br>    }),<br>  );<br>};</pre><pre>export const setupFailedHomeHandlers = () =&gt; {<br>  server.use(<br>    rest.get(&#39;<a href="https://fancy-app.com/homepage-data&#39;">https://fancy-app.com/homepage-data&#39;</a>, (_req, res) =&gt; {<br>      return res.networkError(&#39;Failed to connect&#39;);<br>    })<br>  );<br>};</pre><p><a href="https://gist.github.com/marta-pinkowska/e0c347c0e8bc6b0baf101f799b15c37a#file-msw-test-8-tsx">msw.test.8.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>We can add tests for the scenarios described above: <strong>what should happen if the server returns a successful response, but the values are unexpected?</strong> How should the website behave if there is a network error?</p><p>Let’s see those tests in action:</p><pre>// src/FancyHomepageFeature/__tests__/FancyHomePage.test.js<br>import { FancyHomePage } from &quot;../FancyHomePage&quot;;<br>import {<br>  setupHomeHandlers,<br>  setupFaultyHomeHandlers,<br>  setupFailedHomeHandlers,<br>} from &quot;./msw/mswHandlers&quot;;</pre><pre>describe(&quot;&lt;FancyHomePage /&gt;&quot;, () =&gt; {<br>  beforeEach(() =&gt; setupHomeHandlers());<br>  test(&quot;displays homepage data&quot;, async () =&gt; {<br>    // Render homepage with backend data<br>  });<br>});</pre><pre>describe(&quot;&lt;FancyHomePage /&gt; - faulty data&quot;, () =&gt; {<br>  beforeEach(() =&gt; setupFaultyHomeHandlers());<br>  test(&quot;displays readable error when receiving unexpected data&quot;, async () =&gt; {<br>    // Render homepage with error information<br>  });<br>});</pre><pre>describe(&quot;&lt;FancyHomePage /&gt; - network error&quot;, () =&gt; {<br>  beforeEach(() =&gt; setupFailedHomeHandlers());<br>  test(&quot;displays network error&quot;, async () =&gt; {<br>    // Render homepage with network error information<br>  });<br>});</pre><p><a href="https://gist.github.com/marta-pinkowska/3ec5f99e31331926859d0cb2661dc59b#file-msw-test-8-tsx">msw.test.8.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><h3>Request handler overrides</h3><p>If you read the MSW documentation carefully, you may be tempted to use the <a href="https://mswjs.io/docs/api/setup-server/use#one-time-override">one-time override</a> (‘res.once()’) for testing errors.</p><p>We have tried using this strategy in our codebase. We have found that using ‘res.once()’ is<strong> counter-intuitive to the test author</strong>. If the test setup includes this one-time override, but the test suite has more than one test, only the first test will behave as expected.</p><p>It may take the test author quite some time and great detective work to figure out that all his tests were correct, but the MSW handlers were prepared to handle only one request. If I was ever to use ‘res.once()’, it would only be directly in a test file, where it’s easily visible, and never in setup files.</p><h3>Response object overrides</h3><p>There is another type of override that I do recommend using — <strong>response object overrides</strong>.</p><p>Let’s say you would like to test your network request with different, successful responses. You could write separate functions using ‘server.use()’, but that’s a lot of repetitive work.</p><p>One of my colleagues, <a href="https://www.callstack.com/team/jan-jaworski">Jan Jaworski</a>, came up with a very elegant solution to this problem. He created a helper function that could <strong>accept override data and use it in the response object thanks to the spread operator</strong>.</p><p>The function looked roughly like this:</p><pre>export const setupSmartMswHelper = (override = {}) =&gt; {<br>  server.use(<br>    rest.get(&quot;<a href="https://fancy-app.com/return-some-data">https://fancy-app.com/return-some-data</a>&quot;, (req, res, ctx) =&gt; {<br>      return res(<br>        ctx.status(200),<br>        ctx.json({<br>          fancyData: &quot;Im so fancy!&quot;,<br>          moreData: &quot;You already know&quot;,<br>          ...override,<br>        })<br>      );<br>    })<br>  );<br>};</pre><p><a href="https://gist.github.com/marta-pinkowska/8d9e056ca1152fd3ec7d269063263822#file-msw-test-9-tsx">msw.test.9.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Here’s how this helper function would be used in a test:</p><pre>// src/FancyHomepageFeature/__tests__/FancyHomePage.test.js<br>//...<br>test(&quot;handles updated data&quot;, async () =&gt; {<br>  setupSmartMswHelper({<br>    moreData: &quot;Cant you taste this gold?&quot;,<br>  });<br>  //...<br>});</pre><p><a href="https://gist.github.com/marta-pinkowska/eeead2f44adf328dad24b91e5666671f#file-msw-test-10-tsx">msw.test.10.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>This strategy is especially useful for<strong> big data objects we don’t want to re-type multiple times.</strong></p><h3>Testing errors — bonus content</h3><p>Since we started testing network errors, we discovered the terminal output got polluted with many ‘console.error’ messages. These error messages were expected, and we didn’t want them hiding <em>real</em> (as in UNexpected) errors.</p><p>We decided to add a ‘console.error’ override in the Jest setup file:</p><pre>// tools/jest/setupTests.js<br>const error = console.error;</pre><pre>console.error = (...args) =&gt;<br>  // Suppress error messages regarding network error in tests<br>  /Error: Request failed with status code 500/m.test(<br>    args[0]<br>  )<br>    ? void 0<br>    : error(...args);</pre><p><a href="https://gist.github.com/marta-pinkowska/4130ca8d7336d063e41f8cab25f83496#file-msw-test-11-tsx">msw.test.11.tsx </a>hosted with ❤ by <a href="https://github.com/">GitHub</a></p><p>Thanks to this little function, we hid only the specific console errors we were sure about.</p><h3>Summary</h3><p>If you were to take away only one thing from this blog post, I sincerely hope it would be the notion that <strong>MSW is a great tool worth trying, even in a big project</strong>.</p><p>The solutions I described worked great in a real project. They may not be 100% ideal for your needs, but I hope you find some inspiration here to create <strong>the best, most comfortable, and developer-friendly test setup possible.</strong> At the end of the day, we all want to feel like the people at the end of infomercials, no?</p><p><em>This article was originally published at </em><a href="https://www.callstack.com/blog/guide-to-mock-service-worker-msw"><em>callstack.com</em></a><em> on September 27, 2022.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6044e0225d4e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/call-stack/a-comprehensive-guide-to-mock-service-worker-msw-6044e0225d4e">A Comprehensive Guide to Mock Service Worker (MSW)</a> was originally published in <a href="https://medium.com/call-stack">Callstack Engineers</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>