<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Bunmi Oye</title>
    <description>The latest articles on Forem by Bunmi Oye (@bunmioye).</description>
    <link>https://forem.com/bunmioye</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2625205%2F35dad113-d855-47b4-bef1-e5cf273cae76.png</url>
      <title>Forem: Bunmi Oye</title>
      <link>https://forem.com/bunmioye</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bunmioye"/>
    <language>en</language>
    <item>
      <title>How I Built an Infinite Scroll Photo Gallery with Vue 3 and the Unsplash API</title>
      <dc:creator>Bunmi Oye</dc:creator>
      <pubDate>Wed, 06 Aug 2025 10:10:39 +0000</pubDate>
      <link>https://forem.com/bunmioye/how-i-built-an-infinite-scroll-photo-gallery-with-vue-3-and-the-unsplash-api-21np</link>
      <guid>https://forem.com/bunmioye/how-i-built-an-infinite-scroll-photo-gallery-with-vue-3-and-the-unsplash-api-21np</guid>
      <description>&lt;p&gt;Creating a photo gallery powered by the &lt;a href="https://unsplash.com/developers" rel="noopener noreferrer"&gt;Unsplash API&lt;/a&gt; is a great way to build a media-rich, user-driven frontend experience. This walkthrough covers the core components of a Vue 3 + TypeScript application that integrates with Unsplash’s search endpoint to deliver an infinite-scroll image gallery with search support.&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%2F0x5lb372321npjg5d0ws.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%2F0x5lb372321npjg5d0ws.png" alt="gallery" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up the Project: Vite, Vue 3, TypeScript
&lt;/h2&gt;

&lt;p&gt;The project was scaffolded using Vite, Vue 3, and TypeScript to ensure fast dev builds, modern syntax, and type safety. The base structure included a &lt;code&gt;main.ts&lt;/code&gt; entry file, a minimal &lt;code&gt;App.vue&lt;/code&gt; shell, and clean CSS defaults via a custom &lt;code&gt;style.css&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To streamline development, Volar was installed via the VS Code extension store for Vue-specific TypeScript support.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Tip&lt;/strong&gt;: If you're using TypeScript with Vue, Volar offers the best IDE experience in VS Code right now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Building the Photo Fetch Logic
&lt;/h2&gt;

&lt;p&gt;I created a dedicated composable (hook) to fetch photos from Unsplash’s &lt;code&gt;search/photos&lt;/code&gt; endpoint using &lt;code&gt;axios&lt;/code&gt;. It accepted a query string and page number as parameters.&lt;/p&gt;

&lt;p&gt;This modular fetch logic allowed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic searching&lt;/li&gt;
&lt;li&gt;Infinite scrolling&lt;/li&gt;
&lt;li&gt;Reusability across components
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createApi&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unsplash-js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PHOTO_COUNT_PER_PAGE&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../constants&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchPhotos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createApi&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;accessKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPhotos&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;landscape&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;perPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PHOTO_COUNT_PER_PAGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using a composable pattern also made it easy to track request states like loading, success, or error, making the UI much easier to manage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Laying Out the Image Grid
&lt;/h2&gt;

&lt;p&gt;Images from the API were rendered in a grid layout via a dedicated component that accepted the photo data as props. I used CSS Grid to create a responsive, flexible layout that adapts to different screen sizes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Gallery&lt;/span&gt;
  &lt;span class="na"&gt;:photos=&lt;/span&gt;&lt;span class="s"&gt;"photos"&lt;/span&gt;
  &lt;span class="na"&gt;:status=&lt;/span&gt;&lt;span class="s"&gt;"fetchStatus"&lt;/span&gt;
  &lt;span class="na"&gt;:is-loading-initial=&lt;/span&gt;&lt;span class="s"&gt;"isLoadingInitial"&lt;/span&gt;
  &lt;span class="na"&gt;:is-loading-more=&lt;/span&gt;&lt;span class="s"&gt;"isLoadingMore"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each image included proper &lt;code&gt;alt&lt;/code&gt; text (based on Unsplash data) and CSS rules to maintain consistent aspect ratios and spacing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making It Searchable
&lt;/h2&gt;

&lt;p&gt;A search input was added at the top of the page, allowing users to dynamically query the Unsplash API.&lt;/p&gt;

