<?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 Daniel Friyia on Medium]]></title>
        <description><![CDATA[Stories by Daniel Friyia on Medium]]></description>
        <link>https://medium.com/@dfriyia?source=rss-d3e2a73e2cbc------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*5xp-ml8FfJglzlhF6ilVxw.jpeg</url>
            <title>Stories by Daniel Friyia on Medium</title>
            <link>https://medium.com/@dfriyia?source=rss-d3e2a73e2cbc------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 18 May 2026 09:20:23 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@dfriyia/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[D3 Charts and React Native Skia for Beginners]]></title>
            <link>https://javascript.plainenglish.io/d3-charts-and-react-native-skia-for-beginners-d7f418e2e2a1?source=rss-d3e2a73e2cbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/d7f418e2e2a1</guid>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[d3js]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[skia]]></category>
            <dc:creator><![CDATA[Daniel Friyia]]></dc:creator>
            <pubDate>Wed, 13 Jul 2022 11:48:35 GMT</pubDate>
            <atom:updated>2022-07-13T11:48:35.863Z</atom:updated>
            <content:encoded><![CDATA[<h4>Learn to draw and Animate Beautiful Charts with React-Native-Skia.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xIt40kOywuiepbwnkdYMtQ.jpeg" /><figcaption><a href="https://www.pexels.com/photo/a-pencil-and-a-paper-with-printed-math-equation-8482035/">Photo by Sergey Meshkov</a></figcaption></figure><p>I’ve said before that D3 is the best, most powerful tool we have in React-Native (and maybe even all mobile development) for creating charts and data visualizations 📈. In the past, I’ve written about how to use React-Native and D3 with React-Native SVG and Re-Animated 2.</p><p>Since writing that article, React-Native Skia has become the better library for presenting and animating D3’s SVG charts. Because of this, I thought I’d write a new article on how to create and animate D3 Charts with React-Native Skia.</p><p>If you get stuck at any point, have a look at my <a href="https://github.com/friyiajr/D3SkiaSample">code sample on Github</a>. Also, feel free to check out my <a href="https://www.youtube.com/watch?v=-a-3gAQB4eg">YouTube tutorial</a> on this subject if you prefer visual learning.</p><h4>What are we Building?</h4><p>As always with my how-to guides, I like to start by showing what we are building. We will be creating the line chart you see in the GIF below complete with the animation between line graphs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*SutwZnXPXj2toSTn3uOGew.gif" /></figure><h4>Getting Started</h4><p>The first thing you’ll want to do is generate the project using this command:</p><pre>npx react-native init MyAwesomeProject --template react-native-template-typescript</pre><p>After this, run the following commands to add D3 and Skia to your project.</p><pre>yarn add @shopify/react-native-skia<br>yarn add d3<br>cd ios &amp;&amp; npx pod install<br>yarn ios</pre><p>Our environment for the project is now set up and ready to go!</p><h4>Familiarizing Ourselves with the Data</h4><p>Let’s start by familiarizing ourselves with the structure of our data. Each point has these values:</p><pre>export type DataPoint = {<br>  date: string;<br>  value: number;<br>};</pre><pre>export const originalData: DataPoint[] = [<br>  {date: &#39;2000-02-01T05:00:00.000Z&#39;, value: 250},<br>  {date: &#39;2000-02-02T05:00:00.000Z&#39;, value: 300.35},<br>  {date: &#39;2000-02-03T05:00:00.000Z&#39;, value: 150.84},<br>  ...</pre><p>All the data for this app can be found in the Data.ts file in the <a href="https://github.com/friyiajr/D3SkiaSample/blob/master/Data.ts">sample project</a>. I recommend copying and pasting it into your project if you are following along.</p><h4>Organizing our Data</h4><p>This next part is almost identical to when you use React-Native SVG. To build a chart, we need to organize our data so it can be handled by D3. The first thing we’ll want to do is add constants for height and width at the top of the file.</p><pre>const GRAPH_HEIGHT = 400<br>const GRAPH_WIDTH = 370</pre><p>After that, we need to create a method that returns an object with our processed chart data in the App.tsx file.</p><pre>const makeGraph = (data: DataPoint[]) =&gt; {};</pre><p>The next step we’ll take is calculating the max and min values in our dataset. These values are used to form the y domain of our chart. This is pretty simple to do, we can just feed the values of our data into the Math.max and Math.min methods.</p><pre>const max = Math.max(...data.map(val =&gt; val.value));<br>const min = Math.min(...data.map(val =&gt; val.value));</pre><p>After that, creating the y axis is as easy as calling scaleLinear in the D3 library. Note the use of GRAPH_HEIGHT in the range. This will ensure all our data points are mapped to y coordinates on the screen that is no greater then the graph’s height.</p><pre>const y = scaleLinear().domain([0, max]).range([GRAPH_HEIGHT, 35]);</pre><p>For the x-axis, we know our data is always going to be fifteen days so we’ll set the starting point and ending points at the first and fifteenth of the month respectively. Note the use of GRAPH_WIDTH in the range. Like the y axis, it maps our values to x coordinates on the screen and makes sure they are no greater than the graph’s width.</p><pre>const x = scaleTime()<br>    .domain([new Date(2000, 1, 1), new Date(2000, 1, 15)])<br>    .range([10, GRAPH_WIDTH - 10]);</pre><p>We then finish off by creating the line chart using the line function from D3.</p><pre>const curvedLine = line&lt;DataPoint&gt;()<br>    .x(d =&gt; x(new Date(d.date)))<br>    .y(d =&gt; y(d.value))<br>    .curve(curveBasis)(data);</pre><p>After this we convert our curved line into a Skia path.</p><pre>const skPath = Skia.Path.MakeFromSVGString(curvedLine!);</pre><p>We return the max, min and skPath values from our function. They will be needed soon to draw our chart.</p><pre>return {<br>    max,<br>    min,<br>    curve: skPath!,<br> };</pre><p>Finally, let&#39;s define a type for the processed Graph Data we just created.</p><pre>interface GraphData {<br>  min: number;  <br>  max: number; <br>  curve: SkPath;<br>}</pre><p>Altogether, our makeGraph function should look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e2ec6299c4ce191c37c9e100c3fc8d8a/href">https://medium.com/media/e2ec6299c4ce191c37c9e100c3fc8d8a/href</a></iframe><h4>Drawing a Single Graph</h4><p>The next thing we’ll do is draw our graph. Let’s start by adding our first data set to the component in App.tsx.</p><pre>const graphData = makeGraph(originalData);</pre><p>At this point, we are in a good position to add the canvas to our app and set its width and height.</p><pre>&lt;Canvas<br>  style={{<br>    width: GRAPH_WIDTH,<br>    height: GRAPH_HEIGHT<br>  }}<br>&gt;<br>&lt;/Canvas&gt;</pre><p>For some style points on our graph, let&#39;s draw some guidelines. You’ll notice the API for drawing lines differs a bit from SVGs. Instead of passing a first and second coordinate, you pass in coordinates for two points and Skia draws a line in between them.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/44f08054ef98148a2ae35bfda311d56f/href">https://medium.com/media/44f08054ef98148a2ae35bfda311d56f/href</a></iframe><p>The last thing we’re going to want to do is to draw our graph. We do this by passing the Skia path we created earlier into the Path component from React-Native Skia.</p><pre>  &lt;Path<br>    <em>style</em>=&quot;stroke&quot;<br>    <em>path</em>={graphData.curve}<br>    <em>strokeWidth</em>={4}<br>    <em>color</em>=&quot;#6231ff&quot;<br>  /&gt;<br>&lt;/Canvas&gt;</pre><p>The canvas code should be in this state.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e9603c63daae245eba481aade0a527f7/href">https://medium.com/media/e9603c63daae245eba481aade0a527f7/href</a></iframe><p>At this point your graph should look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/413/1*wha0kgNs8bYRe98CKgme5w.png" /></figure><h4>Animating Multiple Graphs</h4><p>Finally! The moment we’ve all been waiting for - animating multiple graphs 🙂. You’ll find the Skia animation API to be pretty different from ReAnimated and ReDash if you are used to those libraries but it&#39;s still about as easy to use. This animation is borrowed from the William Candillon video on <a href="https://www.youtube.com/watch?v=xeLdmn3se1I&amp;t=185s">Chart Animations</a>.</p><p>Start by copying in these buttons and adding them under the canvas. We’ll use them later to control the animation.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d259a0a72f6382043f3555cb2df70861/href">https://medium.com/media/d259a0a72f6382043f3555cb2df70861/href</a></iframe><p>Now, back in our component, let&#39;s give it some state.</p><pre>const transition = useValue(1);<br>const state = useValue({<br>  current: 0,<br>  next: 1,  <br>});</pre><p>The transition value here functions similar to a boolean. This value is 1 if the animation is completed and 0 if we need to animate. The state value is the index of the graph that we want to show.</p><p>Now let’s create the transition.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f4ad4ff408ff92b2fc57df2776831bd5/href">https://medium.com/media/f4ad4ff408ff92b2fc57df2776831bd5/href</a></iframe><p>As you can see here, we start by setting the current graph to the index passed in and the previous graph as the current one. The transition value is then set to 0 so that Skia knows an animation needs to take place. runTiming then animates the graph through a number of values between 0 and 1 until the graph animation reaches its completion.</p><p>Next, we use the useComputedValue hook to create SVG paths for all values of the transition using the state we created above.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2874ffbc496372470dd17bc6b4412df1/href">https://medium.com/media/2874ffbc496372470dd17bc6b4412df1/href</a></iframe><p>At this point, you’ll want to make graphData into an array:</p><pre>const graphData: GraphData[] = [<br>  makeGraph(originalData),<br>  makeGraph(animatedData),<br>];</pre><p>Then pass the path into the Skia path component</p><pre>&lt;Path <em>style</em>=&quot;stroke&quot; <em>path</em>={path} <em>strokeWidth</em>={4} <em>color</em>=&quot;#6231ff&quot; /&gt;</pre><p>Finally, add the startTransition method to the pressables we added earlier:</p><pre>&lt;Pressable<br>  <em>onPress</em>={() =&gt; transitionStart(0)}<br>  <em>style</em>={styles.buttonStyle}&gt;<br>  &lt;Text <em>style</em>={styles.textStyle}&gt;Graph 1&lt;/Text&gt;<br>&lt;/Pressable&gt;<br>&lt;Pressable<br>  <em>onPress</em>={() =&gt; transitionStart(1)}<br>  <em>style</em>={styles.buttonStyle}&gt;<br>  &lt;Text <em>style</em>={styles.textStyle}&gt;Graph 2&lt;/Text&gt;<br>&lt;/Pressable&gt;</pre><p>Our final result is the graph in this GIF 📈!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*SutwZnXPXj2toSTn3uOGew.gif" /></figure><h3>Final Thoughts</h3><p>I hope you enjoyed this exercise and through it were able to learn more about D3 Charts and React-Native Skia. I am doing my best as a community member to raise awareness about the power of D3. There’s really no need for the pre-built chart libraries when we have them at our disposal. Until next time, happy coding.</p><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>. Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a><em> and </em><a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a><em>. Check out our </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Community Discord</em></strong></a><em> and join our </em><a href="https://inplainenglish.pallet.com/talent/welcome"><strong><em>Talent Collective</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d7f418e2e2a1" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/d3-charts-and-react-native-skia-for-beginners-d7f418e2e2a1">D3 Charts and React Native Skia for Beginners</a> was originally published in <a href="https://javascript.plainenglish.io">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[iOS Guide to TurboModules in React-Native for Early Adopters]]></title>
            <link>https://javascript.plainenglish.io/ios-guide-to-turbomodules-in-react-native-for-early-adopters-8b2e9ab66852?source=rss-d3e2a73e2cbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/8b2e9ab66852</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[app-development]]></category>
            <dc:creator><![CDATA[Daniel Friyia]]></dc:creator>
            <pubDate>Mon, 27 Jun 2022 04:16:05 GMT</pubDate>
            <atom:updated>2022-07-19T16:03:30.958Z</atom:updated>
            <content:encoded><![CDATA[<h4>Get an early jump on TurboModules and Codegen in React-Native</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rM53csaoDwCUUV5xrLznaw.jpeg" /><figcaption><a href="https://www.pexels.com/photo/space-gray-iphone-8-818043/">Photo by Tuur Tisseghem</a></figcaption></figure><h4><strong>Introduction</strong></h4><p>In the last article, we implemented and enabled <a href="https://javascript.plainenglish.io/android-guide-to-turbomodules-in-react-native-for-early-adopters-b07f3e23fd1c">TurboModules in Android</a>. If you haven’t completed that blog yet, you’ll need to go back and finish it before starting this one. The previous article contains additional instructions you need to complete in TypeScript code. This article will deal with how to get things up and running in iOS. As usual, if you ever get stuck you can check out the <a href="https://github.com/friyiajr/TurboModuleSample">GitHub repo here</a>. If you prefer visual learning, you may want to check out my <a href="https://www.youtube.com/watch?v=MldDH1SYXCE&amp;t=28s">YouTube tutorial</a> on this subject. To recap the last post a bit, we are building the following app that can call into the Native layer using a TurboModule and print a message.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/1*EBhemgVaWY7JB_8QWx39mQ.gif" /></figure><h4>Updating our package.json</h4><p>iOS requires an extra step in the React side to get things up and running. iOS doesn’t have the same ability as gradle to find folders so we need to specify the path to the Spec file in the package.json. You can do this by adding the following code to the end of the file:</p><pre>&quot;codegenConfig&quot;: {<br>  &quot;libraries&quot;: [{<br>    &quot;name&quot;: &quot;NativeSampleModule&quot;,<br>    &quot;type&quot;: &quot;modules&quot;,<br>    &quot;jsSrcsDir&quot;: &quot;./js&quot;<br>  }]<br>}</pre><h4>Enabling Codegen on iOS</h4><p>Next, we’ll need to enable the new architecture on iOS. You can do this by opening the ios folder in Xcode then going to Build Settings. Find the section Other C++ Flags under Apple Clang — Custom Compiler flags and add -DRCT_NEW_ARCH_ENABLED=1.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sAu2PWF4ESZBayJJ5A3RXw.png" /></figure><p>We now have to run a special pod install command for everything to work with the new architecture:</p><pre>RCT_NEW_ARCH_ENABLED=1 pod install</pre><p>You should see a bunch of new architecture libraries being installed.</p><h4>Hooking up Objective-C to React-Native</h4><p>Now that everything’s been enabled we can move on to writing our native code. We start by adding a Podspec file to the js folder. We do this because Cocoapods are used to manage the TurboModule ecosystem and iOS needs to be aware that you are installing a module. Call the file NativeSampleModule.podspec and copy and paste the following contents:</p><pre>folly_version = &#39;2021.06.28.00-v2&#39;</pre><pre>folly_compiler_flags = &quot;-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-shorten-64-to-32&quot;</pre><pre>Pod::Spec.new do |s|<br>  s.name = &quot;NativeSampleModule&quot;<br>  s.version = &quot;0.0.1&quot;<br>  s.summary = &quot;NativeSampleModule&quot;<br>  s.description = &quot;NativeSampleModule&quot;<br>  s.homepage = &quot;&quot;<br>  s.license = &quot;MIT&quot;<br>  s.platforms = { :ios =&gt; &quot;11.0&quot;}<br>  s.author = &quot;&quot;<br>  s.source = { :git =&gt; &quot;https://github.com/facebook/react-native.git&quot;, :tag =&gt; &quot;#{s.version}&quot;}<br>  s.source_files = &quot;./**/*.{h,m,mm,swift}&quot;<br>  s.compiler_flags = folly_compiler_flags<br>  s.pod_target_xcconfig = {<br>    &quot;HEADER_SEARCH_PATHS&quot; =&gt; &quot;\&quot;$(PODS_ROOT)/boost\&quot;&quot;<br>  }<br>  s.dependancy &quot;React&quot;<br>  s.dependancy &quot;React-RCTFabric&quot;<br>  s.dependancy &quot;React-Codegen&quot;<br>  s.dependancy &quot;RCT-Folly&quot;, folly_version<br>  s.dependancy &quot;RCTRequired&quot;<br>  s.dependancy &quot;RCTTypeSafety&quot;<br>  s.dependancy &quot;ReactCommon/turbomodule/core&quot;<br>end</pre><p>Now if we run RCT_NEW_ARCH_ENABLED=1 pod install again we should be able to generate the bindings for Objective-C. If you see something like this it means the Codegen succeeded:</p><pre>[Codegen] &gt;&gt;&gt;&gt;&gt; Processing NativeSampleModule</pre><pre>[Codegen] Generated schema: /var/folders/70/796_sfnj3xn48tzsx0tzz4g80000gn/T/NativeSampleModuleJbRobp/schema.json</pre><pre>[Codegen] Generated artifacts: TurboModuleSampleProject/ios/build/generated/ios/NativeSampleModule</pre><p>Back in Xcode right click the project and select Add files to TurboModuleExampleProject:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/485/1*Pm05zL0Ap4mOop46_EPkWg.png" /></figure><p>Next look for ios &gt; build &gt; generated &gt; ios &gt; NativeSampleModule. Make sure Create Groups is checked and click add:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5RAG9B9_EJldn7BR9KrOsg.png" /></figure><p>At this point you should see the NativeSampleModule package under your TurboModuleSampleProject:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/369/1*NGcNYT3uWXlpWgLklEJx-A.png" /></figure><p>Now create a header file and an Objective-C++ file called RCTNativeSampleModule. In the header file you’ll want to add the following code:</p><pre>#ifndef RCTNativeSampleModule_h<br>#define RCTNativeSampleModule_h</pre><pre>#include &quot;NativeSampleModule.h&quot;</pre><pre><strong>@interface</strong> NativeSampleModule : NSObject&lt;NativeSampleModuleSpec&gt;<br><strong>@end</strong></pre><pre>#endif /* RCTNativeSampleModule_h */</pre><p>Finally, let’s finish things off by making the methods in the Objective-C++ file. The contents of RCTNativeSampleModule.mm should be as follows:</p><pre>#import &lt;Foundation/Foundation.h&gt;</pre><pre>#include &quot;RCTNativeSampleModule.h&quot;</pre><pre><strong>@implementation</strong> NativeSampleModule<br>RCT_EXPORT_MODULE()</pre><pre>- (std::shared_ptr&lt;facebook::react::TurboModule&gt;)getTurboModule:(<strong>const</strong> facebook::react::ObjCTurboModule::InitParams &amp;)params {<br>  <strong>return</strong> std::make_shared&lt;facebook::react::NativeSampleModuleSpecJSI&gt;(params);<br>}</pre><pre>- (NSString *)getHelloWorld:(NSString *)first second:(NSString *)second {<br>  <strong>return</strong> [NSString stringWithFormat:@&quot;HelloWorld %@ %@&quot;, first, second];<br>}</pre><pre><strong>@end</strong></pre><p>Now if you compile with yarn ios we should be able to tap the button and see the alert message.</p><h4>Conclusion</h4><p>So there’s your introduction to TurboModules in React-Native. I am excited for the architecture to move forward with these better tools for calling into native code. Until next time, happy hacking!</p><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>. Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a><em> and </em><a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a><em>. Check out our </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Community Discord</em></strong></a><em> and join our </em><a href="https://inplainenglish.pallet.com/talent/welcome"><strong><em>Talent Collective</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8b2e9ab66852" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/ios-guide-to-turbomodules-in-react-native-for-early-adopters-8b2e9ab66852">iOS Guide to TurboModules in React-Native for Early Adopters</a> was originally published in <a href="https://javascript.plainenglish.io">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Android Guide to TurboModules in React Native for Early Adopters]]></title>
            <link>https://javascript.plainenglish.io/android-guide-to-turbomodules-in-react-native-for-early-adopters-b07f3e23fd1c?source=rss-d3e2a73e2cbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/b07f3e23fd1c</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[android-app-development]]></category>
            <dc:creator><![CDATA[Daniel Friyia]]></dc:creator>
            <pubDate>Mon, 20 Jun 2022 13:17:12 GMT</pubDate>
            <atom:updated>2022-07-07T13:46:59.712Z</atom:updated>
            <content:encoded><![CDATA[<h4>Get an early jump on TurboModules and Codegen in React Native.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cC9PQ00bv1_1CePwcttLhg.jpeg" /><figcaption><a href="https://www.pexels.com/photo/love-people-woman-heart-11035471/">Photo by RealToughCandy.com</a></figcaption></figure><p>When using React Native earlier, we would communicate between the “Native” layer of our application and the “JavaScript” layer using the JavaScript Bridge. Although the bridge served its purpose, it had a few major issues.</p><p>First, the bridge was asynchronous meaning it batched several calls to the native layer and would invoke them at a set interval. If this wasn’t enough, on the native side you had to serialize and deserialize data coming to and from the bridge. These two operations together made things quite slow.</p><p>Second, the bridge was not type safe. You pretty much passed whatever you wanted across the bridge and it was up to the native layer to do something to process that data. Finally, at app startup, all native modules needed to be loaded into memory. This meant slow startup times for users.</p><p>The creators of React Native have introduced Codegen and TurboModules to solve these problems. TurboModules address the async and loading issues because they behave in a synchronous way in JavaScript and lazy load into memory allowing the app to start faster.</p><p>Codegen addresses the problem with type safety because it allows us to generate interfaces we can use to make sure our native code stays in sync with the data we are passing in from the JavaScript layer.</p><p>This guide will show you how to use Codegen and TurboModules together with React Native in Android. <a href="https://javascript.plainenglish.io/ios-guide-to-turbomodules-in-react-native-for-early-adopters-8b2e9ab66852">The second article</a> in this series will address doing the same thing in iOS. Note that this is an early adopters guide intended for React Native 0.68.2 to 0.69.0. The new React Native Architecture is still in flux and may change over time. If you get stuck, feel free to have a look at my sample project <a href="https://github.com/friyiajr/TurboModuleSample">here</a>. If you are interested in my video tutorial on this subject, checkout my <a href="https://www.youtube.com/watch?v=T1-mqNw6LLY&amp;t=932s">video here</a>.</p><p><strong>EDIT:</strong> Users of React-Native 0.69.0 will see false errors in Android Studio stating that imports cannot be found. I’ve complained about <a href="https://github.com/facebook/react-native/issues/34067#issuecomment-1166168608">this issue here</a> and Meta seems to be aware of it. If you follow these instructions and take imports from my sample project when needed the app will still compile just fine. The Android Studio errors are from a bug in their IDE not in this code. It might make sense to do this tutorial in Visual Studio code so you can avoid the Android Studio error noise.</p><h4>What are we building?</h4><p>In this article, we are going to build a simple app that calls into a TurboModule which prints a message. Simple, I know, but with Codegen you can create functions as complex as you like after reading this blog. It will look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*W_UAk-dvgAb4xX6Sgoqs0g.gif" /></figure><h4>The React Native Setup</h4><p>Start by generating a TypeScript project using the following command:</p><pre>npx react-native init TurboModuleSampleProject --template react-native-template-typescript</pre><p>It’s important we use TypeScript because Codegen requires that we use types. A vanilla JS project will not do here.</p><p>Next, let’s create a folder called js at the root of the project. Inside js we are going to create a file called NativeSampleModule.ts. Be very careful to always prefix the name of your file and the Module with the word Native. If you don’t do this, Codegen won’t be able to find your code and won’t generate anything. It doesn’t give you any error here and fails silently. Finish up by copy and pasting this code into your file.</p><pre>import type {TurboModule} from &#39;react-native&#39;;<br>import {TurboModuleRegistry} from &#39;react-native&#39;;</pre><pre>export interface Spec extends TurboModule {<br>  getHelloWorld(first: string, second: string): string;<br>}</pre><pre>export default TurboModuleRegistry.getEnforcing&lt;Spec&gt;(&#39;NativeSampleModule&#39;);</pre><h4>Android Gradle Setup</h4><p>In Android, we start by going to the app level build.gradle and adding this line to the top of the file</p><pre>apply plugin: &quot;com.facebook.react&quot;</pre><p>After that, we need to tell Android where our Codegen file is. We do that by adding this code to line 88</p><pre>react {<br>  jsRootDir = rootProject.file(&quot;../js/&quot;)<br>}</pre><p>Next, find the property enableHermes and set it to be true. The new architecture for React-Native will not run unless you are using Hermes. After that, uncomment the line:</p><pre>preBuild.dependsOn(&quot;generateCodegenArtifactsFromSchema&quot;)</pre><p>Finally, go to the gradle.properties and set newArchEnabled=true</p><p>Run yarn android to generate the files we need</p><h4>Writing our Java Code</h4><p>Now that we have our build configured and have generated the bindings for JavaScript functions let’s open the android folder in Android Studio and write some native code.</p><p>Start by locating the com.turbomodulessampleproject package</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/370/1*HKkuPdU5Aqarkf8Lvp7qpg.png" /></figure><p>Under that package create a new file named NativeSampleModuleImpl.java . Inside this file we are going to extend the interface created by Codegen. It will look like this.</p><pre>package com.turbomodulesampleproject;<br><br>import androidx.annotation.NonNull;<br><br>import com.facebook.fbreact.specs.NativeSampleModuleSpec;<br>import com.facebook.react.bridge.ReactApplicationContext;<br><br>public class NativeSampleModuleImpl extends NativeSampleModuleSpec {<br><br>    public static String <em>NAME </em>= &quot;NativeSampleModule&quot;;<br><br>    public NativeSampleModuleImpl(ReactApplicationContext reactContext) {<br>        super(reactContext);<br>    }<br><br>    @Override<br>    public String getHelloWorld(String first, String second) {<br>        return &quot;HelloWorld: &quot; + first + &quot; &quot; + second;<br>    }<br><br>    @NonNull<br>    @Override<br>    public String getName() {<br>        return <em>NAME</em>;<br>    }<br>}</pre><p>Next, we&#39;ll want to add our package to the application host. To do this find the newarchitecture directory under the turbo modules package from above and look for the MainApplicationReactNativeHost.java file. Override the getPackages method as follows. Import any classes you need with alt + enter</p><pre>@Override<br>protected List&lt;ReactPackage&gt; getPackages() {<br>  List&lt;ReactPackage&gt; packages = new PackageList(this).getPackages();<br><br>  packages.add(new TurboReactPackage() {<br>    @Nullable<br>    @Override<br>    public NativeModule getModule(String name, ReactApplicationContext reactContext) {<br>      if (name.equals(NativeSampleModuleImpl.<em>NAME</em>)) {<br>        return new NativeSampleModuleImpl(reactContext);<br>      } else {<br>        return null;<br>      }<br>    }<br><br>    @Override<br>    public ReactModuleInfoProvider getReactModuleInfoProvider() {<br>      return () -&gt; {<br>        final Map&lt;String, ReactModuleInfo&gt; moduleInfos = new HashMap&lt;&gt;();<br>        moduleInfos.put(<br>                NativeSampleModuleImpl.<em>NAME</em>,<br>                new ReactModuleInfo(<br>                        NativeSampleModuleImpl.<em>NAME</em>,<br>                        NativeSampleModuleImpl.<em>NAME</em>,<br>                        false, // canOverrideExistingModule<br>                        false, // needsEagerInit<br>                        true, // hasConstants<br>                        false, // isCxxModule<br>                        true // isTurboModule<br>                )<br>        );<br>        return moduleInfos;<br>      };<br>    }<br>  });<br><br><br>  return packages;<br>}</pre><h4>Writing the C++ Code</h4><p>The last step we’ll need to take here is configuring the C++ side of things. Start by locating the Android.mk file at this path.</p><pre>TurboModuleSample/android/app/src/main/jni/Android.mk</pre><p>Then uncomment the Codegen paths as follows:</p><pre>include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk</pre><p>then</p><pre>LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni<br>LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/<em>*</em>.cpp)<br>LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni</pre><p>At the bottom add your library. It should be named react_codegen_AppSpec it will look like this:</p><pre>LOCAL_SHARED_LIBRARIES := <em>\<br></em>  react_codegen_AppSpec <em>\</em><br>  libfabricjni <em>\<br></em>  libfbjni <em>\<br></em>  libfolly_futures <em>\<br></em>  libfolly_json <em>\<br></em>  libglog <em>\<br></em>  libjsi <em>\<br></em>  libreact_codegen_rncore <em>\<br></em>  libreact_debug <em>\<br></em>  libreact_nativemodule_core <em>\<br></em>  libreact_render_componentregistry <em>\<br></em>  libreact_render_core <em>\<br></em>  libreact_render_debug <em>\<br></em>  libreact_render_graphics <em>\<br></em>  librrc_view <em>\<br></em>  libruntimeexecutor <em>\<br></em>  libturbomodulejsijni <em>\<br></em>  libyoga <em>\</em></pre><p>Then in the android/app/src/main/jni/MainApplicationModuleProvider.cpp file add #include &lt;AppSpec.h&gt; and uncomment and replace the following lines:</p><pre>#include &lt;AppSpec.h&gt;</pre><pre>....</pre><pre>auto module = AppSpec_ModuleProvider(moduleName, params);<br>if (module != nullptr) {<br>    return module;<br>}</pre><p>At this point lets run yarn android to make sure the app compiles.</p><h4>The Triumphant Return to React Native</h4><p>Let’s finish up by testing everything out. Anywhere in your App.tsx file add the following code.</p><pre>import NativeSampleModule from &#39;./js/NativeSampleModule&#39;;</pre><pre>...<br>const showMessage = () =&gt; {<br>  const message = NativeSampleModule.getHelloWorld(&#39;Daniel&#39;, &#39;Friyia&#39;);<br>  alert(message);<br>};</pre><pre>...<br>&lt;Button title=&quot;Click here&quot; onPress={showMessage} /&gt;</pre><p>When you click the button you should see an alert pop up with the message we created in the native layer.</p><h4>Conclusion</h4><p>Hopefully, you enjoyed this introduction to TurboModules in React Native for Android. Soon enough they will be removing the old bridge so it’ll be important for us to stay up to date with how TurboModules are coming along. <a href="https://javascript.plainenglish.io/ios-guide-to-turbomodules-in-react-native-for-early-adopters-8b2e9ab66852">Please check out part two </a>where I show you how to get TurboModules and Codegen to work on iOS.</p><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>. Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a><em> and </em><a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a><em>. Check out our </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Community Discord</em></strong></a><em> and join our </em><a href="https://inplainenglish.pallet.com/talent/welcome"><strong><em>Talent Collective</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b07f3e23fd1c" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/android-guide-to-turbomodules-in-react-native-for-early-adopters-b07f3e23fd1c">Android Guide to TurboModules in React Native for Early Adopters</a> was originally published in <a href="https://javascript.plainenglish.io">JavaScript in Plain English</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 & the JavaScript Interface: A Guide for Early Adopters]]></title>
            <link>https://javascript.plainenglish.io/react-native-the-javascript-interface-a-guide-for-early-adopters-c42c46f6fe4b?source=rss-d3e2a73e2cbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/c42c46f6fe4b</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[app-development]]></category>
            <category><![CDATA[jsi]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react-native]]></category>
            <dc:creator><![CDATA[Daniel Friyia]]></dc:creator>
            <pubDate>Mon, 16 May 2022 15:19:39 GMT</pubDate>
            <atom:updated>2022-05-16T20:06:36.996Z</atom:updated>
            <content:encoded><![CDATA[<h4>Part 2— Setting up the JavaScript Interface with Android</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yN_UmZek4ehFXitTNdPDZw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@ffstop?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Fotis Fotopoulos</a> on <a href="https://unsplash.com/s/photos/programming?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Now for the moment, we’ve all been waiting for! Setting up the JSI to work with Android. If you haven’t yet, <a href="https://javascript.plainenglish.io/react-native-the-javascript-interface-a-guide-for-early-adopters-f08274e86de9">please read Part 1 of this series</a> to see how to set things up in iOS.</p><p>Special thanks again to Oscar Franco for this article. Although I haven’t seen any content from him on the Android side of things I rummaged through his “Quick SQLite for React-Native” library to figure out how to do everything. He is the true master of this tech, not me, I am just a humble instructor. Feel free to rummage through his code after this article to learn more. Hopefully, I can give you the tools to do so!</p><p><a href="https://github.com/ospfranco/react-native-quick-sqlite">GitHub - ospfranco/react-native-quick-sqlite: Fast SQLite for react-native.</a></p><p>Remember, this is a really hard process. If you get stuck check out the <a href="https://github.com/friyiajr/EarlyJSITutorial"><strong>GitHub project here.</strong></a><strong> </strong>I will refer back to it a lot because this article requires a lot of long files.</p><p>🚨 <strong>NOTE:</strong> If you are on an M1, you’ll need to follow <a href="https://github.com/flutter/flutter/issues/76393#issuecomment-784014307"><strong>these additional steps </strong></a>before starting the article.</p><h4>Setting up the Android Build System</h4><p>Remember how in iOS we started writing C++ code out of the box? Unfortunately, in Android, this is not the case. C++ development is a kind of second-class citizen where Android Studio forces you to set up all the build steps manually.</p><h4>Configuring the build.gradle</h4><p>The first thing we are going to do is update thebuild.gradle file at the library level with some new code. At the top of the file add these two imports:</p><pre>import org.apache.tools.ant.filters.ReplaceTokens<br>import java.nio.file.Paths</pre><p>Next, update your gradle tools to the following:</p><pre>classpath &#39;com.android.tools.build:gradle:4.2.2&#39;</pre><p>Add this code to the file before the android block. We’ll use it later to get the path to the node_modules.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/080fd755861a4b38ed3a7a4e7181b414/href">https://medium.com/media/080fd755861a4b38ed3a7a4e7181b414/href</a></iframe><p>Add this code right after the function so that we can use the React-Native version in our build later on. We’ll also be using this to pass the path to all the Facebook React-Native libraries into the C++ build system.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a41c5be13002b8887982177cfd025c96/href">https://medium.com/media/a41c5be13002b8887982177cfd025c96/href</a></iframe><p>Under the externalNativeBuild block in the defaultConfig copy and paste this cmake command. Notice we use the node module path and React-Native version here. We are actually passing these values to the C++ build system for Android.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f14f1f716cfa9c2ae1200368a00da49b/href">https://medium.com/media/f14f1f716cfa9c2ae1200368a00da49b/href</a></iframe><p>Add packaging options to the top level of the gradle file. It will prevent duplicate facebook RN libraries from being generated.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/84ff68432ca202ba02eb29d497b680ab/href">https://medium.com/media/84ff68432ca202ba02eb29d497b680ab/href</a></iframe><p>Finally, add this code for configurations we are going to write this code in a moment, but it&#39;s code that executes during the build steps.</p><pre>configurations {<br>  extractHeaders<br>  extractJNI<br>}</pre><p>Under repositories add the following code which finds the React-Native Android sources.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e028b36f07dac85e8baf2654ecaf214e/href">https://medium.com/media/e028b36f07dac85e8baf2654ecaf214e/href</a></iframe><p>Then under dependencies add this code so that we can extract the JNI files for React-Native and add them to the project.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b65fbc69dfc7a613bfbd30c91058e494/href">https://medium.com/media/b65fbc69dfc7a613bfbd30c91058e494/href</a></iframe><p>Finally, copy and paste these functions at the bottom of the file. These facilitate the addition of JNI files to the project.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2287ace3f2eba454eef1454ddbbbb1f5/href">https://medium.com/media/2287ace3f2eba454eef1454ddbbbb1f5/href</a></iframe><p>Normally, at this point, I would show you the whole thing together. Unfortunately this time we’ve made a massive file. Don’t worry though, you can have a look at this all together in my <a href="https://github.com/friyiajr/EarlyJSITutorial/blob/master/android/build.gradle"><strong>GitHub repo here</strong></a>.</p><h4>Setting up the Android C++ Build System</h4><p>With the CMakeLists.txt file we are just going to start from scratch. Most likely you’ve never made one of these before and it&#39;s really intimidating. Don’t worry about it though. These are actually pretty easy to understand once someone has talked you through them. Let&#39;s start by setting up a few variables:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/809ef24876d44ef27086a6d354cccdd7/href">https://medium.com/media/809ef24876d44ef27086a6d354cccdd7/href</a></iframe><p>Next, we’ll have to set a few more variables if you are using a React Native version of less than 68.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f68967d7b85ce0f4841bef6133c5d1f3/href">https://medium.com/media/f68967d7b85ce0f4841bef6133c5d1f3/href</a></iframe><p>After this, we’ll have to tell the C++ build system which directories we want to require files from. At the top, we put our cpp folder then follow this up with a list of all the libraries we want to include.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/25ecebcf1536c838295abe626ea1d3c7/href">https://medium.com/media/25ecebcf1536c838295abe626ea1d3c7/href</a></iframe><p>We then have to add libraries to our build. We do this with the following code.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6e80cd905556c4369d4ef96ad827ee48/href">https://medium.com/media/6e80cd905556c4369d4ef96ad827ee48/href</a></iframe><p>Next, tell the build where our included directories can be found. You’ll find this list is similar to the one earlier.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/40a865f602b6b46fe02d93c6e4798a48/href">https://medium.com/media/40a865f602b6b46fe02d93c6e4798a48/href</a></iframe><p>At this point, we are going to finish up by adding libraries to our build and assigning those libraries to variables. You can do this as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/aadb6e09ed569dffc610792a77dd0f4f/href">https://medium.com/media/aadb6e09ed569dffc610792a77dd0f4f/href</a></iframe><p>Finally, we finish up by linking all these libraries when the build completes.</p><pre>target_link_libraries(<br>  ${PACKAGE_NAME}<br>  ${LOG_LIB}<br>  ${JSI_LIB}<br>  ${REACT_NATIVE_JNI_LIB}<br>  ${FBJNI_LIB}<br>  android<br>)</pre><p>Again this file is crazy long. To see all this code together check out my <a href="https://github.com/friyiajr/EarlyJSITutorial/blob/master/android/CMakeLists.txt"><strong>GitHub repo here</strong></a><strong>.</strong></p><h4>Adding your First Android C++ Code</h4><p>To get everything to compile, go to your cpp-adapter.cpp file and add this code:</p><pre>#include &lt;jni.h&gt;<br>#include &lt;jsi/jsi.h&gt;<br>#include &lt;fbjni/fbjni.h&gt;<br>#include &lt;ReactCommon/CallInvokerHolder.h&gt;<br>#include &lt;typeinfo&gt;<br>#include &lt;android/log.h&gt;<br>#include &quot;react-native-teaching-jsi.h&quot;</pre><pre>using namespace facebook;</pre><pre>JNIEXPORT jint JNI_OnLoad(JavaVM * vm, void * ) {</pre><pre>}</pre><p>At this point run your app and make sure it compiles. Awesome right! You’ve built your first C++ library! Unfortunately, your app will instantly crash on launch 🙃. Isn’t the Android C++ build system great?</p><h4>Finishing up the CPP Adapter</h4><p>Just like in iOS we need to run some code to tell the app that we are installing a function in the global JS object. We start this by creating a struct in cpp-adapter.cpp. Note the use of installMath this is the C++ function we wrote in Part 1.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4b45c2bfaace4482a168e48279a8362a/href">https://medium.com/media/4b45c2bfaace4482a168e48279a8362a/href</a></iframe><p>Be very careful about the kJavaDescriptor variable. That string has to match the path to your Java package. If you didn’t copy my naming you’ll need to adapt this to your app. If it’s wrong, the app will crash frequently and it will be hard to debug.</p><p>After that, we call the initialize function when the app starts.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1f09687ac7376fca67709f8ef777ebd1/href">https://medium.com/media/1f09687ac7376fca67709f8ef777ebd1/href</a></iframe><p>The app will still crash if you try and compile it, however, that should take care of all the C++ we need. To double-check your code <a href="https://github.com/friyiajr/EarlyJSITutorial/blob/master/android/cpp-adapter.cpp"><strong>have a look at this file</strong></a><strong>. </strong>In the next section, let&#39;s fix this crash and get everything up and running.</p><h4>Writing our Java Code to Link with JavaScript</h4><p>I wish I could tell you the weirdness of setting up the C++ part of this build ended there, but unfortunately that&#39;s not the case. We now need to set up the Java code that links the C++ code to the JS engine.</p><h4>The Android Native Java Class</h4><p>The first thing we’ll do is create a class called AndroidNative. It&#39;s going to act as the interface between Java and C++. Start the file off by adding these imports:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8af85038067eae88aa5d574d979156b5/href">https://medium.com/media/8af85038067eae88aa5d574d979156b5/href</a></iframe><p>Next, add this code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0de5c46902427d885ba71df1add03a4f/href">https://medium.com/media/0de5c46902427d885ba71df1add03a4f/href</a></iframe><p>Note the use of public native void here. Methods marked native in Java can call directly into C++. We are going to be using that method to “install” our C++ methods into the JS global object.</p><p>Add these lines to the file because they are required by the React-Native framework:</p><pre>public AndroidNative(ReactApplicationContext reactContext) {<br>  <em>super</em>(reactContext);<br>}</pre><pre>@Override<br>@NonNull<br>public String getName() {<br>  return NAME;<br>}</pre><p>Finish up by adding the install method. This loads the C++ library and calls the install function. Note the use of isBlockingSynchronousThread. This needs to be set to true in order to have the library load at app startup.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e4c6799d975d73da714f91f8602d91b9/href">https://medium.com/media/e4c6799d975d73da714f91f8602d91b9/href</a></iframe><h4>Making the JSI Module Package</h4><p>At this point, we’ll use the code from the previous section. Really all it does is get our native module and call the install function we created earlier.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f1bd863523477228d108284dff4332a4/href">https://medium.com/media/f1bd863523477228d108284dff4332a4/href</a></iframe><h4>Making the React Package</h4><p>The last of the code we need to write is the React Package which is what allows React-Native to see our code. We simply create this file and add our Android Native class to it.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1805de499e7c04ff099b1095c74ead54/href">https://medium.com/media/1805de499e7c04ff099b1095c74ead54/href</a></iframe><h4>Add Library to your Example App</h4><p>Add this code to the React Native host in your MainApplication.java file in the example app.</p><pre><em>import </em>com.facebook.react.bridge.<em>JSIModulePackage</em>;<br><em>import </em>com.reactnativeteachingjsi.TeachingJsiModule;<br><em>import </em>com.reactnativeteachingjsi.TeachingJsiPackage;<br><br><em>public class </em>MainApplication <em>extends </em>Application <em>implements ReactApplication </em>{<br><br>  <em>private final </em>ReactNativeHost mReactNativeHost =<br>      <em>new </em>ReactNativeHost(<em>this</em>) {<br><br>        @Override<br>        <em>protected JSIModulePackage </em>getJSIModulePackage() {<br>          <em>return new </em>TeachingJsiPackage();<br>        }</pre><p>You’ll also want to change the package in MainApplication to be:</p><pre><a href="http://twitter.com/Override">@Override</a><br>protected List&lt;ReactPackage&gt; getPackages() {<br>  <a href="http://twitter.com/SuppressWarnings">@SuppressWarnings</a>(&quot;UnnecessaryLocalVariable&quot;)<br>  List&lt;ReactPackage&gt; packages = new PackageList(this).getPackages();<br>  // Packages that cannot be autolinked yet can be added manually here, for TeachingJsiExample:<br>  // packages.add(new MyReactNativePackage());<br>  packages.add(new TeachingJsiModule());<br>  return packages;<br>}</pre><p>Check out the entire <a href="https://github.com/friyiajr/EarlyJSITutorial/blob/master/example/android/app/src/main/java/com/example/reactnativeteachingjsi/MainApplication.java"><strong>MainApplication.java file here</strong>.</a></p><h4>Conclusion</h4><p>At this point if you run the app you should see the following:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*CsWlF8emfbF5tWz_A7F9yQ.gif" /></figure><p>Wow, that was a lot of work, wasn’t it? I personally can’t wait until the JSI libraries are ready for general consumption so we don’t have to do all this. Either way, I hope you enjoyed the journey and have fun hacking with the base project 🙂.</p><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>. Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a><em> and </em><a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a><em>. Check out our </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Community Discord</em></strong></a><em> and join our </em><a href="https://inplainenglish.pallet.com/talent/welcome"><strong><em>Talent Collective</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c42c46f6fe4b" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/react-native-the-javascript-interface-a-guide-for-early-adopters-c42c46f6fe4b">React Native &amp; the JavaScript Interface: A Guide for Early Adopters</a> was originally published in <a href="https://javascript.plainenglish.io">JavaScript in Plain English</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 & the JavaScript Interface: A Guide for Early Adopters]]></title>
            <link>https://javascript.plainenglish.io/react-native-the-javascript-interface-a-guide-for-early-adopters-f08274e86de9?source=rss-d3e2a73e2cbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/f08274e86de9</guid>
            <category><![CDATA[app-development]]></category>
            <category><![CDATA[jsi]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[react-native]]></category>
            <dc:creator><![CDATA[Daniel Friyia]]></dc:creator>
            <pubDate>Mon, 16 May 2022 14:17:49 GMT</pubDate>
            <atom:updated>2022-05-16T17:52:41.486Z</atom:updated>
            <content:encoded><![CDATA[<h4><em>Part 1 — Setting up the JavaScript Interface with iOS</em></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3_fh5f58n5OLa4Y_lPKtvg.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@jakewalker?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Jake Walker</a> on <a href="https://unsplash.com/s/photos/code-ios-swift-xcode?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>My journey as a programmer began around the time smartphones became popular. I can still remember the excitement I felt compiling my first hello world app on an Android phone at university. As my career progressed, I worked with Bluetooth Low Energy, and C++ libraries, and wrote highly optimized apps. Nothing is as exciting to me as getting the most I can out of the hardware I am working on.</p><p>In React-Native, this was hard to do for a long time because we had to pass values back and forth across the JavaScript bridge. Fortunately, the team at Meta recently exposed JavaScript Interface (JSI) modules. JSI Modules can call native functions synchronously through shared memory.</p><p>Although JSI Modules are not yet in a state where they are ready for general consumption, they are powerful enough to experiment with and prepare for when the real thing is released.</p><p>This article is the first of a two-part series. The goal of this series is to make a quick, easy, copy-paste guide to JSI modules so you can start experimenting with them as soon as possible. As far as I can tell, nothing like this exists in the community and is sorely needed.</p><p><strong>Part 1</strong> is based on the YouTube playlist by Oscar Franco on setting up JSI with iOS. If you want a long, in-depth explanation of things, I recommend you go <a href="https://www.youtube.com/watch?v=DA3KXef81sg&amp;list=PLanS_SVm5swimC_m5zWfly0EPJTk7Tsp8">here</a> and check out his channel.</p><p><a href="https://javascript.plainenglish.io/react-native-the-javascript-interface-a-guide-for-early-adopters-c42c46f6fe4b"><strong>Part 2</strong></a> no one has talked about as far as I can tell. This is <a href="https://javascript.plainenglish.io/react-native-the-javascript-interface-a-guide-for-early-adopters-c42c46f6fe4b">setting up JSI Modules for Android</a>. Never fear though, I’ve labbed 🧑‍🔬 out this process for you and will explain everything there.</p><p>Remember, if you get stuck, check out the <a href="https://github.com/friyiajr/EarlyJSITutorial"><strong>GitHub project here.</strong></a></p><h4>What are we building today?</h4><p>As always, I want to explain what we are building before we build it. Today’s project will seem, at face value, a little boring. That being said, this project is really about learning to set up the JSI. Once you have that knowledge you can make modules as complex as you like.</p><p>Here we are creating an app to calculate the Greatest Common Denominator using a C++ function that will be shared between Android and iOS.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*770prCX1ohXgJrrzbRmPeA.gif" /><figcaption>Our app running on iOS</figcaption></figure><h4>Generating the Library Boilerplate</h4><p>Currently, there is no easy way to generate a JSI library. Instead, what we are going to do is generate a JavaScript bridge library and migrate it over to a JSI lib. The first thing you’ll want to do is run this command:</p><p>npx create-react-native-library react-native-teaching-jsi</p><p>You can just hit enter until you get to this menu:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hSRX0Ym8nUtBhXdAGrRE5w.png" /></figure><p>Make sure you select C++ for Android and iOS here. This will make sure all the C++ code we write is fully cross-platform.</p><h4>Remove Flipper for Faster Compilation (Optional)</h4><p>Before starting, I recommend you comment on Flipper in your example/Podfile. It has a lot of broken releases and sometimes causes things to not compile. When you are done with the tutorial you can always circle back and try to set it up if you feel inclined.</p><h4>Making the Cross-Platform Code</h4><p>After generating the template, you’ll want to start by running yarn in the root of your project to install all the dependencies. Next run open example/ios/TeachingJsiExample.xcworkspace from the project root to open Xcode in the project example. It will seem strange to most but we’ll be editing our Pods from there. We do this so Xcode can give us auto-complete functionality. I recommend trying to run the app from Xcode at this point to make sure everything is working properly. You should see a blank screen with the text “Result: 21”.</p><p>Next, find the library files in Xcode under Pods/Development Pods. It will look like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/266/1*Au8uAPQ4ZYe5CL23Enk0ZA.png" /></figure><p>Update the contents of the react-native-teaching-jsi.h file to the following:</p><pre>#ifndef react_native_teaching_jsi_h<br>#define react_native_teaching_jsi_h</pre><pre>#include &lt;jsi/jsilib.h&gt;<br>#include &lt;jsi/jsi.h&gt;</pre><pre><strong>using</strong> <strong>namespace</strong> facebook;</pre><pre><strong>void</strong> installMath(jsi::Runtime &amp;rt);</pre><pre>#endif /* my_cpp_module_hpp */</pre><p>Next, move over to the react-native-teaching-jsi.cpp file. Here we are going to write our shared function to calculate Greatest Common Denominator in C++. Pretty cool right?</p><p>Let’s start by using the facebook namespace and writing a fast GCD function. It will look like this.</p><pre>#include &quot;react-native-teaching-jsi.h&quot;</pre><pre><strong>using</strong> <strong>namespace</strong> facebook;</pre><pre><strong>int</strong> computeGcd(<strong>int</strong> a, <strong>int</strong> b) {<br>  <strong>while</strong> (b) b ^= a ^= b ^= a %= b;<br>  <strong>return</strong> a;<br>}</pre><p>Surely by now, you must be curious. How do we tell JavaScript/TypeScript that this function exists? The way this happens is by getting access to the JavaScript runtime and “installing” the various functions you want to use in the JS Global object. Before we do that though we need to create the install function that registers compute gcd.</p><p>Add this function to your react-native-teaching-jsi.h file.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b4066daecdc591c07063dbacaf6bd692/href">https://medium.com/media/b4066daecdc591c07063dbacaf6bd692/href</a></iframe><p>I am sure that function is quite a lot to digest 😅 so let&#39;s break it down.</p><pre><strong>void</strong> installMath(jsi::Runtime &amp; rt) {</pre><p>The function header takes in a reference to the jsi::Runtime. This is required to access the JS engine and call our functions from JavaScript.</p><pre><strong>auto</strong> propId = jsi::PropNameID::forAscii(rt, &quot;gcd&quot;);</pre><p>The prop id is just a unique id for our function.</p><pre><strong>auto</strong> lamda = [](jsi::Runtime &amp; rt,<br>    <strong>const</strong> jsi::Value &amp; thisValue,<br>    <strong>const</strong> jsi::Value * args,<br>    size_t count<br>  ) -&gt; jsi::Value {<br>    <strong>auto</strong> data = args-&gt;asObject(rt);<br>    <strong>auto</strong> aValue = data.getProperty(rt, &quot;a&quot;);<br>    <strong>auto</strong> bValue = data.getProperty(rt, &quot;b&quot;);<br>    <strong>int</strong> a = aValue.asNumber();<br>    <strong>int</strong> b = bValue.asNumber();<br>    <strong>int</strong> gcd = computeGcd(a, b);<br>    <strong>return</strong> jsi::Value(gcd);<br>  };</pre><p>The code above is where things get interesting. This C++ lambda function extracts data from the JavaScript Interface and converts it into primitive values we can use. We use the utility methods asObject and getProperty to convert the raw data into data types that can be processed by C++.</p><pre>jsi::Function gcd = <br>      jsi::Function::createFromHostFunction(rt, propId, 2, lamda);</pre><pre>rt.global().setProperty(rt, &quot;jsiGcd&quot;, gcd);</pre><p>We then finish up by calling rt.global() which tells JavaScript we want to register this function on the global module.</p><h4>Registering the Function on the JavaScript Runtime</h4><p>The last step we need to take before calling this function from JavaScript is to install our function in the JavaScript runtime. We need to write a little bit of Objective-C code here. This Obj-C code is really just the glue between C++ and JavaScript.</p><p>Under the iOS directory, find the TeachingJsi.h file and add the following code:</p><pre><strong>@interface</strong> TeachingJsi : NSObject &lt;RCTBridgeModule&gt;<br>  <strong>@property</strong>(<strong>nonatomic</strong>, <strong>assign</strong>) <strong>BOOL</strong> setBridgeOnMainQueue;<br><strong>@end</strong></pre><p>This tells Objective-C you will be registering the function on the main thread which is required for the JSI to work.</p><p>Once you’ve completed this go into your TeachingJsi.mm file. Start by adding these imports:</p><pre>#import &lt;React/RCTBridge+Private.h&gt;<br>#import &lt;React/RCTUtils.h&gt;<br>#import &lt;jsi/jsi.h&gt;<br>#import &lt;ReactCommon/CallInvoker.h&gt;<br>#import &lt;memory&gt;</pre><p>Then under @implementation add this code:</p><pre>@synthesize bridge = _bridge;</pre><p>After exporting the module you’ll want to tell Objective-C that you will be registering your method on the main thread:</p><pre>+ (BOOL)requiresMainQueueSetup {<br>  return YES;<br>}</pre><p>Next set up the bridge:</p><pre>- (<strong>void</strong>)setBridge:(RCTBridge *)bridge {<br>  _bridge = bridge;<br>  _setBridgeOnMainQueue = RCTIsMainQueue();<br>  RCTCxxBridge *cxxBridge = (RCTCxxBridge *)<strong>self</strong>.bridge;<br>  <br>  <strong>if</strong>(!cxxBridge.runtime) {<br>    <strong>return</strong>;<br>  }<br>  installMath(*(facebook::jsi::Runtime *) cxxBridge.runtime);<br>}</pre><p>Finish off by deleting all other code in the file. Everything together should look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6d6258e6db8ebf1d7fea4bcaf637fe94/href">https://medium.com/media/6d6258e6db8ebf1d7fea4bcaf637fe94/href</a></iframe><h4>Finishing things off</h4><p>The last thing you’ll want to do is check that all the code we’ve written so far works as expected. Since this isn’t an article on how to make UIs, just copy and paste my UI code into your App.tsx.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a4875f295ff4e152043fd0dad96ace87/href">https://medium.com/media/a4875f295ff4e152043fd0dad96ace87/href</a></iframe><p>Your final result should be something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*770prCX1ohXgJrrzbRmPeA.gif" /></figure><h4><strong>Conclusion</strong></h4><p>And there you have it! Setting up JSI with iOS. <a href="https://javascript.plainenglish.io/react-native-the-javascript-interface-a-guide-for-early-adopters-c42c46f6fe4b">Stay tuned for Part 2 </a>where I’ll be going over how to get this to work with Android. Fair warning, that article isn’t going to be anywhere near this easy. If you haven’t worked with the Java Native Interface (JNI) or CMakeLists before it’ll be a bit of a ride. I promise though that it’ll be fun and really interesting 🙂. Look forward to seeing you there!</p><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>. Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a><em> and </em><a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a><em>. Check out our </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Community Discord</em></strong></a><em> and join our </em><a href="https://inplainenglish.pallet.com/talent/welcome"><strong><em>Talent Collective</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f08274e86de9" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/react-native-the-javascript-interface-a-guide-for-early-adopters-f08274e86de9">React Native &amp; the JavaScript Interface: A Guide for Early Adopters</a> was originally published in <a href="https://javascript.plainenglish.io">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Transforming a Messy Swift Codebase to MVVM — A Case Study]]></title>
            <link>https://medium.com/tribalscale/transforming-a-messy-swift-codebase-to-mvvm-a-case-study-d81a23f6a22c?source=rss-d3e2a73e2cbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/d81a23f6a22c</guid>
            <category><![CDATA[mvvm]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[development]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Daniel Friyia]]></dc:creator>
            <pubDate>Tue, 05 Apr 2022 18:27:26 GMT</pubDate>
            <atom:updated>2023-04-24T20:25:12.197Z</atom:updated>
            <content:encoded><![CDATA[<h3>Transforming a Messy Swift Codebase to MVVM — A Case Study</h3><p><em>Written by: Daniel Friyia, Agile Software Engineer, TribalScale</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*3rk2kQNI7dihnd8z.png" /></figure><h4>📫 <a href="https://www.tribalscale.com/weekly-digest-subscription">Subscribe to receive our content here.</a></h4><h4>💬 Have any questions about transforming a swift codebase to MVVM? <a href="https://www.tribalscale.com/schedule-a-chat">Click here to chat with one of our experts!</a></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*mOqKP_rsAFEwSXL0.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nmuEPkwpSDv7lOKs55wFZQ.jpeg" /><figcaption>Photo Courtesy of <a href="https://unsplash.com/@raagesh">Raagesh C</a> on <a href="https://unsplash.com">Unsplash</a></figcaption></figure><p>We’ve all been there, you get put in charge of a codebase written by another group of developers and you have to maintain it. Problem is, all those developers left the company awhile ago and you have no idea why any decisions were made. This isn’t always a bad experience. I can think of times where developers before me made good decisions and it was easy to dive in and start making changes 🙂. Recently though, my team had a really negative experience with a messy codebase that had basically no architecture to speak of 😞. In this article I’ll be talking about how we went about refactoring this app piece by piece into something we could maintain. Obviously every codebase is different so this article isn’t meant to be a strategy for all refactors. That being said, I hope you’ll pick up a few good ideas from our experience that you can implement when doing architectural refactors in your project.</p><h3><strong>Diagnosing the Health of an Inherited Codebase</strong></h3><p>When starting out with any project it’s first important to understand what we are dealing with. Obviously there can’t be any meaningful changes until we can identify what parts of the app are well built and which are not. When assessing a new codebase I like to think in terms of, what I feel, are the five pillars of any mobile or front-end project: User Interfaces, Navigation, State Management, Networking and Peripheral Management. Through this framework, I can get a feel for the app’s architecture and overall code health. There were the results of our diagnosis:</p><h4><strong>User Interface Development</strong><em> ✅</em></h4><p>In our case this app was written in Swift so it wasn’t a legacy project or anything. When building user interfaces, the previous developers used XIB files in combination with Swift View-Controller files. This was a bit annoying because the team had mostly worked with storyboards, but it wasn’t technically wrong or anything, so we felt we could leave this as-is.</p><h4><strong>Navigation</strong><em> ❌</em></h4><p>This app had no structured form of navigation. Because we weren’t using storyboards, we had no segues. The previous developers were simply getting the UIApplication root view controller and replacing it. Code snippets like this were randomly all over the place.</p><pre>let vc = MyViewController()<br>UIApplication.shared.theKeyWindow?.rootViewController = vc</pre><p>We would need to fix navigation before making any progress.</p><h4><strong>State Management</strong><em> ❌</em></h4><p>The state management of this code base was a crude form of Model-View-Controller (MVC). Although there are structured ways to do MVC, the developers before us didn’t use it. There were view controllers of 3000+ lines that were hard to navigate through. It would be important to create shorter, more focused files before moving forward.</p><h4><strong>Networking</strong><em> ✅</em></h4><p>The networking layer was another part of this app we didn’t feel needed rework. This is because the app used GraphQL and Apollo which generates most of the queries based on the schema you provide. Even if we wanted to re-write large portions of this, we wouldn’t be able to.</p><h4><strong>Peripheral Management</strong><em> ❌</em></h4><p>The final layer we assessed was the peripheral connection layer. This app used a Bluetooth device. The previous developers only exposed Bluetooth to one part of the app. Future feature development would require Bluetooth to be exposed to the entire app, so this piece wasn’t where it needed to be.</p><p>If I was to diagram the early architecture it would probably look something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/581/1*_d92ZOJjZ47fOJyW-gqypQ.png" /></figure><p>The architecture taken at face value seems simple. But it’s the lack of focused classes and objects that was leading to overloaded view controllers that were verbose and challenging to navigate.</p><h3><strong>The Refactor Begins</strong></h3><p>We diagnosed the app with having three main problems: state management, navigation and peripheral management. After fixing some initial bugs and negotiating refactor time with the client, we were off the the races.</p><h4><strong>Choosing Model-View-View-Model (MVVM)</strong></h4><p>The first decision we made as a team was that we were going to refactor to MVVM. As you’re probably aware, VIPER is another strong candidate for state management. Problem is, we only had a month or so for this refactor and it would take too long to build out the more sophisticated VIPER. Although MVVM is not as flexible as VIPER, it&#39;s no slouch. MVVM would enable us to separate our view logic from our business and navigation logic, effectively hitting two birds with one stone.</p><h4><strong>Refactoring Navigation</strong></h4><p>Once we were set on using MVVM, the first thing we needed to do was to fix the navigation structure of the app. The app was making screen transitions like this on the old architecture:</p><pre>let vc = MyViewController(<br>  val1: 1<br>  val2: 2<br>)<br>UIApplication.shared.theKeyWindow?.rootViewController = vc</pre><p>This meant that navigation logic and building view controllers were taking place in the host View Controller. Without a clear separation of concerns between navigation and the View Controllers, it would be impossible to make any progress on View Models.</p><p>We chose to use the <a href="https://www.hackingwithswift.com/articles/71/how-to-use-the-coordinator-pattern-in-ios-apps">coordinator pattern of navigation</a> which allowed us to keep our navigation functionality in one place. For those who have never used the coordinator pattern before, it’s basically a way of managing access to navigation functions on a global UINavigationController. We paired this with an extension to the UINavigationController that allowed us to simplify navigation primitives such as pushing, popping, and presenting modals. At this point we could set up navigation using a pattern like the following:</p><pre>func goToNewScreen(param1: AnyParam) {<br>  let sampleVM = SampleViewModel(<br>    param1: param1,<br>    networking: self.networkingLayer,<br>    user: self.userModel<br>  )<br>  let sampleCV = SampleViewController(viewModel: sampleVM)<br>  self.push(sampleVC)<br>}</pre><p>Then in the View Controller:</p><pre>class MyViewController {<br>  ...<br>  func transition() {<br>    self.coordinator.goToNewScreen(<br>      param1: sampleParam<br>    )<br>  }<br>}</pre><p>At this point two of our problems were solved.</p><ol><li>We no longer had our business logic entangled with our view logic like what you see in the MVC pattern.</li><li>We were able to remove navigation logic from view controllers. If I were to make a diagram at this point it would look like this:</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/858/1*gioBWagOB7_C4sNhCl2sfQ.png" /></figure><p>There is definitely a lot more going on in this diagram, however, the app had a much better separation of concerns at this point. The Navigation Coordinator handled navigation, View Models handled business logic, View Controllers handled View Logic and the networking layer handled networking.</p><h4><strong>Peripheral Management</strong></h4><p>The final part of this project that needed rework is the peripheral layer. It was a Bluetooth object that was available in only one part of the app. To fix this, we started by transforming it into a singleton. This wasn’t enough though, we still needed to be able to access the delegate methods of Bluetooth from different screens. To do this, we created a superclass for all View Controllers that required Bluetooth connectivity. Extending this class would allow all core controllers to have access to Bluetooth without having to rewrite the protocol methods in all delegates over and over again.</p><h3><strong>Final Thoughts</strong></h3><p>In the end, the app architecture ended up looking like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/822/1*Jp0sEk39g3_hbKnbdBDbJQ.png" /></figure><p>As you can see there are a lot more layers to this app than we started out with. This ends up being a strength because every part of our codebase has a defined purpose. This makes the system not only easier to extend, but a lot easier to explain to stakeholders in plain English when the need arises.</p><p>Thanks for giving this a read! This refactor was actually quite fun and really allowed us to flex our OOP muscles. Hopefully hearing our story will empower you to make some of these decisions in your next major refactor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/259/0*z8yPwvmb2V4ROPnm.png" /></figure><p>Daniel is an Agile Software Developer specializing in Flutter and React-Native. As much as he likes cross platform, he is passionate about all types of mobile development including native iOS and Android and is always looking to advance his skill in the mobile development world.</p><p><a href="http://www.tribalscale.com/"><em>TribalScale</em></a><em> is a global innovation firm that helps enterprises adapt and thrive in the digital era. We transform teams and processes, build best-in-class digital products, and create disruptive startups. Learn more about us on our </em><a href="http://www.tribalscale.com/"><em>website</em></a><em>. Connect with us on </em><a href="http://twitter.com/tribalscale"><em>Twitter</em></a><em>, </em><a href="https://www.linkedin.com/company/tribalscale"><em>LinkedIn</em></a><em> &amp; </em><a href="http://facebook.com/tribalscale"><em>Facebook</em></a><em>!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d81a23f6a22c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/tribalscale/transforming-a-messy-swift-codebase-to-mvvm-a-case-study-d81a23f6a22c">Transforming a Messy Swift Codebase to MVVM — A Case Study</a> was originally published in <a href="https://medium.com/tribalscale">TribalScale</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building a YouTube Component Using the React-Native WebView]]></title>
            <link>https://medium.com/better-programming/building-a-youtube-component-using-the-react-native-webview-808fc4e2d49b?source=rss-d3e2a73e2cbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/808fc4e2d49b</guid>
            <category><![CDATA[youtube]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <dc:creator><![CDATA[Daniel Friyia]]></dc:creator>
            <pubDate>Mon, 14 Mar 2022 14:47:05 GMT</pubDate>
            <atom:updated>2022-03-14T14:47:05.111Z</atom:updated>
            <content:encoded><![CDATA[<h4>Add YouTube Player functionality to your React-Native App</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QIYj7bq2W4dW7xbo-L5Log.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@vmxhu?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Szabo Viktor</a> on <a href="https://unsplash.com/s/photos/youtube?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Recently, I was working on an app that required access to YouTube videos. To my surprise, there wasn’t much in the way of good libraries on NPM. After taking a deep dive on YouTube and React-Native development, I realized that YouTube wants you to just use their embed.</p><p>This posed an interesting problem.</p><p>If we were working in browser-based JavaScript, it would be trivial to just copy and paste the JS from the YouTube documentation. When working on mobile though, we don’t have the same luxury. Luckily, the WebView in React-Native provides a robust API that allows us to communicate between mobile and the WebView’s browser.</p><p>In this blog, I’ll be explaining how we can take advantage of that API to create a YouTube component we can control from React-Native. As always, if you get stuck at any point, check out the complete project repo <a href="https://github.com/friyiajr/iFrameSample">here</a>.</p><h3>What Are We Building?</h3><p>Today, we’ll be building this simple app that plays videos through the YouTube embed. You’ll learn how to display videos as well as how to communicate between the WebView’s JavaScript and React-Native.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*eGG2QMZ-9_Zs92MpZqemtQ.gif" /><figcaption>Our App Running on iOS</figcaption></figure><h3>Getting Started</h3><p>The first thing you’ll want to do is generate an empty TypeScript project using this command:</p><pre>npx react-native init YoutubePlayer --template react-native-template-typescript</pre><p>After generating the project, run the following command to install the react-native-webview:</p><pre>npm i react-native-webview</pre><p>Finish up by installing the new Cocoapods in your project.</p><pre>cd ios &amp;&amp; npx pod install</pre><h3>Writing the Markup</h3><p>When using a complex web component like the YouTube player, we can’t just pop in a URL and watch the WebView work. In order to support such a feature-rich component, we need to use the <a href="https://developers.google.com/youtube/iframe_api_reference">YouTube embed</a>.</p><p>I recommend starting by creating a file called iFrame.tsx under your src directory. After creating this file, we can start by making a function called buildIFrame. This function will build the embed part of our HTML code.</p><p>Start by adding a player div that we can use as a target for the embed.</p><pre>const buildIFrame = (videoId: string) =&gt; `<br>  &lt;div id=&quot;player&quot;&gt;&lt;/div&gt;</pre><p>Next, we’ll want to build the script that makes the YouTube player appear. We start by loading the iFrame player code asynchronously.</p><pre>...<br>var tag = document.createElement(&#39;script&#39;);<br>tag.src = &quot;https://www.youtube.com/iframe_api&quot;;<br>var firstScriptTag = document.getElementsByTagName(&#39;script&#39;)[0];<br>firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);<br>...</pre><p>At this point, we need to create the YouTube player and target the player div we created. We do this as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/89f96d1ca4d768b4e62c64884b4c266a/href">https://medium.com/media/89f96d1ca4d768b4e62c64884b4c266a/href</a></iframe><p>The videoId will be passed in a bit later, but for now, you can get the screen width from the React Native dimensions like this.</p><pre>import {Dimensions} from &#39;react-native&#39;;<br>const {width} = Dimensions.get(&#39;window&#39;);</pre><p>Your buildIFrame function so far should be as follows.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e2b043e48afb2f12c0ef77ad4ef23ea6/href">https://medium.com/media/e2b043e48afb2f12c0ef77ad4ef23ea6/href</a></iframe><p>The next step is to style our iFrame. Keep in mind the styles for this are pretty specific. This is because we want the iFrame to fill its parent view.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/031e568af8a349008588f0b29ca9817f/href">https://medium.com/media/031e568af8a349008588f0b29ca9817f/href</a></iframe><p>Finally, let&#39;s create a method that takes in a videoId from YouTube and uses it to build the entire iFrame HTML page.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ae582f231e5f10070999181595931328/href">https://medium.com/media/ae582f231e5f10070999181595931328/href</a></iframe><h3>Creating the Component</h3><p>Now that we have the markup we need, let&#39;s create the WebView Component. Navigate back to your App.tsx file. At this point, you want to import the WebView component and use it along with the buildHTML function we just finished creating. Altogether, the file should look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e42d83fbbb86c2fb0507364e3a125f5e/href">https://medium.com/media/e42d83fbbb86c2fb0507364e3a125f5e/href</a></iframe><p>At this point, you should be able to watch the video if you tap on it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*WtESj9gOVPaO--y-SA_IVw.gif" /><figcaption>Video Should be Working</figcaption></figure><h3>Building the Controls</h3><p>To create the controls we are going to add more code to the buildIFrame function from earlier. On the web, the YouTube player gives you access to several functionalities. The ones we use in this project are playing and pausing the video, seeking to a time, and getting the current time in the video.</p><p>We wrap these functionalities in JavaScript browser functions so we can call them from React-Native later on. After doing this, your buildIFrame will take this form.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/49ebe7e07a0ceaea42f45a1635103350/href">https://medium.com/media/49ebe7e07a0ceaea42f45a1635103350/href</a></iframe><p>Back in the App.tsx file, we have the trivial task of wrapping these functions in React-Native functions so that we can call them in the browser. Start by grabbing a ref to the WebView.</p><pre>const webRef = useRef&lt;WebView&gt;(null);<br>...<br>&lt;WebView<br>  ref={webRef}</pre><p>After that, you can call whatever JavaScript functions you want on the WebView. Here are the ones we’ll use for this project:</p><pre>const playVideo = () =&gt; {<br>    webRef.current?.injectJavaScript(&#39;play()&#39;);<br>};</pre><pre>const pauseVideo = () =&gt; {<br>    webRef.current?.injectJavaScript(&#39;pause()&#39;);<br>};</pre><pre>const restartVideo = () =&gt; {<br>    webRef.current?.injectJavaScript(&#39;seekTo(0)&#39;);<br>};</pre><p>If we throw in a few buttons and some light styling, our component ends up in its penultimate form.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/64a745fb3e7a15651c98aa18bcf65cf2/href">https://medium.com/media/64a745fb3e7a15651c98aa18bcf65cf2/href</a></iframe><p>We’re almost there! At this point, you should be able to play the video with the controls.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/366/1*83rsQMWXASj-5WIORP_cXQ.gif" /><figcaption>Controls should now work</figcaption></figure><h3>Displaying the Timer</h3><p>The last thing we’ll want to do is display the timer. To do this, we’ll have to post messages from the WebView and send them to React-Native every second or so.</p><p>We can add this functionality to our WebView using the postMessage function. You can add this snippet to your iFrame.ts.</p><pre>setInterval(() =&gt; {<br>  const data = {<br>    currentDuration: getCurrentTime()<br>  }<br>  window.ReactNativeWebView.postMessage(JSON.stringify(data));<br>}, 1000)</pre><p>The function should now contain the set interval, shown below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a75ebee34cd9d6ce41427d7b74ef492f/href">https://medium.com/media/a75ebee34cd9d6ce41427d7b74ef492f/href</a></iframe><p>We can finish up by grabbing these events from the WebView and displaying them using a state. Your final App.tsx will look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8a578e0d28911d1636cf8b3b1f32be0d/href">https://medium.com/media/8a578e0d28911d1636cf8b3b1f32be0d/href</a></iframe><p>Your final result should be this:</p><figure><img alt="Video playing with a play, pause, restart, and timer under it." src="https://cdn-images-1.medium.com/max/327/1*7sYGulZqFlyCwgytnPWZWA.gif" /><figcaption>Final Result Running on Android</figcaption></figure><h3>Final Thoughts</h3><p>With YouTube being the primary hosting service on the internet, it’s really important to be able to use it in our apps. Above, I gave you the basics for how to add it to your app.</p><p>Feel free to style the controls as you see fit in order to suit your user experience!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=808fc4e2d49b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/better-programming/building-a-youtube-component-using-the-react-native-webview-808fc4e2d49b">Building a YouTube Component Using the React-Native WebView</a> was originally published in <a href="https://betterprogramming.pub">Better Programming</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why 2022 Will Be a Huge Year for React-Native]]></title>
            <link>https://medium.com/tribalscale/why-2022-will-be-a-huge-year-for-react-native-f61b6d6b30b8?source=rss-d3e2a73e2cbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/f61b6d6b30b8</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[react-native-development]]></category>
            <dc:creator><![CDATA[Daniel Friyia]]></dc:creator>
            <pubDate>Thu, 03 Mar 2022 18:18:47 GMT</pubDate>
            <atom:updated>2023-04-24T20:30:11.632Z</atom:updated>
            <content:encoded><![CDATA[<p><em>Written by: Daniel Friyia, Agile Software Engineer, TribalScale</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*3rk2kQNI7dihnd8z.png" /></figure><h4>📫 <a href="https://www.tribalscale.com/weekly-digest-subscription">Subscribe to receive our content here.</a></h4><h4>💬 Have any questions about React-Native? <a href="https://www.tribalscale.com/schedule-a-chat">Click here to chat with one of our experts!</a></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*mOqKP_rsAFEwSXL0.png" /></figure><figure><img alt="Smartphone on a table next to a computer keyboard" src="https://cdn-images-1.medium.com/max/1024/1*axiDeO1kF1bGMuRbV1Asmg.jpeg" /><figcaption>Courtesy of <a href="https://unsplash.com/@casparrubin">Caspar Camille Rubin</a> from <a href="https://unsplash.com">Unsplash</a></figcaption></figure><p>The React-Native (RN) community can seem quiet at times. This is especially true if you are new to the ecosystem and don’t know who the key influencers in the community are. Unlike iOS or Android, big developments to React-Native are not met with large conference announcements and fanfare. Instead, they are reliant on social media and developers making recommendations to one another. I sorely wish our community was better at PR when major developments take place, but unfortunately that’s not the case. Knowing this, I thought I would take a break from my usual tutorials and do my civic duty as a member of the React-Native community to promote changes to the ecosystem I think will make a huge difference in 2022.</p><h3><strong>More progress on the new architecture</strong></h3><p>The first big development we will see in 2022 is the new React-Native architecture becoming increasingly more mature. I know not everyone is up to speed on what the components of the RN architecture are, so let me explain. The RN refactor has three parts: Turbo Modules, Fabric and Codegen. Turbo Modules allow JavaScript to hold a reference to C++ host objects and manipulate them. Fabric is the new renderer for RN that is meant to increase rendering performance and make Android and iOS UI behaviours more consistent with one another. Finally, Codegen is used to generate native code at build time. A great explanation of this can be found in the <a href="https://twitter.com/ReactNativeRdio/status/1471919123546324994?s=20&amp;t=Tjmc3mcJO12evCxhGyZL6Q">React-Native Radio (RNR) Podcast 222 </a>with React-Native’s Engineering Manager <a href="https://twitter.com/fkgozali">Kevin Gozali</a>.</p><h3>React Native Radio on Twitter: &quot;❤️🖤RNR 222 is out❤️🖤We interview Meta engineer @fkgozali to discuss the React Native new architecture - TurboModules, Fabric, codegen, and whether React Native developers need to go learn C++!@jamonholmgren @jonmajorc @mazenchami #ReactNative https://t.co/EueMCk1mfH / Twitter&quot;</h3><p>❤️🖤RNR 222 is out❤️🖤We interview Meta engineer @fkgozali to discuss the React Native new architecture - TurboModules, Fabric, codegen, and whether React Native developers need to go learn C++!@jamonholmgren @jonmajorc @mazenchami #ReactNative https://t.co/EueMCk1mfH</p><p>In the RNR Podcast, Kevin let us know that up to this point TurboModules and Fabric have been mostly completed. In accordance with his statement, Meta’s React-Native blog just announced that the architecture will be <a href="https://reactnative.dev/blog/2022/01/21/react-native-h2-2021-recap#the-new-architecture-rollout-and-releases">open-sourced this year</a> so that everyone has a chance to try it out. It will be exciting to see all the new libraries and app optimizations that come out of the release!</p><h3><strong>Moving towards Hermes as default across all React-Native platforms</strong></h3><p>This next point builds on the last related to the RN re-architecture. Late last year, Meta announced they are working towards making Hermes the <a href="https://reactnative.dev/blog/2021/10/26/toward-hermes-being-the-default">default JavaScript Engine on all platforms</a>.</p><h3>React Native on Twitter: &quot;With community adoption and feedback, @HermesEngine has flourished.Today, we&#39;d like to share all the progress we&#39;ve made and the case for making Hermes the default engine for React Native.https://t.co/P9mIe8f6KH / Twitter&quot;</h3><p>With community adoption and feedback, @HermesEngine has flourished.Today, we&#39;d like to share all the progress we&#39;ve made and the case for making Hermes the default engine for React Native.https://t.co/P9mIe8f6KH</p><p>Although Hermes has been available for a while, especially on mobile, it’s great to see it will be a core part of the RN ecosystem moving forward. Hermes is a Meta’s JS engine tailored specifically for running with RN, as opposed to engines like V8 that are optimized for Google Chrome. <a href="https://reactnative.dev/docs/hermes">Using Hermes results in faster app start-up times, less memory usage and smaller apps</a>. Basically, it’s a much welcomed overall buff for the RN ecosystem 😅. I’ve been enabling it on all the demo projects I write for Medium and will be enabling it on all future projects even before it becomes default.</p><h3><strong>Major improvements to animations</strong></h3><p>Another big development in the RN community this year is going to be animations. Mid last year we saw the release of <a href="https://blog.swmansion.com/reanimated-2-0-stable-release-is-out-564c9c910891">React-Native ReAnimated 2</a> which allowed us to have access to the native UI thread. As the library continues to gain popularity this year, we will see the performance of animations improve by leaps and bounds on lower performance devices where, in the past, RN animations would struggle because of the old bridging architecture.</p><p>As if ReAnimated 2 wasn’t enough of a leap forward, a few months ago, development on a new, equally powerful, animations project was announced. Twitter followers of <a href="https://twitter.com/wcandillon/status/1479795666700357635?s=20&amp;t=EBUlpkxw4dU1NfLh0tBVZg">William Candillon</a> and Shopify Engineering will be aware that a new project called <a href="https://shopify.github.io/react-native-skia/]">React-Native-Skia</a> is being worked on.</p><h3>Shopify Engineering on Twitter: &quot;A lot of great work happening on #ReactNativeSkia! https://t.co/mg3SY9TBqP / Twitter&quot;</h3><p>A lot of great work happening on #ReactNativeSkia! https://t.co/mg3SY9TBqP</p><p>This library brings Skia functionality to RN. For those who don’t know, <a href="https://skia.org/">Skia</a> is the rendering engine used by Google Chrome, Android and Flutter that gives the user control over every Pixel on the screen. It is especially popular for its two dimensional drawing optimizations. It will be interesting to follow this library’s journey to production readiness this year. I know I’ll be following this work on William Candillon’s <a href="https://www.youtube.com/channel/UC806fwFWpiLQV5y-qifzHnA">YouTube channel</a>.</p><h3>William Candillon on Twitter: &quot;Is that how they do the mirror dimension in doctor strange? pic.twitter.com/xxkdcsLlyP / Twitter&quot;</h3><p>Is that how they do the mirror dimension in doctor strange? pic.twitter.com/xxkdcsLlyP</p><h3><strong>Final thoughts</strong></h3><p>Thanks for giving this a read! I hope you’ll find this article useful coming into 2022. If there are any parts of the React-Native ecosystem you think will be significant in the coming year feel free to share them in the comments. It would be great to share the cool emerging libraries and technologies everyone is working with.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/259/0*T-Sd6T74Yp_z3le5.png" /></figure><p>Daniel is an Agile Software Developer specializing in Flutter and React-Native. As much as he likes cross platform he is passionate about all types of mobile development including native iOS and Android and is always looking to advance his skill in the mobile development world.</p><p><a href="http://www.tribalscale.com/"><em>TribalScale</em></a><em> is a global innovation firm that helps enterprises adapt and thrive in the digital era. We transform teams and processes, build best-in-class digital products, and create disruptive startups. Learn more about us on our </em><a href="http://www.tribalscale.com/"><em>website</em></a><em>. Connect with us on </em><a href="http://twitter.com/tribalscale"><em>Twitter</em></a><em>, </em><a href="https://www.linkedin.com/company/tribalscale"><em>LinkedIn</em></a><em> &amp; </em><a href="http://facebook.com/tribalscale"><em>Facebook</em></a><em>!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f61b6d6b30b8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/tribalscale/why-2022-will-be-a-huge-year-for-react-native-f61b6d6b30b8">Why 2022 Will Be a Huge Year for React-Native</a> was originally published in <a href="https://medium.com/tribalscale">TribalScale</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[D3 and React-Native — An Essential Guide to Line Graphs]]></title>
            <link>https://medium.com/better-programming/d3-and-react-native-an-essential-guide-to-line-graphs-dc1ce392b440?source=rss-d3e2a73e2cbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/dc1ce392b440</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[react-native]]></category>
            <dc:creator><![CDATA[Daniel Friyia]]></dc:creator>
            <pubDate>Tue, 01 Mar 2022 17:02:42 GMT</pubDate>
            <atom:updated>2022-03-01T17:02:42.130Z</atom:updated>
            <content:encoded><![CDATA[<h4>Your guide to making beautiful, animated, line graphs in React Native</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*etw5z11s3mQYd5Bd8Coj7g.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@isaacmsmith?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Isaac Smith</a> on <a href="https://unsplash.com/s/photos/graph?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>D3.js is the best, most powerful tool we have in React-Native (and maybe even all mobile development) for creating charts and data visualizations 📈. If there is any doubt in your mind I recommend checking out the <a href="https://www.d3-graph-gallery.com"><strong>D3 gallery</strong></a><strong>.</strong></p><p>The amazing amount of variety in the gallery demonstrates the versatility of D3 when it comes to visualizing data. D3 is the way to go if you want full freedom over what your data visualizations look like.</p><p>I was inspired to write this article because there aren’t many resources that exist on D3 line charts let alone D3 and React-Native. I assume that readers of this post are already familiar with SVG Animations in React-Native.</p><p>If not, you can <a href="https://medium.com/tribalscale/intro-to-svg-animations-with-react-native-reanimated-2-78bd87438129">learn about them from my last post here</a>. I want this article to serve as a guide for React-Native developers looking to get into D3 for themselves and start crafting beautiful charts.</p><h4><strong>What are we Building?</strong></h4><p>As always with my how-to guides, I like to start by showing what we are building. We will be creating the line chart you see in the GIF below complete with the animation between line graphs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*-cKL6jc53A9ftlWy5E1YAA.gif" /><figcaption>Our final result running on iOS</figcaption></figure><h4><strong>Getting Started</strong></h4><p>Unlike my other tutorials, I am going to start this one from a boilerplate. If you want to follow along, you can clone the <a href="https://github.com/friyiajr/D3LineChartSample">starter project here</a>. You should be in the main branch at this point.</p><p>There won’t be anything to set up since I’ve already installed the ReAnimated and SVG libraries for you. All you need to do is run yarn install and then cd ios &amp;&amp; pod install in your terminal from the root of the project. If you get stuck and want to view the solution, check out the solution branch.</p><p>Note that the boilerplate does not include all imports. You’ll need to import library values as you go with cmd + . in your VSCode editor. Your project so far should be an empty card with some buttons that looks like this.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/471/1*uyFm_sO2cLIQfz1E02_Pag.png" /><figcaption>Starting Canvas Running on iOS</figcaption></figure><h4><strong>Familiarizing Ourselves with the Data</strong></h4><p>Let’s start by familiarizing ourselves with the structure of our data. Each point has these values:</p><pre>export type DataPoint = {<br>  date: string;<br>  value: number;<br>};</pre><pre>export const originalData: DataPoint[] = [<br>  {date: &#39;2000-02-01T05:00:00.000Z&#39;, value: 250},<br>  {date: &#39;2000-02-02T05:00:00.000Z&#39;, value: 300.35},<br>  {date: &#39;2000-02-03T05:00:00.000Z&#39;, value: 150.84},<br>  ...</pre><p>All the data for this app can be found in the Data.ts file under the src directory. Notice the dates are saved in ISO-8601 string format. This is because ReAnimated for Android isn’t able to handle JavaScript date objects well. The only way to pass our dates to ReAnimated later on will be in the form of ISO date strings. Our values are numbers representing real-life dollar amounts.</p><h4>Organizing our Data</h4><p>To build a chart, we need to organize our data so it can be handled by D3. The best way to start things off is to create a method that returns an object with our processed chart data in the App.tsx file.</p><pre>const makeGraph = (data: DataPoint[]) =&gt; {};</pre><p>The next step we’ll take is calculating the max and min values in our dataset. These values are used to form the y domain of our chart. This is pretty simple to do, we can just feed the values of our data into the Math.max and Math.min methods.</p><pre>const max = Math.max(...data.map(val =&gt; val.value));<br>const min = Math.min(...data.map(val =&gt; val.value));</pre><p>After that, creating the y axis is as easy as calling scaleLinear in the D3 library. Note the use of GRAPH_HEIGHT in the range. This will ensure all our data points are mapped to y coordinates on the screen that is no greater then the graph’s height.</p><pre>const y = scaleLinear().domain([0, max]).range([GRAPH_HEIGHT, 35]);</pre><p>For the x-axis, we know our data is always going to be fifteen days so we’ll set the starting point and ending points at the first and fifteenth of the month respectively. Note the use of GRAPH_WIDTH in the range. Like the y axis, it maps our values to x coordinates on the screen and makes sure they are no greater than the graph’s width.</p><pre>const x = scaleTime()<br>    .domain([new Date(2000, 1, 1), new Date(2000, 1, 15)])<br>    .range([10, GRAPH_WIDTH - 10]);</pre><p>We then finish off by creating the line chart using the line function from D3.</p><pre>const curvedLine = line&lt;DataPoint&gt;()<br>    .x(d =&gt; x(new Date(d.date)))<br>    .y(d =&gt; y(d.value))<br>    .curve(curveBasis)(data);</pre><p>We return the max, min and curvedLine values from our function. They will be needed soon to draw our chart.</p><pre>return {<br>    max,<br>    min,<br>    curve: curvedLine!,<br> };</pre><p>Altogether, our makeGraph function should look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a1a2190b1f2d621d26052553e776bd96/href">https://medium.com/media/a1a2190b1f2d621d26052553e776bd96/href</a></iframe><h4><strong>Drawing the Graph</strong></h4><p>The next thing we’ll do is draw our graph. Let&#39;s start by adding our first data set to the array of graph data sets in App.tsx.</p><pre>const graphData: GraphData[] = [makeGraph(originalData)];</pre><p>Since graphData is already passed into the LineChart component, lets jump back over into the LineChart.tsx file. Start by de-structuring all component values in the method header.</p><pre>const LineChart: FC&lt;LineChartProps&gt; = ({<br>  height,<br>  width,<br>  data,<br>  bottomPadding,<br>  leftPadding,<br>}) =&gt; {</pre><p>When we called the line method earlier, D3 took in a set of domain and range values and used them to construct an SVG path. Our chart then is really just an SVG we display on the screen. To host our line graph, we add the SVG canvas to our LineChart component.</p><pre>&lt;Animated.View style={styles.chartContainer}&gt;<br>  &lt;Svg width={width} height={height} stroke=&quot;#6231ff&quot;&gt;&lt;/Svg&gt;<br>&lt;/Animated.View&gt;</pre><p>At this point, we’ll see our graph snap into its proper height.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/329/1*5lrj-qC1cutF-exPc7sKqQ.png" /><figcaption>Resized Canvas Running on iOS</figcaption></figure><p>Now we’ll add some gridlines to make the graph stand out a more. We can do this by drawing a few SVG lines.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a9d94f13e218eba0d909a5ca38b24881/href">https://medium.com/media/a9d94f13e218eba0d909a5ca38b24881/href</a></iframe><p>Note the use of x1, x2, y1, andy2 values here. The first value of x or y is the coordinates of where you want the line to start. The second value for the coordinates is where you want the line to end. Our result will be this empty chart:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/328/1*nl8bFCBAqDE8QmpeIejs_Q.png" /><figcaption>Canvas with Graph Lines on iOS</figcaption></figure><p>Finally, the moment has come, let&#39;s place our graph on the canvas. Add the following code to the file under the lines we drew earlier.</p><pre>&lt;Path d={data[0].curve} strokeWidth=&quot;2&quot; /&gt;</pre><p>The result will be a graph that looks as follows.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/328/1*FcbXZIyiV-iukeEIokpgPg.png" /><figcaption>A Simple Graph Running on iOS</figcaption></figure><p>Your code for the LineChart component so far should look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c48671982b593db46ba2e8a00553e2ee/href">https://medium.com/media/c48671982b593db46ba2e8a00553e2ee/href</a></iframe><h4>Animating Multiple Graphs</h4><p>That was exciting! Not only did we draw our graph to the screen, but we were also able to add guidelines for good measure.</p><p>The next phase of this article will focus on switching between multiple line charts and animating those transitions. This section is only possible because of the <a href="https://github.com/wcandillon/react-native-redash">react-native-redash</a> TypeScript library authored by the Godfather of React Native animations <a href="https://medium.com/u/4bdbd6b3a30a">William Candillon</a>.</p><p>To start the process of animating our graph, start back in the App.tsx by adding the other datasets to our array of graphs:</p><pre>const graphData: GraphData[] = [<br>  makeGraph(originalData),<br>  makeGraph(animatedData),<br>  makeGraph(animatedData2),<br>  makeGraph(animatedData3),<br>];</pre><p>You will also need to run redash parse on the curve attribute of makeGraph and adjust your types accordingly.</p><pre>import {parse, Path as RePath} from &#39;react-native-redash&#39;;<br>...<br>export type GraphData = {<br>  ...<br>  curve: RePath;<br>};</pre><pre>const makeGraph = (data: DataPoint[]) =&gt; {<br>  ...<br>  return {<br>    max,<br>    min,<br>    curve: parse(curvedLine!),<br>  };<br>};</pre><p>Navigate back to your LineChart.tsx file and create a sharedValue for the graph you’ve currently selected. This is also a good time to make a function that can transition between graphs (without animating). Altogether the code should look like this:</p><pre>const selectedGraph = useSharedValue(data[0]);<br>const onQuarterTapped = (quarter: number) =&gt; {<br>  selectedGraph.value = data[quarter - 1];<br>};<br>const animatedProps = useAnimatedProps(() =&gt; {<br>  return {<br>    d: selectedGraph.value.curve,<br>  };<br>});<br>const q1Tapped = () =&gt; onQuarterTapped(1);<br>const q2Tapped = () =&gt; onQuarterTapped(2);<br>const q3Tapped = () =&gt; onQuarterTapped(3);<br>const q4Tapped = () =&gt; onQuarterTapped(4);</pre><p>You can also add these functions to the button section at the bottom of the file:</p><pre>&lt;ButtonSection<br>  q1Tapped={q1Tapped}<br>  q2Tapped={q2Tapped}<br>  q3Tapped={q3Tapped}<br>  q4Tapped={q4Tapped}<br>/&gt;</pre><p>Your code will appear like this so far.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c9b41f49c4ff8b6667559c8b51210c55/href">https://medium.com/media/c9b41f49c4ff8b6667559c8b51210c55/href</a></iframe><p>At this point, you’ll have a chart that can jump between graphs like in the GIF below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/1*HT5e7JGB6-sq0zdYE82QLQ.gif" /><figcaption>Pre-Animated Chart running on Android</figcaption></figure><p>Obviously, this looks a little weird, so let&#39;s add in the animation now. Back in LineChart.tsx we add a state for our current graph, the graph we are transitioning from, and the status of our transition.</p><pre>const selectedGraph = useSharedValue(data[0]);<br>const previousGraph = useSharedValue({...data[0]});<br>const isAnimationComplete = useSharedValue(true);<br>const transition = useSharedValue(1);</pre><p>We will need to update the animatedProps to reflect the transition between these graphs. The new code will be as follows:</p><pre>const animatedProps = useAnimatedProps(() =&gt; {<br>  return {<br>    d: mixPath(<br>      transition.value,<br>      previousGraph.value.curve,<br>      selectedGraph.value.curve,<br>    ),<br>  };<br>});</pre><p>Note the use of the function mixPath. This redash function interpolates two paths with an animation value that goes from 0 to 1. Let’s finish by updating our onQuarterTapped function to animate from one state to the next.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/18c809cbdfe4c99e5c3307379ce6a7bb/href">https://medium.com/media/18c809cbdfe4c99e5c3307379ce6a7bb/href</a></iframe><p>The above code does a number of things, so I’ll break it down here. First, we have an if statement that blocks new animations from happening if there is already an animation in progress.</p><p>If there are no active animations, we set the selected graph as the graph we tapped on.</p><p>At this point we use the withTiming to slowly increase the transition value to 1 which allows mixPath to animate the chart. Finally, when the animation is complete, we set isAnimationComplete to true so that the user is free to tap the buttons again and transition to another chart.</p><h4>Bonus: Animating Text</h4><p>Let’s finish up by animating the text at the top of the screen where we see the dollar amount. Start by adding a mostRecent property to the makeGraph function. You can do it like this:</p><pre>const makeGraph = (data: DataPoint[]) =&gt; {<br>  ...<br>  return {<br>    max,<br>    min,<br>    curve: parse(curvedLine!),<br>    mostRecent: data[data.length - 1].value,<br>  };<br>};</pre><p>We can then create a derived value in LineChart.tsx so that this string is visible to the UI Thread.</p><pre>const mostRecent = useDerivedValue(() =&gt; {<br>  return `$${selectedGraph.value.mostRecent}`;<br>});</pre><p>Finally we can use ReText from react-native-redash to show the value on the UI:</p><pre>&lt;View style={styles.titleContainer}&gt;<br>  &lt;Text style={styles.titleText}&gt;FACEBOOK&lt;/Text&gt;<br>  &lt;ReText style={styles.priceText} text={mostRecent} /&gt;<br>&lt;/View&gt;</pre><p>Our completed code is as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/478008797e0459285c1477457ff4e9ab/href">https://medium.com/media/478008797e0459285c1477457ff4e9ab/href</a></iframe><p>Our final result is the graph in this GIF</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/1*oFVLYyNQlW1RrPsHXyqwNQ.gif" /><figcaption>Our final result running on Android</figcaption></figure><h3>Final Thoughts</h3><p>Wow that was a tough one! D3 definitely has a steep learning curve and can be a bit tricky at times. I hope by using this article you were able to get through this exercise and learn more about how to use it.</p><p>I’d love to see the React-Native community rally around this technology and cast more light on fun and interesting charts we can add to our apps. Until next time, happy coding.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dc1ce392b440" width="1" height="1" alt=""><hr><p><a href="https://medium.com/better-programming/d3-and-react-native-an-essential-guide-to-line-graphs-dc1ce392b440">D3 and React-Native — An Essential Guide to Line Graphs</a> was originally published in <a href="https://betterprogramming.pub">Better Programming</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Modern Test-Driven Development with TypeScript and Redux Slices]]></title>
            <link>https://javascript.plainenglish.io/modern-test-driven-development-with-typescript-and-redux-slices-32c249fdc8fe?source=rss-d3e2a73e2cbc------2</link>
            <guid isPermaLink="false">https://medium.com/p/32c249fdc8fe</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Daniel Friyia]]></dc:creator>
            <pubDate>Mon, 21 Feb 2022 09:18:12 GMT</pubDate>
            <atom:updated>2022-02-21T09:18:12.905Z</atom:updated>
            <content:encoded><![CDATA[<h4>Test your React app and make it bulletproof.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ejy_WacOj2q7X10ltf_ThA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@clark_fransa?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Arnold Francisca</a> on <a href="https://unsplash.com/s/photos/code?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>One of the most important but most neglected practises in Agile Software Development is unit testing. I’ve worked with a lot of tools and languages in my career, but haven’t found any that makes it as easy to test your code as it is in TypeScript/JavaScript. As front-end engineers, it’s our responsibility to make sure as much code as possible is covered by some kind of unit test. Beyond the obvious benefit of checking for errors, unit testing can serve as a form of documentation and an exercise in making our functions and components smaller and more reusable.</p><p>In the last few years, we’ve been blessed in the React world by having the ability to work with TypeScript and Redux Slices. TypeScript gives us types (obviously 🙂) while Redux slices make our state management code less verbose than traditional Redux. Together they serve as powerful tooling for your React app. This article will use a todo list example to show users of these tools how to unit test their code effectively and build bulletproof apps.</p><h4><strong>Getting Started</strong></h4><p>To build our todo list, we are going to use the red/green refactor model of unit testing. This means for every function we will go through the following steps:</p><ol><li>Write a function with just enough code to compile (no logic yet 🙅)</li><li>Write a unit test containing the desired outcome for that function</li><li>Run the test and watch it fail</li><li>Write a function that we think will pass the unit test</li><li>Run the function and watch the test pass</li></ol><p>To get started, we’ll create a boilerplate reducer and unit test to make sure things are working. We aren’t writing any logic, just enough code to compile the app. The Redux Slice should look like this:</p><pre>import { createSlice } from &quot;@reduxjs/toolkit&quot;;</pre><pre>const todoSlice = createSlice({<br>  name: &quot;todo&quot;,<br>  reducers: {}, <br>  initialState: {}, <br>});</pre><pre>export default todoSlice.reducer;</pre><p>Your unit test file should look like this:</p><pre>import todoSlice from &quot;../todo.reducer&quot;;</pre><pre>describe(&quot;Todo Slice&quot;, () =&gt; {<br>  describe(&quot;My First function&quot;, () =&gt; {<br>    it(&quot;should compile&quot;, () =&gt; {<br>      expect(1).toEqual(1);<br>    });<br>  });<br>});</pre><p>If you run yarn test at this point, the tests should compile and pass.</p><h4><strong>Adding a ToDo</strong></h4><p>The first function we’ll build in this article is one which adds a todo to our state. Because we’re using the red/green method of unit testing, we start by writing just enough code to compile, but not enough to pass our test. Once our test fails, we can work backward to create our function. Let’s start by creating a model for our todos. Our todo model will have isCompleted, text, and id properties. We can then use that model to create our initial state. It will look something like this:</p><pre>type Todo = {<br>  id: String;<br>  text: String;<br>  isCompleted: boolean;<br>};</pre><pre>export type TodoState = {<br>  todos: Todo[];<br>};</pre><pre>export const INITIAL_STATE: TodoState = {<br>  todos: [],<br>};</pre><pre>const todoSlice = createSlice({<br>  name: &quot;todo&quot;,<br>  reducers: {},<br>  initialState: INITIAL_STATE,<br>});</pre><p>We’ll also write a function with a body that does nothing and add it to the reducers:</p><pre>const todoSlice = createSlice({<br>  name: &quot;todo&quot;,<br>  reducers: {<br>    addTodo: (state, action) =&gt; {<br>      return state;<br>    },<br>  },<br>  initialState: INITIAL_STATE,<br>});</pre><pre>export const { addTodo } = todoSlice.actions;</pre><p>Finally, we can write our first failing test 😄! Our test will create a todo model, create the todo action and attempt to modify the state. We can refactor the test we had before into the following form:</p><pre>import todoSlice, {<br>  addTodo,<br>  INITIAL_STATE,<br>  Todo,<br>  TodoState,<br>} from &quot;../todo.reducer&quot;;</pre><pre>describe(&quot;Todo Slice&quot;, () =&gt; {<br>  describe(&quot;addTodo&quot;, () =&gt; {<br>    it(&quot;should add a todo to the state&quot;, () =&gt; {<br>      const todo: Todo = {<br>        id: &quot;1&quot;,<br>        isCompleted: false,<br>        text: &quot;hello world&quot;,<br>      };<br>      const action = addTodo(todo);<br>      const expectedResult: TodoState = {<br>        todos: [todo],<br>      };<br>      const actualResult = todoSlice(INITIAL_STATE, action);<br>      expect(actualResult).toEqual(expectedResult);<br>    });<br>  });<br>});</pre><p>If we run our tests at this point, we should see the iconic red test failing text.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/483/1*HPGUxyt1olZ0y8mQsOlBjg.png" /></figure><p>Cool! So now we’ve set up our todo model so we know what a model looks like, and we’ve set up the todo state so we know what that should look like. Let’s put together a function that can actually add data to the state. Change your reducer function to have the logic for adding a new todo.</p><pre>reducers: {<br>  addTodo: (<br>    state: TodoState, action: PayloadAction&lt;Todo&gt;<br>  ) =&gt; {<br>    const newTodo = action.payload;<br>    state.todos = [...state.todos, newTodo];<br>  },<br>},</pre><p>At this point, you should get a passing test! We’ve completed our first red/green refactor 🎉.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/466/1*FyZVrLLWT1Juq5rqevVoJg.png" /></figure><h4><strong>Modify a Todo</strong></h4><p>Let’s do a couple more functions so you can get a better feel for the TS/Redux Slice unit testing experience. This time we’ll address a situation where there is already data in the state by updating an existing todo to the completed state. Like last time, we add an empty stub and export it.</p><pre>updateTodo: (state, action) =&gt; {<br>  return state;<br>},</pre><pre>...</pre><pre>export const { addTodo, updateTodo } = todoSlice.actions;</pre><p>Then we write our failing test where we show what the state should look like after marking as complete.</p><pre>describe(&quot;updateTodo&quot;, () =&gt; {<br>  it(&quot;should update a todo in the state&quot;, () =&gt; {<br>    const todo: Todo = {<br>      id: &quot;1&quot;,<br>      isCompleted: false,<br>      text: &quot;hello world&quot;,<br>    };<br>    const state: TodoState = {<br>      todos: [todo],<br>    };</pre><pre>    const updatedTodo: Todo = {<br>      id: &quot;1&quot;,<br>      isCompleted: true,<br>      text: &quot;hello world&quot;,<br>    };</pre><pre>    const action = updateTodo(updatedTodo);</pre><pre>    const expectedResult: TodoState = {<br>      todos: [updatedTodo],<br>    };</pre><pre>    const actualResult = todoSlice(state, action);<br>    expect(actualResult).toEqual(expectedResult);<br>  });<br>});</pre><p>Notice how I used the todo to create a “state” to simulate the application state in the todoSlice reducer function? This way of “mocking” the state is often difficult for beginners to pick up on. I wanted to highlight it as a bit of a pro tip for beginners in this area. With this test though, we are back into the red.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/520/1*_FosVTyWUPOXH-uEPVyqbA.png" /></figure><p>Let&#39;s fix this by implementing our update function for real.</p><pre>updateTodo: (<br>  state: TodoState, action: PayloadAction&lt;Todo&gt;<br>) =&gt; {<br>  const updatedTodo = action.payload;<br>  const newTodoArray = [...state.todos];<br>  const index = newTodoArray.findIndex((todo) =&gt; {<br>    return updatedTodo.id === todo.id;<br>  });<br>  newTodoArray[index] = updatedTodo;<br>  state.todos = newTodoArray;<br>},</pre><p>With that, red/green cycle two is completed 🔥. We can now add and update todos in our application.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/484/1*Zm7-sdgn_yarSCNaDstaSg.png" /></figure><h4><strong>Delete a ToDo</strong></h4><p>Let’s finish off by implementing delete. This will be really similar to update, but I wanted to finish off with the last of the CRUD operations for the sake of completeness. Implement your deleteTodo stub and export as follows:</p><pre>deleteTodo: (state, action) =&gt; {<br>  return state<br>}<br>...<br>export const { addTodo, updateTodo, deleteTodo } = todoSlice.actions;</pre><p>Then make the deleteTodo test as follows:</p><pre>describe(&quot;deleteTodo&quot;, () =&gt; {<br>  it(&quot;should delete a todo in the state&quot;, () =&gt; {<br>    const todo: Todo = {<br>      id: &quot;1&quot;,<br>      isCompleted: false,<br>      text: &quot;hello world&quot;,<br>    };<br>    const state: TodoState = {<br>      todos: [todo],<br>    };<br>    const action = deleteTodo(&quot;1&quot;);<br>    const expectedResult: TodoState = {<br>      todos: [],<br>    };<br>    const actualResult = todoSlice(state, action);<br>    expect(actualResult).toEqual(expectedResult);<br>  });<br>});</pre><p>Let’s watch it fail</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/542/1*1DqHXUBQCFgbcADQ1W1hVA.png" /></figure><p>Then finish up by implementing the function:</p><pre>deleteTodo: (<br>  state: TodoState, action: PayloadAction&lt;string&gt;<br>) =&gt; {<br>  const id = action.payload;<br>  state.todos = [...state.todos].filter((todo) =&gt; id !== todo.id);<br>},</pre><p>With that, all tests are passing and we have a working todo reducer:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/467/1*FNKGIZ3wBbk6kymuXHD9vQ.png" /></figure><h4><strong>Final Thoughts</strong></h4><p>Thanks for checking out my article on TDD with TypeScript and Redux Slices. Because this code is so short I won’t be posting the whole thing on GitHub. If you want an example with a project that has unit testing with TS and TDD you can check out <a href="https://github.com/friyiajr/ReduxSliceCodeAlong">this repo</a> and navigate to the final-solution branch. This is a small project that fetches a Pokemon from the internet using its Pokédex number. I hope you enjoyed this article and look forward to trying out the red/green refactor technique with TS and Redux in your next project!</p><p><em>More content at </em><a href="http://plainenglish.io/"><strong><em>plainenglish.io</em></strong></a><em>. Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Get exclusive access to writing opportunities and advice in our </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>community Discord</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=32c249fdc8fe" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/modern-test-driven-development-with-typescript-and-redux-slices-32c249fdc8fe">Modern Test-Driven Development with TypeScript and Redux Slices</a> was originally published in <a href="https://javascript.plainenglish.io">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>