<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Angel Umeh</title>
    <description>The latest articles on DEV Community by Angel Umeh (@akcumeh).</description>
    <link>https://dev.to/akcumeh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F853092%2Ff7104274-75e4-484c-8d4b-96e16868303b.jpeg</url>
      <title>DEV Community: Angel Umeh</title>
      <link>https://dev.to/akcumeh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/akcumeh"/>
    <language>en</language>
    <item>
      <title>Turns Out I Never Knew What Node.js Was</title>
      <dc:creator>Angel Umeh</dc:creator>
      <pubDate>Fri, 10 Jul 2026 09:04:24 +0000</pubDate>
      <link>https://dev.to/akcumeh/my-journey-at-altschool-africa-366b</link>
      <guid>https://dev.to/akcumeh/my-journey-at-altschool-africa-366b</guid>
      <description>&lt;p&gt;I started AltSchool Africa's Backend Engineering program already knowing how to code. I had about 3 years of frontend experience (and multiple &lt;a href="https://www.hackerrank.com/certificates/1ad769922b0d" rel="noopener noreferrer"&gt;Hackerrank certificates&lt;/a&gt; to show for it), and had already held professional roles the year prior, so I'd shipped things. I assumed the program would mostly hand me new syntax to bolt onto what I already knew.&lt;/p&gt;

&lt;p&gt;That assumption didn't survive the first semester. Thirteen projects later, I don't build software the same way anymore. This is the long version of that story, mostly for myself, but also for anyone weighing whether a structured year-long program is worth it when you already have some experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  The browser was my whole world
&lt;/h2&gt;

&lt;p&gt;Before AltSchool, I built interfaces. I knew how to make things look right and behave predictably in the browser. What I didn't have was a real mental model of what was happening on the other side of the request. APIs were things I consumed, not things I designed.&lt;/p&gt;

&lt;p&gt;That changed early. Once I understood how a request actually moves through a server, gets validated, hits a database, and comes back, my frontend work started improving on its own. I started asking better questions, like why an endpoint was shaped the way it was, instead of quietly adjusting messy frontend logic around it. Frontend development became a way to visualize the systems I was learning to build, which made me sharper on the data side too. It was a side effect of finally understanding both ends of the same conversation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unlearning JavaScript
&lt;/h2&gt;

&lt;p&gt;Somewhere in the first few months, I had a moment that felt almost embarrassing given how long I'd already been writing JavaScript. I realized I had never actually understood that Node.js is just a runtime for executing JavaScript outside the browser. Not a framework or a language extension. This reorganized a lot of loose knowledge I'd been carrying around for years.&lt;/p&gt;

&lt;p&gt;The same thing happened with TypeScript. I'd always thought of it as just "harder JavaScript" because of the extra syntax, which is technically true but misses the point. Working with NestJS revealed the true power of TypeScript. It is the essential backbone of modular architecture, and its static typing catches entire categories of bugs before they ever exist. The fun part of this was making a codebase legible to whoever opens it next, including future me. I even realized some of the descriptive tooltips in a code editor come from intentional typing and scoping made possible with TypeScript, not some editor magic. I even picked up a HackerRank certification in &lt;a href="https://www.hackerrank.com/certificates/7aef5c73bbdb" rel="noopener noreferrer"&gt;Angular (Intermediate)&lt;/a&gt; even though it wasn't part of the program's stack, simply because I understood well enough to prove so under a clock, with no IDE hints and no Stack Overflow tab open.&lt;/p&gt;

&lt;p&gt;I also learned the difference between an API and a server that just supplies data. That distinction sounds small until you're the one designing the boundary between what a client should be allowed to ask for and what the server hands back regardless of the request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning to design data instead of just querying it
&lt;/h2&gt;

&lt;p&gt;A recurring lesson across almost every project: filtering and shaping data is a database concern, not an application concern. Early on it's tempting to pull everything with a broad &lt;code&gt;select('*')&lt;/code&gt; and slice it down in application code. It works, but it's also wasteful and it doesn't scale. Now, I ask of any new endpoint what the query itself should already be doing before the data ever reaches application code.&lt;/p&gt;

&lt;p&gt;This connected to and refreshed the SQL experience I thought I already knew from my data science work in Python. I saw that I knew how to write queries against data someone else had already organized for me. PostgreSQL, used properly inside a real application with real constraints, forced me to think about schema design, indexing, and query efficiency in a way ad hoc data science scripts never had.&lt;/p&gt;

&lt;h2&gt;
  
  
  My stateless tokens were rather stately
&lt;/h2&gt;