&lt;p&gt;Here’s how it worked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a new term was submitted, the photo list was cleared&lt;/li&gt;
&lt;li&gt;The query state updated&lt;/li&gt;
&lt;li&gt;A new request was made, starting from page 1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This enabled users to explore terms like “mountains”, “sunsets”, or “cityscapes” in real-time through Unsplash’s library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Infinite Scroll Without Breaking Everything
&lt;/h2&gt;

&lt;p&gt;To reduce friction and improve the experience, I implemented infinite scroll. As users approached the bottom of the page, the app automatically requested the next page of results and appended them to the current list.&lt;/p&gt;

&lt;p&gt;Scroll position was tracked with an event listener, and throttling was applied to prevent spammy API requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;onMounted&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="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IntersectionObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loadMorePhotos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loadMoreRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;onBeforeUnmount&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;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This created a smooth, uninterrupted browsing experience, essential for image-heavy interfaces.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Note&lt;/strong&gt;: Be mindful of Unsplash’s API rate limits if you’re implementing this yourself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Happens When Things Break
&lt;/h2&gt;

&lt;p&gt;I added visual indicators to show when content was loading and included fallback UI for error states, like when the API request failed or hit its limit.&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%2Fay7bxnv53zx2pdlgqecv.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%2Fay7bxnv53zx2pdlgqecv.png" alt="gallery with loading photos" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whether it was a network hiccup or exceeding Unsplash’s rate limit, the app informed users without breaking flow or crashing the UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned (and You Might, Too)
&lt;/h2&gt;

&lt;p&gt;This project combined Vue 3’s modern frontend tools with Unsplash’s API to deliver a fast, engaging, and responsive image gallery.&lt;/p&gt;

&lt;p&gt;Key takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modular composables make fetch logic reusable and testable&lt;/li&gt;
&lt;li&gt;Infinite scroll feels great but needs careful handling&lt;/li&gt;
&lt;li&gt;Semantic HTML and thoughtful styling go a long way in user experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're looking to build something similar, start simple. Then iterate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;Some upgrades I would explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debounced search input to reduce redundant API requests&lt;/li&gt;
&lt;li&gt;Lazy-loading images to improve performance&lt;/li&gt;
&lt;li&gt;A photo modal for fullscreen previews and metadata&lt;/li&gt;
&lt;li&gt;LocalStorage (or backend) support for saving favorites&lt;/li&gt;
&lt;li&gt;Dark mode toggle (because why not?)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;This project was a fun way to learn and apply Vue 3 in a hands-on setting, while integrating with a real-world API. If you’re exploring Vue or just want to build something visual and interactive, a photo gallery like this is a great place to start.&lt;/p&gt;

&lt;p&gt;Working with Vue was a new experience for me, and I talked about that experience here: &lt;a href="https://dev.to/bunmioye/i-thought-react-was-clean-then-i-tried-vue-1m5k"&gt;I Thought React Was Clean, Then I Tried Vue&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Tooling I Used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;⚡ &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; – for super fast development&lt;/li&gt;
&lt;li&gt;🟦 TypeScript – for static typing&lt;/li&gt;
&lt;li&gt;🌄 &lt;a href="https://unsplash.com/developers" rel="noopener noreferrer"&gt;Unsplash API&lt;/a&gt; – for fetching beautiful images&lt;/li&gt;
&lt;li&gt;🧱 Vue 3 – using the Composition API&lt;/li&gt;
&lt;li&gt;🖼️ SCSS – scoped in &lt;code&gt;.vue&lt;/code&gt; files for styling&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔗 &lt;a href="https://github.com/bunmi-oye/splash" rel="noopener noreferrer"&gt;View the code here&lt;/a&gt;  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Thanks for reading! I'd love to hear your thoughts and experiences with Vue. What stood out to you the most? Let me know in the comments.&lt;/p&gt;

&lt;p&gt;Happy coding. 🚀&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Thought React Was Clean, Then I Tried Vue</title>
      <dc:creator>Bunmi Oye</dc:creator>
      <pubDate>Wed, 30 Jul 2025 08:00:00 +0000</pubDate>
      <link>https://forem.com/bunmioye/i-thought-react-was-clean-then-i-tried-vue-1m5k</link>
      <guid>https://forem.com/bunmioye/i-thought-react-was-clean-then-i-tried-vue-1m5k</guid>
      <description>&lt;h2&gt;
  
  
  Why I Finally Gave Vue a Shot
&lt;/h2&gt;

&lt;p&gt;As a frontend developer who's spent a lot of time with React, learning Vue has always been on my bucket list. I finally got my hands on Vue recently and I want to share my experience, highlighting the differences, similarities, and surprises along the way.&lt;/p&gt;

&lt;p&gt;Learning and using Vue was easier than I expected. At one point I genuinely thought, &lt;em&gt;“Man, they have it easy over here.”&lt;/em&gt; Vue’s simple yet functional nature is what I hope to share in this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a Job Application Pushed Me into Vue
&lt;/h2&gt;

&lt;p&gt;I applied for a job that required Vue, and given my strength in React, I was confident I could pick it up fast. The company had other plans, though, they required me to complete an assessment &lt;em&gt;using&lt;/em&gt; Vue.js. That turned my casual interest into a hands-on crash course.&lt;/p&gt;

&lt;h2&gt;
  
  
  Me and React: A Brief History
&lt;/h2&gt;

&lt;p&gt;My first hands-on experience with React was in 2020, back when &lt;code&gt;class components&lt;/code&gt; were still widely used. It was a bit of a headache to learn, but I leaned into it while appreciating the simpler &lt;code&gt;functional components&lt;/code&gt;. I started working with React professionally at an entry level in 2021.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Vue, and Why Now?
&lt;/h2&gt;

&lt;p&gt;Back in 2020, the options presented to me were React, Vue, or Angular. Angular seemed like it was falling out of favor (even though it wasn’t really losing Google’s support) while Vue felt a bit more alien than React (surprisingly). I sometimes wonder if starting with Vue would’ve been better, but I’m ultimately glad I picked React first. Learning Vue after React felt easier than I imagine the reverse would’ve been.&lt;/p&gt;

&lt;p&gt;Besides needing Vue for the assessment, I’d had it in mind for a while. The job just gave me the excuse I needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  My First Impressions of Vue
&lt;/h2&gt;

&lt;p&gt;Working with Vue was actually a lot more intuitive (and fun) than I expected. Vue files reminded me of vanilla web projects; HTML, CSS, and JavaScript all in one place.&lt;/p&gt;

&lt;p&gt;Vue components come in two flavors: the Options API and the Composition API. The Options API structures things around objects and is more declarative. The Composition API, introduced in Vue 3, is closer to the function-based style I'm used to in React. I tried the Options API briefly, but stuck with the Composition API because it felt more natural.&lt;/p&gt;

&lt;p&gt;A typical &lt;code&gt;.vue&lt;/code&gt; file contains three sections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"greeting"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; Hi mom! &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isReact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"scss"&lt;/span&gt; &lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nc"&gt;.greeting&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;font-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;italic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tag handles your rendered HTML and other components, kind of like the &lt;code&gt;return()&lt;/code&gt; in a React component. You can also render multiple elements without wrapping them in a div, just like React fragments. (Fun fact: Vue also supports JSX.)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;&amp;lt;script setup&amp;gt;&lt;/code&gt; block is where you declare state, functions, and imports, similar to what you'd place above the return statement in React.&lt;/li&gt;
&lt;li&gt;Styling is scoped by default and written in a &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; block using normal CSS selectors. It also allows using specific styling like SCSS.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building Something Real with Vue
&lt;/h2&gt;

&lt;p&gt;I built an infinite scroll photo gallery using the &lt;a href="https://unsplash.com/documentation" rel="noopener noreferrer"&gt;Unsplash API&lt;/a&gt;. Key features included:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keyword search via a search bar&lt;/li&gt;
&lt;li&gt;Displaying photos in a masonry-style grid&lt;/li&gt;
&lt;li&gt;Viewing each photo in a modal&lt;/li&gt;
&lt;li&gt;Auto-loading more photos when scrolling near the bottom&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I went into more detail in &lt;a href="https://dev.to/bunmioye/how-i-built-an-infinite-scroll-photo-gallery-with-vue-3-and-the-unsplash-api-21np"&gt;this post&lt;/a&gt;, but here’s what stood out compared to React.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetching on Page Load
&lt;/h3&gt;

&lt;p&gt;To load photos on page load, I used Vue’s &lt;code&gt;onMounted()&lt;/code&gt; lifecycle hook. It’s basically Vue’s version of React’s &lt;code&gt;useEffect(() =&amp;gt; {}, [])&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;onMounted&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="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;fetchPhotos&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Modals with &lt;code&gt;&amp;lt;teleport&amp;gt;&lt;/code&gt; vs React Portals
&lt;/h3&gt;