&lt;p&gt;Early in the program, I made a mistake common enough to be almost a rite of passage: I misunderstood how JWT authentication is supposed to work and often stored tokens in server side sessions (who doesn't love baking cookies, eh?), which defeats the entire point of a stateless token. JWTs are meant to be self contained and verified straight from the Authorization header on every request, no session middleware holding state on the server.&lt;/p&gt;

&lt;p&gt;I learned why stateless authentication exists as a pattern, and every project since, including my capstone, uses proper Bearer token verification with role based access control, and I understand exactly why it's built that way instead of just copying a template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reopening &lt;a href="https://myflorence.site" rel="noopener noreferrer"&gt;Florence&lt;/a&gt; with new eyes
&lt;/h2&gt;

&lt;p&gt;I'd actually already tried backend engineering before AltSchool. My first experience was when I was trying to figure out CORS limitations, and with some help from my friends I once wrote up a simple server. I even built my own startup's product, &lt;a href="https://myflorence.site" rel="noopener noreferrer"&gt;Florence*&lt;/a&gt;, surrounded by a lot of documentation and some AI (well before today's LLMs got as good as they have at coding).&lt;/p&gt;

&lt;p&gt;Around the seventh month of the program when I went back to Florence, it was actually a proud moment for me to be able to laugh at my code. I could point to the exact architectural gaps, the places I'd skipped proper validation, the parts where I'd solved problems with brute force instead of a structural fix. This was one of the more validating moments of the whole course. I hadn't just learned new things in a bootcamp, I could revisit problems I'd already run into in the wild, on my own, before I had the language for them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Projects for breakfast, lunch and dinner
&lt;/h2&gt;

&lt;p&gt;AltSchool's diploma program runs three semesters. Across all three, I worked on some thirteen projects as a requisite part of my coursework, not counting theoretical assessments. My &lt;a href="https://github.com/stars/akcumeh/lists/altschool-coursework" rel="noopener noreferrer"&gt;GitHub list&lt;/a&gt; has the full lineup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/akcumeh/altschool-s01-a01" rel="noopener noreferrer"&gt;Self intro in plain HTML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/akcumeh/altschool-s01-a02" rel="noopener noreferrer"&gt;HTML tables &amp;amp; media&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/akcumeh/altschool-s01-a03" rel="noopener noreferrer"&gt;A recipe page&lt;/a&gt; (my renowned fried rice, naturally)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/akcumeh/altschool-s01-a04" rel="noopener noreferrer"&gt;Self intro, rebuilt with CSS Flex &amp;amp; Grid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/akcumeh/altschool-s01-e01" rel="noopener noreferrer"&gt;A stopwatch&lt;/a&gt; (first semester exam)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/akcumeh/altschool-s02-a01" rel="noopener noreferrer"&gt;Servers &amp;amp; APIs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/akcumeh/altschool-s02-a02" rel="noopener noreferrer"&gt;Database design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/akcumeh/altschool-s02-a03" rel="noopener noreferrer"&gt;A to-do app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/akcumeh/altschool-s02-e01" rel="noopener noreferrer"&gt;A blog API&lt;/a&gt; (second semester exam, evolved into &lt;a href="https://blogr-ng.netlify.app/" rel="noopener noreferrer"&gt;Blogr&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/akcumeh/altschool-s03-a01" rel="noopener noreferrer"&gt;A guessing game&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/akcumeh/altschool-s03-a02" rel="noopener noreferrer"&gt;A birthday reminder app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/akcumeh/altschool-s03-a03" rel="noopener noreferrer"&gt;A restaurant chatbot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/akcumeh/altschool-s03-e01" rel="noopener noreferrer"&gt;Eventful&lt;/a&gt; (the capstone)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was roughly one significant submission every three to four weeks, for a full year. It was the kind of intensity I wanted, and throughout it I held myself to a standard of treating every assignment as something that should be portfolio-ready.&lt;/p&gt;

&lt;p&gt;First semester was web fundamentals: semantic HTML, CSS Flex &amp;amp; Grid, responsive layouts, and JS in the browser.&lt;/p&gt;

&lt;p&gt;Second semester was where the backend actually began: Express servers, MongoDB, REST API design, CORS, JWT and session-based auth, validating data with Joi, testing with Jest, documenting everything in Postman.&lt;/p&gt;

&lt;p&gt;Third semester raised the ceiling: TypeScript, cron jobs, queues with BullJS, webhooks, rate limiting, logging, security hardening for Express apps, WebSockets with Socket.io, object-oriented design, server-sent events. Best part? None of it stayed theoretical. Cron jobs became the core of the reminder emails on the birthday reminder app. Webhooks became the Paystack confirmation flow in the restaurant chatbot.&lt;/p&gt;

&lt;p&gt;By the time I got to my capstone project, I wasn't doing anything new under the pressure of a deadline or the need to make something fancy; I was simply applying patterns I'd already stress-tested a dozen times.&lt;/p&gt;

&lt;p&gt;Part of that standard also meant documenting my APIs properly, and I did not expect to enjoy this. Documenting an endpoint forces you to step through exactly what happens: what the request looks like, what validations run, what the response looks like when everything goes right and how I find the weak points in my own code. In my attempts to make the documentation clearer and more robust, I frequently caught errors and edge cases I had forgotten to think about, which usually meant the API got better in the process of fixing them. Documentation stopped being a chore to satisfy a grading rubric and started being another phase of the real work.&lt;/p&gt;

&lt;p&gt;One pattern that became obvious partway through the program was that &lt;a href="https://www.frontendmentor.io" rel="noopener noreferrer"&gt;Frontend Mentor&lt;/a&gt; challenges I'd built years ago as pure UI exercises could become full-stack, real products the moment I paired them with a proper backend. I just caught a fun opportunity to build functionality behind a design I already liked, and I didn't miss it. My favorite example is &lt;a href="https://blogr-ng.netlify.app/blogs" rel="noopener noreferrer"&gt;Blogr&lt;/a&gt;, originally a blog API &lt;a href="https://github.com/akcumeh/altschool-s02-e01" rel="noopener noreferrer"&gt;built&lt;/a&gt; and &lt;a href="https://documenter.getpostman.com/view/38823654/2sBXcBmguN" rel="noopener noreferrer"&gt;documented&lt;/a&gt; for my second semester exam, that's evolved into a full stack app with design inspiration drawn from a &lt;a href="https://www.frontendmentor.io/challenges/blogr-landing-page-EX2RLAApP" rel="noopener noreferrer"&gt;Frontend Mentor blog landing page&lt;/a&gt;. The aesthetic &amp;amp; style was extended to more pages to better capture the API's capabilities (see it on &lt;a href="https://github.com/akcumeh/17-ng-blogr" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;). I wrote about that semester &lt;a href="https://www.linkedin.com/posts/angelumeh_i-recently-wrapped-up-my-second-semester-activity-7444410747331248128-Y_CZ" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eventful, literally
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://akcumeh-eventful.vercel.app" rel="noopener noreferrer"&gt;Eventful&lt;/a&gt; is an event ticketing platform I submitted for my Capstone Project, and it's the clearest evidence of everything above landing in one place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NestJS on the backend, Next.js on the frontend&lt;/li&gt;
&lt;li&gt;Supabase/PostgreSQL for the data layer&lt;/li&gt;
&lt;li&gt;Paystack for payments, confirmed via webhooks&lt;/li&gt;
&lt;li&gt;Nodemailer for transactional email&lt;/li&gt;
&lt;li&gt;QR codes generated and embedded into ticket emails, scanned at the door to mark tickets used&lt;/li&gt;
&lt;li&gt;Scheduled reminder emails via &lt;code&gt;@nestjs/schedule&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;JWT auth with role separation: creators get event management and analytics, eventees get ticket purchasing and their own history&lt;/li&gt;
&lt;li&gt;&lt;a href="https://documenter.getpostman.com/view/38823654/2sBXwsMVu2" rel="noopener noreferrer"&gt;API Docs on Postman&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these pieces were unfamiliar by the time I built them. I'd already used Paystack for Florence* and on prior assignments like the restaurant chatbot. I'd worked with Supabase and PostgreSQL enough times that schema design felt automatic instead of intimidating, I even knew how to drop and recreate tables. The QR flow, encoding a ticket identifier, generating a PNG, storing it, verifying it later, was new in the specific implementation but not conceptually foreign, specifically because I'd already built comparable verification flows for smaller assignments, but generally because my time in AltSchool had reinforced in me how to use the knowledge I already have to gain more.&lt;/p&gt;

&lt;p&gt;I was selected to present Eventful at my pre-graduation showcase, and by all accounts it went well. Part of that came down to something I already had before the program: an eye for clean, consistent visual design, which you might notice in the &lt;a href="https://drive.google.com/file/d/1KU0I-3sClnF5GxO3XxqWqbZdB4kUSV8S/view" rel="noopener noreferrer"&gt;slides&lt;/a&gt;. But most of it came down to preparation: because the capstone wasn't far removed from a year of assignments and prior years of experience in technical communication &amp;amp; presentations, I could easily tell a technical story to a mixed audience without hesitation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The multitasker
&lt;/h2&gt;

&lt;p&gt;AltSchool ran concurrently with my NYSC service year. I remember missing my opening parade march to write my AltSchool entrance exam, which I &lt;a href="https://x.com/akcumeh/status/1934674982992244782" rel="noopener noreferrer"&gt;scored 90% on&lt;/a&gt;. By the time NYSC wrapped up on 21st May this year, I was eagerly awaiting the start of my capstone exam, which I submitted a fortnight later. For most of the stretch in between, I also held down full-time work: about seven months as a frontend engineer, followed by a full stack contract role for about 6 weeks. Backend fundamentals from AltSchool showed up almost immediately in decisions I was making at work, and constraints I ran into at work sharpened how I approached AltSchool assignments. It wasn't always easy to manage the schedule, but the pressure was exciting because I never had the luxury of learning something and forgetting it before I got to use it.&lt;/p&gt;

&lt;p&gt;In the same May, I built and shipped my portfolio site after almost 8 months of putting it off. It is live at &lt;a href="https://angelumeh.dev" rel="noopener noreferrer"&gt;angelumeh.dev&lt;/a&gt;, with most of what's here in more detail than a single article can hold.&lt;/p&gt;

&lt;h2&gt;
  
  
  More than code
&lt;/h2&gt;

&lt;p&gt;AltSchool's coursework wasn't only practical. Alongside the assignments there were quizzes that tested understanding, which separated it from being yet another code-and-submit bootcamp. But the part I didn't expect was the career support layered on top of the technical curriculum. CV positioning, application strategy, and professional presentation and communication were treated almost as seriously as the code. Some of it I already knew from experience, but it was a pleasant relief to know that AltSchool reinforced these things (and would have taught me regardless). I've since learned to present myself better as a candidate, a skill I've been approximating on my own for a long time.&lt;/p&gt;

&lt;p&gt;I'm really grateful for the friends who supported and encouraged me through the program, especially &lt;a href="https://www.linkedin.com/in/zubairidrisaweda" rel="noopener noreferrer"&gt;Zubair&lt;/a&gt; (&lt;a class="mentioned-user" href="https://dev.to/zubs"&gt;@zubs&lt;/a&gt;) who always had the time to read my code and helped me see the process of API documentation for what it is; and &lt;a href="https://www.linkedin.com/in/alabo-edwin-2596b123b/" rel="noopener noreferrer"&gt;Edwin&lt;/a&gt; who helped sharpen my understanding of database design. Working near experienced people and getting called out kindly but clearly made it more real and a lot less academic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;A year of AltSchool didn't just add backend skills to a frontend résumé. It gave me a way of thinking that connects both sides of a system, and thirteen projects' worth of proof that it wasn't accidental. &lt;/p&gt;

&lt;p&gt;What's actually next though is I'm searching for my next role. I build across the stack and I'm open to a role that connects me to talented people and allows me to build the way this past year has taught me to. If you're deciding whether a program like this is worth it when you already have some development experience, my answer is this article. 😁&lt;/p&gt;




&lt;h3&gt;
  
  
  Author
&lt;/h3&gt;

&lt;p&gt;Thank you for reading this far! Connect with me via:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://linkedin.com/in/angelumeh" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/akcumeh" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/akcumeh" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devjournal</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>Responsive Space Tourism App with React Native: What I Built &amp; What I Learned</title>
      <dc:creator>Angel Umeh</dc:creator>
      <pubDate>Fri, 22 Aug 2025 15:29:50 +0000</pubDate>
      <link>https://dev.to/akcumeh/responsive-space-tourism-app-with-react-native-what-i-built-what-i-learned-2h8d</link>
      <guid>https://dev.to/akcumeh/responsive-space-tourism-app-with-react-native-what-i-built-what-i-learned-2h8d</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;
About the Project

&lt;ul&gt;
&lt;li&gt;Goals&lt;/li&gt;
&lt;li&gt;Tools &amp;amp; Stack&lt;/li&gt;
&lt;li&gt;Features&lt;/li&gt;
&lt;li&gt;Links &amp;amp; Demo&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
What I learned

&lt;ul&gt;
&lt;li&gt;More React Native Components&lt;/li&gt;
&lt;li&gt;State Management with &lt;code&gt;useRef&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Data Persistence with &lt;code&gt;AsyncStorage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Improved Animations &amp;amp; Gestures&lt;/li&gt;
&lt;li&gt;Challenges&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;For my second swim in React Native development, I tackled a &lt;a href="https://www.frontendmentor.io/challenges/space-tourism-multipage-website-gRWj1URZ3" rel="noopener noreferrer"&gt;Frontend Mentor challenge&lt;/a&gt; to build a space tourism app.&lt;/p&gt;

&lt;p&gt;This was my second project built with React Native &amp;amp; Expo, and is the second project in my &lt;a href="https://github.com/akcumeh/rn-60d/blob/main/projects.md" rel="noopener noreferrer"&gt;60-day React Native challenge&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Goals
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Build my second &lt;strong&gt;React Native&lt;/strong&gt; cross-platform app&lt;/li&gt;
&lt;li&gt;Build on and advance in &lt;strong&gt;styling in React Native&lt;/strong&gt; &amp;amp; writing CSS-in-JS&lt;/li&gt;
&lt;li&gt;Implement improved &lt;strong&gt;interactivity&lt;/strong&gt; in my app&lt;/li&gt;
&lt;li&gt;Learn about &amp;amp; implement data persistence with &lt;strong&gt;AsyncStorage&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tools &amp;amp; Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;React Native + Expo&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;React Native &lt;strong&gt;&lt;code&gt;Animated&lt;/code&gt; API&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;AsyncStorage&lt;/li&gt;
&lt;li&gt;Route management with Expo Router&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I primarily used Expo Router for navigation, though React Navigation could also have been a fit. I chose Expo Router for its file-based simplicity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;p&gt;This is an interactive space tourism introduction. Users can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View each page&lt;/li&gt;
&lt;li&gt;Toggle between the tabs to see new information&lt;/li&gt;
&lt;li&gt;View the optimal layout for each of the website's pages depending on their device's screen size&lt;/li&gt;
&lt;li&gt;See hover states for all interactive elements on the page. On native devices, “hover states” translate to touch feedback rather than mouse hover.&lt;/li&gt;
&lt;li&gt;[Extra] Come back to their last viewed sections on each page&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Links &amp;amp; Demo
&lt;/h3&gt;

&lt;p&gt;You can find the app here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/akcumeh/13-rn-space-tourism" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.frontendmentor.io/solutions/responsive-space-tourism-app-with-react-native-4-zy52P9mf" rel="noopener noreferrer"&gt;Frontend Mentor solution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://space-tourism-rn.netlify.app" rel="noopener noreferrer"&gt;Live link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This live link is the web export of the React Native app via Expo, deployed on Netlify.&lt;/p&gt;

&lt;p&gt;Some snippets:&lt;/p&gt;

&lt;p&gt;Mobile Screenshots:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6sb8zi3v8a5md5x5x9j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6sb8zi3v8a5md5x5x9j.jpg" alt="Home - Mobile" width="800" height="1731"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmdtsuvk601v7jbip286z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmdtsuvk601v7jbip286z.jpg" alt="Destination - Mobile" width="800" height="1731"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzaiq56yg7xy0xe6x593l.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzaiq56yg7xy0xe6x593l.jpg" alt="Crew - Mobile" width="800" height="1731"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwf6y2d09fiofmjrseyn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwf6y2d09fiofmjrseyn.jpg" alt="Technology - Mobile" width="800" height="1731"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Desktop Screenshots:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb5j8ueznkqq7r50xb9ff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb5j8ueznkqq7r50xb9ff.png" alt="Home - Desktop" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ht1kh9pmflbtr0b7n42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ht1kh9pmflbtr0b7n42.png" alt="Destination - Desktop" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkttxcqvzzvppp5sbitda.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkttxcqvzzvppp5sbitda.png" alt="Crew - Desktop" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30v6hp3wrd97rwjzxpmr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30v6hp3wrd97rwjzxpmr.png" alt="Technology - Desktop" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;
&lt;h3&gt;
  
  
  More React Native &lt;strong&gt;Components&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I discovered more React Native components in this project, a little further removed from web development this time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ImageBackground&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;getBg&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;resizeMode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cover&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ScrollView&lt;/span&gt; &lt;span class="nx"&gt;contentContainerStyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;// Your content here&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ScrollView&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ImageBackground&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I learned to use &lt;code&gt;ImageBackground&lt;/code&gt; for full-screen background images that adapt to different screen sizes, and &lt;code&gt;ScrollView&lt;/code&gt; with &lt;code&gt;contentContainerStyle&lt;/code&gt; attribute for better content layout control within scrollable areas.&lt;/p&gt;

&lt;h3&gt;
  
  
  State Management with React &lt;strong&gt;&lt;code&gt;useRef&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useState&lt;/code&gt; remained an important part of my toolbox, managing the animation states, but &lt;code&gt;useRef&lt;/code&gt; allowed me to maintain animation values that would update frequently but that don't trigger re-renders.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slideAnim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scaleAnim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.95&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Data Persistence with &lt;strong&gt;AsyncStorage&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Just like JS &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;AsyncStorage&lt;/code&gt; allowed me to store and persist user choices like the selected destination or the last viewed crew member.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Save user selection&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;AsyncStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastDestination&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Load on app startup&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastDestination&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;AsyncStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastDestination&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Improved Animations &amp;amp; Gestures
&lt;/h3&gt;

&lt;p&gt;I got a much clearer understanding of the anatomy of a typical gesture, thanks to &lt;a href="https://x.com/eveningkid" rel="noopener noreferrer"&gt;@eveningkid&lt;/a&gt;'s &lt;a href="https://youtube.com/playlist?list=PLiVL41zTt2lIIdZvWBwzoCjOb84DKtOX6&amp;amp;si=Sc8Z-qLxfwrcaJlY" rel="noopener noreferrer"&gt;YouTube tutorials&lt;/a&gt;. I was able to progress from single animations to coordinated animation systems. On re-reading the &lt;a href="https://reactnative.dev/docs/animated" rel="noopener noreferrer"&gt;React Native &lt;code&gt;Animated&lt;/code&gt;&lt;/a&gt; docs, I found methods like &lt;code&gt;sequence()&lt;/code&gt;, &lt;code&gt;parallel()&lt;/code&gt;, &lt;code&gt;stagger()&lt;/code&gt;, and &lt;code&gt;loop()&lt;/code&gt;. I mostly used &lt;code&gt;parallel()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parallel&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slideAnim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;toValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleAnim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;toValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Distinct Responsive Layouts based on screen size
&lt;/h3&gt;

&lt;p&gt;Rather than just scaling elements, I learned to create fundamentally different layouts, where mobile stacks all the page content vertically, while desktop uses a two-column layout, each optimized for their respective interaction patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenges Faced
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Platform differences:
\
I realized that many functions, effects or other behaviors that seem normal on web may not apply on real devices.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rgba(11, 13, 23, 0.15)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;backdropFilter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blur(40px)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Works in browser, not iOS&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Gestures:
\
Making a functional multi-part gesture required me to properly understand the anatomy of a gesture. &lt;a href="https://x.com/eveningkid" rel="noopener noreferrer"&gt;@eveningkid&lt;/a&gt;'s tutorials helped me get that gestures are comprised of a start, a behavior, and a release.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;I enjoyed building this app. It was quite the challenge, but it helped me flex my layouts muscle.&lt;/p&gt;

&lt;p&gt;I also learned to create animation systems for smooth effects, and implement slightly more complicated gestures. Thanks to this project, I learned the anatomy of a gesture, and this will serve as a building block for more complicated ones in the future.&lt;/p&gt;

&lt;p&gt;This project is part of my &lt;a href="https://x.com/akcumeh/status/1951328182617120795" rel="noopener noreferrer"&gt;summer side quest&lt;/a&gt;.&lt;br&gt;
You can follow me on &lt;a href="https://x.com/akcumeh" rel="noopener noreferrer"&gt;X&lt;/a&gt; &amp;amp; &lt;a href="https://github.com/akcumeh" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; to keep up with the full challenge.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>typescript</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>To-do App with React Native: What I Built &amp; What I Learned</title>
      <dc:creator>Angel Umeh</dc:creator>
      <pubDate>Sun, 10 Aug 2025 22:33:46 +0000</pubDate>
      <link>https://dev.to/akcumeh/to-do-app-with-react-native-what-i-built-what-i-learned-4hej</link>
      <guid>https://dev.to/akcumeh/to-do-app-with-react-native-what-i-built-what-i-learned-4hej</guid>
      <description>&lt;p&gt;What Happens When A Web Developer Discovers Mobile Development?&lt;/p&gt;

&lt;p&gt;Let’s see!&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;For my first dive into React Native development, I tackled a &lt;a href="https://www.frontendmentor.io/challenges/todo-app-Su1_KokOW" rel="noopener noreferrer"&gt;Frontend Mentor challenge&lt;/a&gt; to build a fully-featured to-do app.&lt;/p&gt;

&lt;p&gt;This project was my first foray into the world of React Native &amp;amp; Expo, and is the first project in my React Native learning journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Goals
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Build my first &lt;strong&gt;React Native&lt;/strong&gt; cross-platform mobile app&lt;/li&gt;
&lt;li&gt;Learn &lt;strong&gt;styling in React Native&lt;/strong&gt; &amp;amp; writing CSS-in-JS&lt;/li&gt;
&lt;li&gt;Master fundamentals of mobile UI patterns&lt;/li&gt;
&lt;li&gt;Implement &lt;strong&gt;animations&lt;/strong&gt; and &lt;strong&gt;interactive gestures&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tools &amp;amp; Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;React Native + Expo&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;React Native &lt;strong&gt;&lt;code&gt;Animated&lt;/code&gt; API&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;React Native &lt;strong&gt;&lt;code&gt;Reanimated&lt;/code&gt; library&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;p&gt;This is a simple to-do app with all the basic functionality, as well as a few advanced interactions. Users can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add tasks&lt;/li&gt;
&lt;li&gt;Mark tasks as complete&lt;/li&gt;
&lt;li&gt;Delete tasks&lt;/li&gt;
&lt;li&gt;Filter tasks: view all, active or completed tasks&lt;/li&gt;
&lt;li&gt;Clear all completed tasks in one click&lt;/li&gt;
&lt;li&gt;Switch app between light &amp;amp; dark themes&lt;/li&gt;
&lt;li&gt;Drag &amp;amp; drop to reorder items&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Links &amp;amp; Demo
&lt;/h3&gt;

&lt;p&gt;You can find the app here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/akcumeh/16-todo-app" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://16-todo-app.netlify.app/" rel="noopener noreferrer"&gt;Live link&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some snippets:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogjl3fqnjjdpkuw99t2r.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogjl3fqnjjdpkuw99t2r.jpg" alt="Light theme - All tasks active" width="592" height="1280"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9vbur3qv4p7w5zb7cvj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9vbur3qv4p7w5zb7cvj.jpg" alt="Light theme - Partially-completed tasks" width="592" height="1280"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnm72negm9x9at7m4vidm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnm72negm9x9at7m4vidm.jpg" alt="Light theme - Completed filter" width="592" height="1280"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzie7vgiow4346993h46f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzie7vgiow4346993h46f.jpg" alt="Dark theme - Active filter" width="592" height="1280"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ng2byobmh5y75y7k8kq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ng2byobmh5y75y7k8kq.jpg" alt="Dark theme - New todo item" width="592" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fakcumeh%2Frn-60d%2Fblob%2Fmain%2Fassets%2Fvideos%2F16tda-demo-video.mp4" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fakcumeh%2Frn-60d%2Fblob%2Fmain%2Fassets%2Fvideos%2F16tda-demo-video.mp4" alt="Demo video" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;
&lt;h3&gt;
  
  
  React Native &lt;strong&gt;Components&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Components are the essential building blocks of React Native apps.&lt;br&gt;
They are analogous to other common elements used in web, Android and iOS app development.&lt;/p&gt;

&lt;p&gt;In this project I dealt directly with the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;View&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Text&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Button&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Image&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TextInput&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TouchableOpacity&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ScrollView&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FlatList&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Coming from a web development background, it was very interesting to draw the following parallels:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;React Native Component&lt;/th&gt;
&lt;th&gt;Web Equivalent&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;View&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;non-scrollable &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;A simple box that accepts layout, styling, user controls and accessibility controls, representing its children (however, does not scroll)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Text&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Used for displaying strings of text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Button&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A basic button with native styling (hence it looks different on web vs iOS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Image&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;An element that displays most types of pictures / images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;TextInput&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;input type="text"&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;An input item that takes text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;TouchableOpacity&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A more customizable button with native touch feedback &amp;amp; accessibility that can nest other content like images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;ScrollView&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A simple scrollable box that accepts layout, styling, user controls and accessibility controls, representing its children and rendering all its items at once&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;FlatList&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A list, with lazy rendering for large datasets.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Styling in React Native - &lt;strong&gt;&lt;code&gt;Stylesheet.create()&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;React Native styling felt familiar. Here, CSS must be written in a JavaScript Object that is then passed into the &lt;code&gt;Stylesheet.create()&lt;/code&gt; function. Then when any new element is created, the specific style(s) that apply are called in its style attribute. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Stylesheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;container1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;d34a76&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;container2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;c23ad4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;38005&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TestApp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;Hi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;I&lt;/span&gt; &lt;span class="nx"&gt;am&lt;/span&gt; &lt;span class="nx"&gt;Container&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;Hi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;I&lt;/span&gt; &lt;span class="nx"&gt;am&lt;/span&gt; &lt;span class="nx"&gt;Container&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;TestApp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some key differences from web CSS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flexbox by default&lt;/strong&gt;: Every View uses flexbox layout&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Column-first&lt;/strong&gt;: Default &lt;code&gt;flexDirection&lt;/code&gt; is &lt;code&gt;column&lt;/code&gt;, this makes sense for mobile apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No cascading&lt;/strong&gt;: Styles are scoped to components&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;State Management with React &lt;code&gt;useState&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;State Management is used to handle data within a component that is expected to change over time - it is like storage, but for React components.&lt;/p&gt;

&lt;p&gt;Managing many parts of my todo list required careful consideration and handling of data flow. &lt;code&gt;useState&lt;/code&gt; was used to manage the app theme and filter the todo list, while &lt;code&gt;useMemo&lt;/code&gt; minimized unnecessary rerenders when filtering large lists.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using custom fonts
&lt;/h3&gt;

&lt;p&gt;In an Expo project, there are two ways to import and use custom fonts other than the native font or Expo-provided fonts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the font assets to your project and import them, or&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the &lt;a href="https://github.com/expo/google-fonts" rel="noopener noreferrer"&gt;&lt;code&gt;expo-google-fonts&lt;/code&gt;&lt;/a&gt; library - for example, my app uses Josefin Sans, so I installed &lt;code&gt;expo-google-fonts/josefin-sans&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using linear gradients in Expo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating animations in React Native&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Animations &amp;amp; Gestures
&lt;/h3&gt;

&lt;p&gt;I implemented two animation systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React Native &lt;strong&gt;Animated API&lt;/strong&gt; for simple animations:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fadeAnim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fadeAnim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;toValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;useNativeDriver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;React Native &lt;strong&gt;Reanimated&lt;/strong&gt; library for hold-drag-and-drop gestures&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Challenges Faced
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Integrating SVG Assets:&lt;br&gt;
All of my icon assets were in SVG format, but React Native doesn't support SVGs out of the box. I had to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;code&gt;react-native-svg&lt;/code&gt; and &lt;code&gt;react-native-svg-transformer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Configure Metro bundler to handle SVG files:
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transformer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;babelTransformerPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-svg-transformer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assetExts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assetExts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceExts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;ul&gt;
&lt;li&gt;Import SVGs as React components:
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CrossIcon&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../assets/images/icon-cross.svg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;iOS compatibility issues:&lt;br&gt;
I learned to always specify &lt;code&gt;flex&lt;/code&gt; or &lt;code&gt;height&lt;/code&gt; properties for consistent cross-platform rendering.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Animations:&lt;br&gt;
Making an intuitive drag &amp;amp; drop gesture required that I do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gesture detection: I had to use a long-press to activate it to avoid interfering with the scrolling behavior.&lt;/li&gt;
&lt;li&gt;Position calculations: I had to detect where exactly the dragged item was being placed and do a little math to make sure that it was dropped at the right position.&lt;/li&gt;
&lt;li&gt;Spring motion: I included a small spring motion in order to make it more intuitive - something being picked up should appear to lift up and away from the list (closer to the user).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;It was fun to experience building mobile apps for the first time.&lt;/p&gt;

&lt;p&gt;React Native is very similar to React. The component-based architecture, hooks, and state management patterns all translate directly from my web development experience to mobile development. &lt;/p&gt;

&lt;p&gt;Flexbox-by-default and the component system make building responsive mobile UIs more straightforward than I expected.&lt;/p&gt;

&lt;p&gt;The animation APIs also opened my eyes to new possibilities for creating engaging, visually appealing and intuitive UXs that improve the "mobile app" feel. There's definitely more to learn before I move on to more complex gestures.&lt;/p&gt;

&lt;p&gt;I look forward to more complex projects and making future apps more accessible.&lt;/p&gt;

&lt;p&gt;This project is part of my &lt;a href="https://x.com/akcumeh/status/1951328182617120795" rel="noopener noreferrer"&gt;summer side quest&lt;/a&gt;. You can follow me on &lt;a href="https://x.com/akcumeh" rel="noopener noreferrer"&gt;X&lt;/a&gt; &amp;amp; &lt;a href="https://github.com/akcumeh" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; to keep up with the full challenge.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Angel Umeh</dc:creator>
      <pubDate>Tue, 05 Aug 2025 15:51:48 +0000</pubDate>
      <link>https://dev.to/akcumeh/-579</link>
      <guid>https://dev.to/akcumeh/-579</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/danielubenjamin/how-to-test-your-nodejs-postgres-app-using-drizzle-pglite-38h" class="crayons-story__hidden-navigation-link"&gt;How to Test Your Node.js &amp;amp; Postgres App Using Drizzle &amp;amp; PGlite&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/danielubenjamin" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F58350%2F7e831abd-f7c4-471c-90ca-1f98ab6bcc7d.jpeg" alt="danielubenjamin profile" class="crayons-avatar__image" width="800" height="1067"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/danielubenjamin" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Daniel Benjamin
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Daniel Benjamin
                
              
              &lt;div id="story-author-preview-content-2748058" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/danielubenjamin" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F58350%2F7e831abd-f7c4-471c-90ca-1f98ab6bcc7d.jpeg" class="crayons-avatar__image" alt="" width="800" height="1067"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Daniel Benjamin&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/danielubenjamin/how-to-test-your-nodejs-postgres-app-using-drizzle-pglite-38h" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 2 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/danielubenjamin/how-to-test-your-nodejs-postgres-app-using-drizzle-pglite-38h" id="article-link-2748058"&gt;
          How to Test Your Node.js &amp;amp; Postgres App Using Drizzle &amp;amp; PGlite
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/pglite"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;pglite&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/drizzle"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;drizzle&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/node"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;node&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/vitest"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;vitest&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/danielubenjamin/how-to-test-your-nodejs-postgres-app-using-drizzle-pglite-38h" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/danielubenjamin/how-to-test-your-nodejs-postgres-app-using-drizzle-pglite-38h#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>pglite</category>
      <category>drizzle</category>
      <category>node</category>
      <category>vitest</category>
    </item>
    <item>
      <title>#30DaysofCode September: My journey to DSA Mastery</title>
      <dc:creator>Angel Umeh</dc:creator>
      <pubDate>Mon, 30 Sep 2024 20:05:20 +0000</pubDate>
      <link>https://dev.to/akcumeh/30daysofcode-september-my-journey-to-dsa-mastery-647</link>
      <guid>https://dev.to/akcumeh/30daysofcode-september-my-journey-to-dsa-mastery-647</guid>
      <description>&lt;p&gt;This September, I embarked on a self-imposed &lt;strong&gt;30 Days of Code&lt;/strong&gt; challenge, a commitment to solve at least two Data Structures and Algorithms (DSA) problems every single day. My goal was to push myself out of my comfort zone, build consistency, and improve my problem-solving skills and programming logic.&lt;/p&gt;

&lt;p&gt;I didn’t just stick to one platform — I completed HackerRank’s &lt;a href="https://hackerrank.com/domains/tutorials/30-days-of-code" rel="noopener noreferrer"&gt;30 Days of Code challenge&lt;/a&gt;, LeetCode’s &lt;a href="https://leetcode.com/studyplan/30-days-of-javascript" rel="noopener noreferrer"&gt;30 Days of JavaScript plan&lt;/a&gt;, and also tackled LeetCode’s &lt;a href="https://leetcode.com/studyplan/top-interview-150" rel="noopener noreferrer"&gt;Top Interview 150 track&lt;/a&gt;, a collection of 150 typical interview problems for anyone prepping for a coding interview. Additionally, I took a few lessons on &lt;a href="https://structy.net" rel="noopener noreferrer"&gt;Structy&lt;/a&gt; to further strengthen my grasp of DSA concepts.&lt;/p&gt;

&lt;p&gt;I solved most problems using JavaScript (except for a few HackerRank problems where JavaScript wasn’t supported, so I used Python instead). To help keep myself accountable, as well as share my progress, I posted the challenges I solved each day on Twitter. You can find them in this quote trail: &lt;iframe class="tweet-embed" id="tweet-1840720685099864068-181" src="https://platform.twitter.com/embed/Tweet.html?id=1840720685099864068"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1840720685099864068-181');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1840720685099864068&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Types, Basic to Advanced
&lt;/h3&gt;

&lt;p&gt;Each day exposed me to different types of data structures and algorithms. I learned to handle&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;arrays&lt;/li&gt;
&lt;li&gt;strings&lt;/li&gt;
&lt;li&gt;objects&lt;/li&gt;
&lt;li&gt;maps&lt;/li&gt;
&lt;li&gt;sets&lt;/li&gt;
&lt;li&gt;numbers&lt;/li&gt;
&lt;li&gt;booleans, and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some problems involved more complex structures like linked lists and binary trees, while others threw matrices / n-D arrays into the mix, letting me deal in multidimensional spaces.&lt;/p&gt;

&lt;p&gt;The diversity of the problems kept me on my toes. The problems on LeetCode’s 30 Days of JavaScript track introduced me to fundamentals like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;array transformations&lt;/li&gt;
&lt;li&gt;function transformations&lt;/li&gt;
&lt;li&gt;closures&lt;/li&gt;
&lt;li&gt;classes&lt;/li&gt;
&lt;li&gt;JSONs&lt;/li&gt;
&lt;li&gt;Promises &amp;amp; time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LeetCode’s Top Interview 150 track took things a step further, tossing me between problems of varying difficulty and approach. Solving at least one of these each day was invaluable. These problems also challenged me to think more often about optimization and how different approaches could drastically affect runtime and memory efficiency.&lt;/p&gt;

&lt;p&gt;I also took Structy lessons alongside these challenges to solidify my understanding of key concepts. I learned more efficient ways to handle some data structures, like the sections on linked lists and binary trees. I came to especially appreciate the platform’s dynamic approach to teaching and breaking down problems in a way that makes them easy to digest. It’s a great platform to learn DSA at a very basic level and then translate this understanding to other coding problems I face.&lt;/p&gt;

&lt;h3&gt;
  
  
  Approaches and Techniques
&lt;/h3&gt;

&lt;p&gt;As the days progressed, I encountered many kinds of solution approaches, problem-solving techniques such as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;recursion&lt;/li&gt;
&lt;li&gt;two-pointer&lt;/li&gt;
&lt;li&gt;hashmap&lt;/li&gt;
&lt;li&gt;hashtable&lt;/li&gt;
&lt;li&gt;greedy algorithms&lt;/li&gt;
&lt;li&gt;binary search&lt;/li&gt;
&lt;li&gt;sliding window&lt;/li&gt;
&lt;li&gt;dynamic programming&lt;/li&gt;
&lt;li&gt;caching (memoization), and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found the two-pointer approach a straightforward yet powerful way to work through problems involving sequences (primarily arrays and strings), by reducing the search space for more efficient solutions. I also used greedy algorithms where I needed to make locally optimal choices at each step.&lt;/p&gt;

&lt;p&gt;Sliding window techniques were another eye-opener— initially challenging, but valuable for problems involving subarrays or substrings; problems that required keeping track of a moving range of elements within a sequence. Hashmaps and hashtables are great for key-value pairs in problems involving frequent lookups.&lt;/p&gt;

&lt;p&gt;One of the most complex techniques I worked with was dynamic programming. Early on, I found DP quite intimidating due to the difficulty in recognizing overlapping subproblems, but with repeated exposure memoization became my best friend in optimizing recursive calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function Manipulation (feat. Wrappers &amp;amp; Prototypes)
&lt;/h3&gt;

&lt;p&gt;In addition to core DSA problems, I also got the chance to try out more advanced JavaScript concepts. I wrote wrapper functions, learning how to control the flow of my code and extend functionality for specific requirements. I even learned to set timers on functions which allows me handle time-sensitive operations or limit how often certain functions can execute.&lt;/p&gt;

&lt;p&gt;Working with prototypes showed me that data types can be manipulated beyond their inbuilt capabilities by creating custom methods. This allowed me to extend the inbuilt functionality of data types like objects and arrays in new ways. I came to appreciate the importance of writing clean, modular code.&lt;/p&gt;

&lt;p&gt;I also learned memoization, a technique where you modify a function such that it stores previously called arguments with their results! This is a kind of caching that helps improve performance in problems where there are multiple calls to the same function. I wrote about my Memoize solution that beat 99% (memory) here: &lt;a href="https://leetcode.com/problems/memoize/solutions/5755775/memoize-intuitive-solution-beats-99-memory" rel="noopener noreferrer"&gt;Memoize Intutitive Solution beats 99% Memory&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing &amp;amp; Optimization
&lt;/h3&gt;

&lt;p&gt;Another thing I started to pay more attention to during this journey was the optimization of my code. After a proper introduction to big-O notation on Structy, I understood the importance of time and space complexity and I learned the optimal technique for most common problems. Toward the end of the HackerRank challenge track, I also learned to test code using classes and to write generics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Takeaway
&lt;/h3&gt;

&lt;p&gt;By the time I completed the 30 Days of Code challenge, I felt a profound sense of growth. It improved my ability to handle a wide range of problems and deepened my understanding of JavaScript and DSA. More than just solving problems, this month-long journey was a reminder to myself that I really could put in the effort. Seeing the rewards of consistency and discipline, I have been renewed with the mindset to approach any challenge with confidence and a strong toolkit of techniques.&lt;/p&gt;

&lt;p&gt;This experience marks a significant milestone in my programming journey. The skills I’ve sharpened over these 30 days will undoubtedly carry forward into my career as a software engineer.&lt;/p&gt;

&lt;p&gt;I am proud of me for having put in the effort, and grateful to my friends who cheered me on and offered their support and wisdom throughout the challenge.&lt;/p&gt;

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

</description>
      <category>dsa</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