&lt;p&gt;For the modal, I wanted to append it directly under the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tag. In React, I’d use &lt;code&gt;ReactDOM.createPortal&lt;/code&gt;, but Vue makes this incredibly simple with the &lt;code&gt;&amp;lt;teleport&amp;gt;&lt;/code&gt; tag. Honestly, this might be my favorite Vue feature so far.&lt;/p&gt;

&lt;h4&gt;
  
  
  React Portal
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createPortal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Modal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;createPortal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is a modal!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Vue Teleport
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;teleport&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;"body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;This is a modal!&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/teleport&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modal closed&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%2Ft50u6fsrzkvl7jjgsric.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%2Ft50u6fsrzkvl7jjgsric.png" alt="photos in masonsry grid" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Modal open&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%2Fr7bhgkzt87pk3gg41w8i.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%2Fr7bhgkzt87pk3gg41w8i.png" alt="single photo opened in a modal" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Passing Props to Child Components
&lt;/h3&gt;

&lt;p&gt;To pass the selected photo to the modal, I used props. In Vue, you pass props using the &lt;code&gt;:&lt;/code&gt; shorthand for &lt;code&gt;v-bind&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Gallery&lt;/span&gt; &lt;span class="na"&gt;:photos=&lt;/span&gt;&lt;span class="s"&gt;"photos"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Infinite Scroll with Intersection Observer
&lt;/h3&gt;

&lt;p&gt;To implement infinite scrolling, I set up an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API" rel="noopener noreferrer"&gt;&lt;code&gt;IntersectionObserver&lt;/code&gt;&lt;/a&gt; inside the &lt;code&gt;onMounted()&lt;/code&gt; hook and cleaned it up using &lt;code&gt;onBeforeUnmount()&lt;/code&gt;, just like you would with a cleanup function in React.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;onMounted&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="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IntersectionObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loadMorePhotos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loadMoreRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;onBeforeUnmount&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;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skeleton loaders when scrolling down&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%2Fylmb3ndh2wy4uj78gcn5.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%2Fylmb3ndh2wy4uj78gcn5.png" alt="image showing skeleton loaders when newring the bootom of the screen" width="800" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts on Vue vs React
&lt;/h2&gt;

&lt;p&gt;React and Vue share many similarities, but Vue feels cleaner and more elegant in some areas. That said, I haven’t tackled advanced topics in Vue yet; like lazy loading, memoization, or server-side rendering (SSR). I know Vue might not have 1:1 equivalents for everything in React, and that’s okay. I'm excited to explore further and share what I learn.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tooling I Used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;⚡ &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; – for super fast development&lt;/li&gt;
&lt;li&gt;🟦 TypeScript – for static typing&lt;/li&gt;
&lt;li&gt;🌄 &lt;a href="https://unsplash.com/developers" rel="noopener noreferrer"&gt;Unsplash API&lt;/a&gt; – for fetching beautiful images&lt;/li&gt;
&lt;li&gt;🧱 Vue 3 – using the Composition API&lt;/li&gt;
&lt;li&gt;🖼️ SCSS – scoped in &lt;code&gt;.vue&lt;/code&gt; files for styling&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔗 &lt;a href="https://github.com/bunmi-oye/splash" rel="noopener noreferrer"&gt;View the code here&lt;/a&gt;  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Thanks for reading! I'd love to hear your thoughts and experiences with Vue or React. Have you tried switching between them? What stood out to you the most? Let me know in the comments.&lt;/p&gt;

&lt;p&gt;Happy coding. 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>vue</category>
      <category>frontend</category>
    </item>
    <item>
      <title>(Mis)Understanding React Context</title>
      <dc:creator>Bunmi Oye</dc:creator>
      <pubDate>Mon, 14 Apr 2025 05:00:00 +0000</pubDate>
      <link>https://forem.com/bunmioye/misunderstanding-react-context-2ei2</link>
      <guid>https://forem.com/bunmioye/misunderstanding-react-context-2ei2</guid>
      <description>&lt;p&gt;I've been building frontend websites with React for a while now, gaining experience with each passing year, but I recently made an assumption that cost me some hours of my life. I falsely believed that when using React context to manage state, using multiple providers in different sections of the codebase would all refer to the same state. Wild, I know.&lt;/p&gt;

&lt;h3&gt;
  
  
  A quick dive into React Context
&lt;/h3&gt;

&lt;p&gt;React context is an in-house solution to managing state in React. It shines best when used between parents and deeply nested children, as it prevents props drilling. For example, when you pass a state required by Component C as a prop from Component A through Component B to Component C, Component B receives the state so that it can pass it to Component C without using the state itself.&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%2Fdpx54h0b9763w4wnugu7.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%2Fdpx54h0b9763w4wnugu7.png" alt="Illustration of props drilling versus react context" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how you would do it without context&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ComponentA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ComponentB&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ComponentB receives state it does not use&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ComponentB&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ComponentC&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ComponentC&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can get messy when you pass the props through many children components.&lt;/p&gt;

&lt;p&gt;How to do it with context&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// context.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CounterContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CounterProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CounterContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;CounterContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ComponentA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CounterProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ComponentB&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;CounterProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// no longer receives state it does not use&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ComponentB&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ComponentC&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ComponentC&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CounterContext&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To extract and use a context value from &lt;code&gt;useContext&lt;/code&gt;, the component must be wrapped with the context provider. The implementation in Component A resolves to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ComponentA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CounterProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ComponentB&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ComponentC&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Count: 0 &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ComponentC&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ComponentB&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;CounterProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may be wondering why Component B, which still does not use the count state, needs to be wrapped with the provider? You would be correct. You should wrap the component (or preferably the children) at the topmost level that uses the state. In our case, we can wrap only Component C with the provider&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ComponentA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ComponentB&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CounterProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ComponentC&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Count: 0 &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ComponentC&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;CounterProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ComponentB&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A common bad practice is to wrap &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; (or its children), which is typically the topmost component, with the provider so that any child that needs the state has easy access. The problem with this is that whenever the state changes, the entire app re-renders.&lt;br&gt;
Imagine you have a landing page with a countdown timer below the navbar managed by context state. With every passing second, the entire page re-renders, including the hero, the footer, and all other possibly complex sections. &lt;br&gt;
The only time it's permissible to wrap &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; is when you have two components that need the state, and you're certain that &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; is the only common ancestor. If you get to that point, though, consider other state management libraries. However, React context is fine for small-scale state management, like theming.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Provider divide
&lt;/h3&gt;

&lt;p&gt;Remember when I said this?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The only time it's permissible to wrap &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; is when you have two components that need the state, and you're certain that &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; is the only common ancestor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I sometimes wondered why I can't wrap each component separately with the provider; that way, I don't have to wrap the entire &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt; with it, and both components access the state easily.&lt;br&gt;
In fact, I didn't just wonder, I did this implementation once and forgot that I did, and boy, did things go wrong.&lt;/p&gt;

&lt;p&gt;Cue the debug session. I would update the state, but would not see the expected re-render on one of the child components. I checked the state values to ensure that it's being updated, and it is, but one child component isn't receiving these changes. Frustrating.&lt;/p&gt;

&lt;p&gt;After a while, I finally noticed that I had the two components wrapped with separate providers, instead of wrapping a common ancestor component. The odd thing is that at that moment, I felt it was normal. It made sense. But my frustration led me to do a deep dive into the React context docs, and like a flash of lightning, I realised my mistake.&lt;/p&gt;

&lt;p&gt;React Context Provider manages the state and allows all nested children access to the state. However, when you wrap a section with the provider and another section with the same provider, you get two different instances of the context. It's the same way we are able to reuse a component multiple times in React. Every time the component is used, a different instance is made.&lt;/p&gt;

&lt;p&gt;Going back to my implementation, the two different components were referencing two different instances of the same context, and by extension, two different states, so they could not react to the same state change. The simple solution was to take out the providers wrapping each component and wrap the common ancestor with one provider. What a day that was.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Interestingly, what seemed like common sense to me at the time was more of a rookie mistake, but it was a real learning experience.&lt;br&gt;
React Context is useful for light state management, and proper usage means you identify all the components that use the context state, and then wrap their common ancestor with the provider. That way, they all have access to the same instance of that state.&lt;/p&gt;

&lt;p&gt;Thank you for your time. Let me know your thoughts on this, as well as your experience with React context. Enjoy coding.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>react</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
