<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Bocovo's blog]]></title><description><![CDATA[Bocovo's blog]]></description><link>https://juste.bocovo.me</link><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 17:48:04 GMT</lastBuildDate><atom:link href="https://juste.bocovo.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Build a Slider in React Native Using FlatList]]></title><description><![CDATA[When implementing a slider in React Native, many developers instinctively turn to external libraries, assuming that creating a slider from scratch is a complex task. However, what may seem like a daunting challenge is actually much simpler to accompl...]]></description><link>https://juste.bocovo.me/how-to-build-a-slider-in-react-native-using-flatlist</link><guid isPermaLink="true">https://juste.bocovo.me/how-to-build-a-slider-in-react-native-using-flatlist</guid><category><![CDATA[React Native]]></category><category><![CDATA[Slider]]></category><category><![CDATA[React Native FlatList]]></category><dc:creator><![CDATA[Juste R. Bocovo]]></dc:creator><pubDate>Sun, 22 Sep 2024 01:19:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1726967756792/9e68790c-ca8f-4bcd-bbb4-d95f2d68ca77.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When implementing a slider in React Native, many developers instinctively turn to external libraries, assuming that creating a slider from scratch is a complex task. However, what may seem like a daunting challenge is actually much simpler to accomplish in React Native using its built-in components—often more straightforward than implementing a similar feature on the web.</p>
<p>So, how can you build a slider without relying on third-party libraries?</p>
<p>In this tutorial, I'll show you how to create a fully functional slider in React Native using just <code>FlatList</code> with minimal code. It's an easy and effective approach that leverages React Native's native components to achieve smooth, efficient sliders.</p>
<p>We are going to create this style of slider</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726958469250/9ede3be7-7250-4e9a-abb4-f947223c0a2b.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-creating-the-item-component">Creating the item component</h3>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { View, Text, StyleSheet, Image } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;

<span class="hljs-keyword">interface</span> OnboardingCardProps {
  imageUrl: <span class="hljs-built_in">string</span>;
  title: <span class="hljs-built_in">string</span>;
  description: <span class="hljs-built_in">string</span>;
  width: <span class="hljs-built_in">number</span>;
}

<span class="hljs-keyword">const</span> OnboardingCard = <span class="hljs-function">(<span class="hljs-params">{
  imageUrl,
  title,
  description,
  width,
}: OnboardingCardProps</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    &lt;View style={[styles.container, { width }]}&gt;
      &lt;Image source={{ uri: imageUrl }} style={styles.image} /&gt;

      &lt;Text style={styles.title}&gt;{title}&lt;/Text&gt;

      &lt;Text style={styles.subtitle}&gt;{description}&lt;/Text&gt;
    &lt;/View&gt;
  );
};

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  container: {
    flex: <span class="hljs-number">1</span>,
    justifyContent: <span class="hljs-string">"center"</span>,
    alignItems: <span class="hljs-string">"center"</span>,
    padding: <span class="hljs-number">20</span>,
    backgroundColor: <span class="hljs-string">"#fff"</span>,
  },
  image: {
    width: <span class="hljs-number">150</span>,
    height: <span class="hljs-number">150</span>,
    resizeMode: <span class="hljs-string">"contain"</span>,
    marginBottom: <span class="hljs-number">20</span>,
  },
  title: {
    fontSize: <span class="hljs-number">24</span>,
    fontWeight: <span class="hljs-string">"bold"</span>,
    color: <span class="hljs-string">"#000"</span>,
    textAlign: <span class="hljs-string">"center"</span>,
    marginBottom: <span class="hljs-number">10</span>,
  },
  subtitle: {
    fontSize: <span class="hljs-number">16</span>,
    color: <span class="hljs-string">"#666"</span>,
    textAlign: <span class="hljs-string">"center"</span>,
    paddingHorizontal: <span class="hljs-number">20</span>,
  },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> OnboardingCard;
</code></pre>
<h3 id="heading-creating-the-slider">Creating the slider</h3>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Dimensions, FlatList, StyleSheet } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;
<span class="hljs-keyword">import</span> { onboardingSteps } <span class="hljs-keyword">from</span> <span class="hljs-string">"data/onboarding"</span>;
<span class="hljs-keyword">import</span> OnboardingCard <span class="hljs-keyword">from</span> <span class="hljs-string">"components/onboarding/OnboardingCard"</span>;

<span class="hljs-keyword">const</span> screenWidth = <span class="hljs-built_in">Math</span>.round(Dimensions.get(<span class="hljs-string">"window"</span>).width);

<span class="hljs-keyword">const</span> Onboarding = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    &lt;FlatList
      style={styles.slider}
      horizontal
      data={onboardingSteps}
      showsHorizontalScrollIndicator={<span class="hljs-literal">false</span>}
      contentContainerStyle={styles.sliderItemsWrapper}
      pagingEnabled
      renderItem={<span class="hljs-function">(<span class="hljs-params">{ item }</span>) =&gt;</span> (
        &lt;OnboardingCard
          width={screenWidth}
          title={t(item.title)}
          description={t(item.description)}
          image={item.image}
        /&gt;
      )}
    /&gt;
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Onboarding;

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  viewport: {
    flex: <span class="hljs-number">1</span>,
  },
  wrapper: {
    flex: <span class="hljs-number">1</span>,
  },
  slider: {
    flex: <span class="hljs-number">1</span>,
  },
  sliderItemsWrapper: {
    display: <span class="hljs-string">"flex"</span>,
    alignItems: <span class="hljs-string">"center"</span>,
  },
});
</code></pre>
<h3 id="heading-explaining-the-props-used-on-the-flatlist">Explaining the props used on the FlatList</h3>
<ul>
<li><p><code>horizontal</code> prop allow us to have items aligned horizontally</p>
</li>
<li><p>The <code>pagingEnabled</code> prop is what creates the “snapping” effect in a scrollable view. When this prop is set to <code>true</code>, the user can only scroll one full page (or item) at a time, causing the scroll to “snap” to the nearest page when they release their finger. This means that partial views of items won't be left visible; the scroll will always land in such a way that one full item is shown, creating a smooth, page-by-page scrolling experience.</p>
</li>
<li><p>Without it, here is how the scroll goes</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726961699040/cf6c206a-a2cb-4503-b761-89ae9597a19e.gif" alt class="image--center mx-auto" /></p>
<p>  But with it, we got this</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726964450296/c01ca70f-8a0c-407e-93fb-7af61076c810.gif" alt class="image--center mx-auto" /></p>
</li>
<li><p><code>showsHorizontalScrollIndicator</code> is to hide the scroll indication</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">To show only one item at a time, make sure both the <code>FlatList</code> and its items have the same width.</div>
</div>

<h3 id="heading-adding-the-indicators">Adding the indicators</h3>
<h4 id="heading-dot-component-the-dot-item-component">Dot component ( the dot item component )</h4>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { StyleSheet, View } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;

<span class="hljs-keyword">interface</span> DotProps {
  active: <span class="hljs-built_in">boolean</span>;
}

<span class="hljs-keyword">const</span> Dot = <span class="hljs-function">(<span class="hljs-params">{ active }: DotProps</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> &lt;View style={[styles.dot, ...(active ? [styles.active] : [])]} /&gt;;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Dot;

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  dot: {
    backgroundColor: <span class="hljs-string">"#D3BDF2"</span>,
    borderRadius: <span class="hljs-number">50</span>,
    marginHorizontal: <span class="hljs-number">5</span>,
    width: <span class="hljs-number">10</span>,
    height: <span class="hljs-number">10</span>,
  },
  active: {
    width: <span class="hljs-number">16</span>,
    height: <span class="hljs-number">16</span>,
    backgroundColor: <span class="hljs-string">"#6A3EFC"</span>,
  },
});
</code></pre>
<h4 id="heading-the-dots-list-component">The dots list component</h4>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { StyleSheet, View } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;
<span class="hljs-keyword">import</span> Dot <span class="hljs-keyword">from</span> <span class="hljs-string">"./Dot"</span>;

<span class="hljs-keyword">interface</span> DotIndicatorsProps {
  itemCount: <span class="hljs-built_in">number</span>;
  activeIndex: <span class="hljs-built_in">number</span>;
}
<span class="hljs-keyword">const</span> DotIndicators = <span class="hljs-function">(<span class="hljs-params">{ activeIndex, itemCount }: DotIndicatorsProps</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    &lt;View style={styles.container}&gt;
      {<span class="hljs-built_in">Array</span>.from({ length: itemCount }).map(<span class="hljs-function">(<span class="hljs-params">_, index</span>) =&gt;</span> (
        &lt;Dot active={activeIndex === index} /&gt;
      ))}
    &lt;/View&gt;
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> DotIndicators;

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  container: {
    flexDirection: <span class="hljs-string">"row"</span>,
    justifyContent: <span class="hljs-string">"center"</span>,
    alignItems: <span class="hljs-string">"center"</span>,
  },
});
</code></pre>
<h4 id="heading-creating-a-state-for-the-current-item">Creating a state for the current item</h4>
<p>Storing the current active index into a state and display the dots indicators.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Dimensions, FlatList, StyleSheet } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-native"</span>;
<span class="hljs-keyword">import</span> { onboardingSteps } <span class="hljs-keyword">from</span> <span class="hljs-string">"data/onboarding"</span>;
<span class="hljs-keyword">import</span> OnboardingCard <span class="hljs-keyword">from</span> <span class="hljs-string">"components/onboarding/OnboardingCard"</span>;

<span class="hljs-keyword">const</span> screenWidth = <span class="hljs-built_in">Math</span>.round(Dimensions.get(<span class="hljs-string">"window"</span>).width);

<span class="hljs-keyword">const</span> Onboarding = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [currentIndex, setCurrentIndex] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">return</span> (
    &lt;&gt;
        &lt;FlatList
          <span class="hljs-comment">// ...</span>
          viewabilityConfig={{ viewAreaCoveragePercentThreshold: <span class="hljs-number">100</span> }}
          onViewableItemsChanged={<span class="hljs-function">(<span class="hljs-params">{ viewableItems, changed }</span>) =&gt;</span> {
                <span class="hljs-keyword">const</span> currentIndex = viewableItems.at(<span class="hljs-number">0</span>)?.index;
                <span class="hljs-keyword">if</span> (currentIndex !== <span class="hljs-literal">null</span> &amp;&amp; currentIndex !== <span class="hljs-literal">undefined</span>) {
                  setCurrentIndex(currentIndex);
                }
          }}
        /&gt;

        &lt;DotIndicators
           itemCount={onboardingSteps.length}
           activeIndex={currentIndex}
        /&gt;
    &lt;/&gt;
  );
};
</code></pre>
<p>The <code>viewabilityConfig.viewAreaCoveragePercentThreshold</code> prop determines the percentage of an item that must be visible for it to be considered "viewable" within the viewport. By setting this value to <code>100</code>, the item will only be considered "viewable" when it is fully visible (i.e., 100% of the item's area is visible on the screen).</p>
<p>This ensures that the current index calculation is more accurate, particularly when the user is scrolling slowly. Without this setting, items that are only partially visible could be incorrectly marked as "viewable," causing the <code>currentIndex</code> to update prematurely or inaccurately. By enforcing the requirement that an item must be fully visible, you prevent incorrect index changes that can occur when the user is scrolling slowly and only small parts of items are entering or exiting the viewport.</p>
<p>In short, setting the <code>viewAreaCoveragePercentThreshold</code> to <code>100%</code> ensures that the current item index only changes when the item is fully in view, leading to more precise behavior during slow scrolling.</p>
<h3 id="heading-the-result">The result</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726969982458/086ffdb8-c4ac-4640-9a80-0f9698835335.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>You only need three props to create a slider in React Native without external libraries:</p>
<ul>
<li><p><code>pagingEnabled</code>: Enables the snap effect for smooth scrolling.</p>
</li>
<li><p><code>onViewableItemsChanged</code>: Tracks the active item as the user scrolls.</p>
</li>
<li><p><code>viewabilityConfig.viewAreaCoveragePercentThreshold</code>: Ensures accurate active index calculation by requiring 100% of the item to be visible.</p>
</li>
</ul>
<p>With just these props, you can easily create a slider using React Native's built-in components.</p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li><p><a target="_blank" href="https://kps250.medium.com/creating-image-slider-with-flatlist-in-react-native-1815d3793d99">https://kps250.medium.com/creating-image-slider-with-flatlist-in-react-native-1815d3793d99</a></p>
</li>
<li><p><a target="_blank" href="https://reactnative.dev/docs/flatlist#viewabilityconfig">https://reactnative.dev/docs/flatlist#viewabilityconfig</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How Vite helped me on my React source code exploration adventure.]]></title><description><![CDATA[Diving into the depths of React.js source code or embarking on a journey of reverse engineering can be an exhilarating endeavor. To complete your journey, you'll need a small React application to act as your compass. So, how can you preview this smal...]]></description><link>https://juste.bocovo.me/how-vite-helped-me-on-my-react-source-code-exploration-adventure</link><guid isPermaLink="true">https://juste.bocovo.me/how-vite-helped-me-on-my-react-source-code-exploration-adventure</guid><category><![CDATA[React]]></category><category><![CDATA[reverse engineering]]></category><category><![CDATA[vite]]></category><dc:creator><![CDATA[Juste R. Bocovo]]></dc:creator><pubDate>Sat, 21 Sep 2024 22:15:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1726955821520/57c7b04f-0e79-444d-a239-d0cee72b9226.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Diving into the depths of React.js source code or embarking on a journey of reverse engineering can be an exhilarating endeavor. To complete your journey, you'll need a small React application to act as your compass. So, how can you preview this small app ? The essential step for most individuals is to create an HTML file and utilize a Content Delivery Network (CDN) to import React.js scripts. This approach typically fulfills all necessary requirements. However, for those interested in reverse engineering or seeking a more comprehensive exploration experience, there exists another method. In this post, I'll show you how I created this application using React's direct source code with vite.js.</p>
<h3 id="heading-lets-delve-into-how-its-accomplished-with-html-and-reactjs-builds">Let's delve into how it's accomplished with HTML and React.js builds</h3>
<ol>
<li>Using React CDN</li>
</ol>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react@18.2.0/umd/react.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/react-dom@18.2.0/umd/react-dom.development.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/babel-standalone@6/babel.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"container"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/babel"</span>&gt;</span><span class="javascript">
      ReactDOM.render(
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>,
        <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'container'</span>)
      );
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<ol start="2">
<li><p>Self bundles creation from React source code</p>
<p> According to <a target="_blank" href="https://legacy.reactjs.org/docs/how-to-contribute.html">React contribution docs</a> you can build the source code with <code>yarn build</code> and open the <code>fixtures/packaging/babel-standalone/dev.html</code> to preview the result of the build. The contents of this file are the same as above, except that it loads the bundles generated by the yarn build command.</p>
</li>
</ol>
<h3 id="heading-is-there-any-drawback-to-using-bundles-in-your-exploration-journey">Is there any drawback to using bundles in your exploration journey ?</h3>
<p>While bundles serve a purpose, I believe there's another approach that offers a superior exploration experience. Bundles do have their limitations:</p>
<ul>
<li><p>You can't easily get to grips with module organization while debugging. There's no <code>.map</code> files.</p>
</li>
<li><p>When you make some changes in the code you need to re-build each time. There's no existing auto-reload features.</p>
</li>
</ul>
<p>I tried to change the build configs to create <code>.map</code> files, but I get an error.</p>
<h3 id="heading-how-vite-helped-me">How <code>Vite</code> helped me ?</h3>
<p>During my exploration of the React source code, I promptly encountered the constraints I previously mentioned. I pondered on a method to bring the source code directly to the browser without resorting to bundles. Knowing that <code>Vite</code> operates in this manner, I decided to leverage it.</p>
<p>I learned that the React codebase utilizes the <code>yarn</code> workspaces feature, which implies that I can conveniently create a new package (workspace) within these workspaces to share React's source code. This is precisely what I proceeded to do. However, I encountered additional challenges along the way. In the subsequent lines, I will elucidate on my implementation.</p>
<h4 id="heading-1-i-create-new-workspace-with-me-example-application-code-using-vite">1. I create new workspace with me example application code using <code>Vite</code>.</h4>
<ul>
<li>In the <code>packages</code> folder in React source code, I create new project using <code>vite-create</code></li>
</ul>
<pre><code class="lang-bash">yarn create vite preview-react --template vanilla
<span class="hljs-comment"># You might ask why use the vanilla template and not this React one? </span>
<span class="hljs-comment"># Because the vanilla template is easier to clean.</span>

<span class="hljs-comment"># The command will create `preview-react` folder</span>
</code></pre>
<ul>
<li><p>Delete all the generated files without <code>package.json</code> and the <code>index.html</code> files</p>
</li>
<li><p>Update the <code>index.html</code> file as follows</p>
</li>
</ul>
<pre><code class="lang-javascript">&lt;!DOCTYPE html&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>React preview<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./App.jsx"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<ul>
<li>Create <code>App.jsx</code> file with the content below</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { createRoot } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Counter</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{count}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count + 1)}&gt;
        Increment
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}

<span class="hljs-keyword">const</span> root = createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'app'</span>));
root.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Counter</span> /&gt;</span></span>);
</code></pre>
<h4 id="heading-2-add-react-dependencies">2. Add <code>React</code> dependencies</h4>
<p>I require two dependencies: react and react-dom. To obtain their version numbers, I navigate to the package.json file within each respective package (located in the packages folder of the React code base). Upon noting down the version numbers, I update the package.json file of the preview-react workspace with the identified versions.</p>
<pre><code class="lang-json">{
...
<span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"react"</span>: <span class="hljs-string">"put-identified-react-version-here"</span>,
    <span class="hljs-attr">"react-dom"</span>: <span class="hljs-string">"put-identified-react-dom-version-here"</span>
  }
}
</code></pre>
<h4 id="heading-3-create-custom-vite-config">3. Create custom <code>vite</code> config</h4>
<p>We need to add some custom configs to make <code>vite</code> work properly with react code base.</p>
<ul>
<li><strong>Transpile flow files</strong><br />  React code base uses <code>flow.js</code> for typing, necessitating transpilation before it can be sent to the browser. Fortunately, there's good news: there exists a <code>Vite</code> plugin tailored for this purpose.</li>
</ul>
<pre><code class="lang-json">yarn add -D @bunchtogether/vite-plugin-flow
</code></pre>
<blockquote>
<p>If the installation fails with an error like <code>An unexpected error occurred: "expected workspace package to exist for "..."".</code> , try to manually add <code>@bunchtogether/vite-plugin-flow</code> in <code>devDependencies</code> and run <code>yarn</code></p>
</blockquote>
<ul>
<li><strong>Load the flow plugin</strong><br />  Create <code>vite.config.js</code> file with the content below</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { esbuildFlowPlugin, flowPlugin } <span class="hljs-keyword">from</span> <span class="hljs-string">'@bunchtogether/vite-plugin-flow'</span>;
<span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vite'</span>;

<span class="hljs-keyword">const</span> flowPluginOptions = {
  <span class="hljs-attr">include</span>: <span class="hljs-regexp">/\.(flow|js?)$/</span>,
  exclude: <span class="hljs-regexp">/node_modules/</span>,
  flow: {
    <span class="hljs-comment">// The `all` flag is set to `true` to force transpiling of all files.</span>
    <span class="hljs-comment">// The plugin expects files typed with flow to include the `@flow` annotation.</span>
    <span class="hljs-comment">/// But not all react modules include this annotation, even if they are</span>
    <span class="hljs-comment">// flow-typed.</span>
    <span class="hljs-attr">all</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">pretty</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">ignoreUninitializedFields</span>: <span class="hljs-literal">false</span>,
  },
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">plugins</span>: [flowPlugin(flowPluginOptions)],
  <span class="hljs-attr">optimizeDeps</span>: {
    <span class="hljs-attr">esbuildOptions</span>: {
      <span class="hljs-attr">plugins</span>: [
        esbuildFlowPlugin(
          flowPluginOptions.include,
          <span class="hljs-literal">undefined</span>,
          flowPluginOptions.flow,
        ),
      ],
    },
  },
});
</code></pre>
<ul>
<li><p><strong>Create some React global values</strong></p>
<p>  The React source code depends on certain global variables that are typically defined or replaced at build time by tools like <code>webpack</code> or <code>rollup</code>. Since I'm not utilizing <code>webpack</code> or <code>rollup</code>, I need to manually provide these values. I leverage <code>Vite's</code> global variable feature for this purpose. Subsequently, I include the necessary line in the <code>Vite</code> configuration.</p>
</li>
</ul>
<pre><code class="lang-javascript">...

export <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">plugins</span>: ...,
  <span class="hljs-attr">optimizeDeps</span>: ...,
  <span class="hljs-attr">define</span>: {
    <span class="hljs-attr">__DEV__</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">__EXPERIMENTAL__</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">__EXTENSION__</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">__PROFILE__</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">__TEST__</span>: <span class="hljs-literal">false</span>,
  },
});
</code></pre>
<h4 id="heading-4-resolve-some-importation-in-react-code-base">4. Resolve some importation in React code base</h4>
<p>This section of the article might pose a challenge for understanding. Allow me to clarify the necessity of this resolution.<br />Take a look at the <a target="_blank" href="https://github.com/facebook/react/blob/9e3b772b8cabbd8cadc7522ebe3dde3279e79d9e/packages/react/src/ReactServerContext.js#L22">line 22</a> of this file <code>packages/react/src/ReactServerContext.js</code> of React code base, you will see this importation.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// packages/react/src/ReactServerContext.js</span>

<span class="hljs-keyword">import</span> ReactSharedInternals <span class="hljs-keyword">from</span> <span class="hljs-string">'shared/ReactSharedInternals'</span>;
</code></pre>
<blockquote>
<p>This module is imported in <code>packages/react/src/React.js</code> this one imported in <code>packages/react/index.js</code>.<br />Notice that we are in the <code>react</code> package and trying to import something from the <code>shared</code> package.</p>
</blockquote>
<p>Now let's take a look at the <code>shared/ReactSharedInternals</code> file at its line <a target="_blank" href="https://github.com/facebook/react/blob/9e3b772b8cabbd8cadc7522ebe3dde3279e79d9e/packages/shared/ReactSharedInternals.js#L10">10</a>, the content is below</p>
<pre><code class="lang-javascript">
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> ReactSharedInternals =
  React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
</code></pre>
<blockquote>
<p>This module depends on <code>react</code> package.</p>
</blockquote>
<p>There is a circle dependency. Take a look at the graph below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711127469250/e7afeeda-1b13-4811-9945-12d341a9c443.png" alt class="image--center mx-auto" /></p>
<p>Let me show you another stuff. Go to the <code>packages/react-reconciler/src/ReactFiberHydrationContext.old.js</code> file. At its line <a target="_blank" href="https://github.com/facebook/react/blob/9e3b772b8cabbd8cadc7522ebe3dde3279e79d9e/packages/react-reconciler/src/ReactFiberHydrationContext.old.js#L42">42</a> you will see some import from <code>packages/react-reconciler/src//ReactFiberHostConfig</code> .</p>
<pre><code class="lang-javascript">
<span class="hljs-comment">// We expect that our Rollup, Jest, and Flow configurations</span>
<span class="hljs-comment">// always shim this module with the corresponding host config</span>
<span class="hljs-comment">// (either provided by a renderer, or a generic shim for npm).</span>
<span class="hljs-comment">//</span>
<span class="hljs-comment">// We should never resolve to this file, but it exists to make</span>
<span class="hljs-comment">// sure that if we *do* accidentally break the configuration,</span>
<span class="hljs-comment">// the failure isn't silent.</span>

<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'This module must be shimmed by a specific renderer.'</span>);
</code></pre>
<p>The module triggers an error unconditionally. and notably lacks any export statement. However, it includes a clear comment.</p>
<p>What you need to understand is that during build certain imports are resolved in a specific way. For example, the circular dependency that I'm talking about a little earlier will be fixed, by importing the <code>react/src/ReactSharedInternals</code> module instead of <code>react</code> in the <code>shared/ReactSharedInternals.js</code> file. And the import of <code>react-reconciler/src//ReactFiberHostConfig</code> in module <code>react-reconciler/src/ReactFiberHydrationContext.old.js</code> will be replaced by <code>react-reconciler/src/forks/ReactFiberHostConfig.dom.js</code> in as part of a build for the web.</p>
<p>There are many similar cases in the code base. The resolution of the two that I talked about allows React to work in the browser, we are not going to worry about the rest. If you're interested in seeing how the resolution is done, then take a look at this <a target="_blank" href="https://github.com/facebook/react/blob/9e3b772b8cabbd8cadc7522ebe3dde3279e79d9e/scripts/rollup/forks.js#L1">file</a>. The easiest way to make the <code>vite</code> project work <code>quickly</code> with these new elements is to modify the corresponding files with the correct imports. This involves modifying the React source code. Alternatively, the resolution can be handled in the Vite config by creating a plugin (which I've done, although I won't include those details in this article; you can check them here.</p>
<p>Let's do it quickly by modifying the codebase.</p>
<ul>
<li>Change import in <code>packages/shared/ReactSharedInternals.js</code> file. Replace its content by the follow.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> ReactSharedInternals <span class="hljs-keyword">from</span> <span class="hljs-string">'react/src/ReactSharedInternals'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ReactSharedInternals;
</code></pre>
<ul>
<li>Replace the content of <code>packages/react-reconciler/src/ReactFiberHostConfig.js</code><br />  by the content below.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> * <span class="hljs-keyword">from</span> <span class="hljs-string">'react-reconciler/src/forks/ReactFiberHostConfig.dom.js'</span>;
</code></pre>
<p>Now there are all necessary to the preview app to works.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711359534825/5a340f86-472b-4587-acfc-093bb76d7fce.png" alt class="image--center mx-auto" /></p>
<p>This makes exploration much smoother.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Exploring React's source code in order to gain an in-depth understanding of its operation and architecture is an exhilarating undertaking. We need a small React application as a guide. Generally speaking, this is an HTML page into which we import React's scripts (bundles). This technique, while satisfactory, has some limitations: slow build times and lack of source maps.</p>
<p>In this article, I presented an alternative method using <code>Vite</code>, bypassing the need for bundling and bringing React source code directly to the browser. This involved creating a new workspace within React's yarn workspaces feature and configuring <code>Vite</code> to handle Flow.js files and resolve specific imports.</p>
<blockquote>
<p>I create a public repo that includes the example application with <code>Vite</code>, find it <a target="_blank" href="https://github.com/BOCOVO/vite-example-app-template-to-explore-react-depths">here</a>.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Visualize the entity relationship diagram from Prisma code in the VsCode editor]]></title><description><![CDATA[If you are a Prisma user, I have great news for you. This about a VsCode extension that let you visualize your Prisma code in ERD directly in your VsCode Editor. That give you more readability of your database schema.
The extension has some interesti...]]></description><link>https://juste.bocovo.me/visualize-the-entity-relationship-diagram-from-prisma-code-in-the-vscode-editor</link><guid isPermaLink="true">https://juste.bocovo.me/visualize-the-entity-relationship-diagram-from-prisma-code-in-the-vscode-editor</guid><category><![CDATA[prisma]]></category><category><![CDATA[vscode]]></category><category><![CDATA[vscode extensions]]></category><category><![CDATA[ERD (Entity-Relationship Diagrams)]]></category><dc:creator><![CDATA[Juste R. Bocovo]]></dc:creator><pubDate>Sat, 27 Jul 2024 18:47:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722103528981/44be23d8-22e2-452d-a85a-8cecd279f30b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you are a Prisma user, I have great news for you. This about a VsCode extension that let you visualize your Prisma code in ERD directly in your VsCode Editor. That give you more readability of your database schema.</p>
<p>The extension has some interesting features. First it let you use the right theme according to your theme preference, you have the light and dark mode. You can also drag your table in the diagram, to reorganize as you want. Zooming is also supported. Another interesting feature is, you can hide columns, showing all columns, only relational columns, or only the table's name ( Let's thank the contributors for adding this feature ).</p>
<p>So, stop talking and let's see how to use it.</p>
<h3 id="heading-get-started"><strong>Get started</strong></h3>
<p>Let's dive in and show how to use it.</p>
<h3 id="heading-first-install-the-extension">First install the extension</h3>
<p>From your VsCode in the extension tab, search for this <code>Prisma Entity-Relationship Diagrams visualizer</code>. Install the first item int the result. How can follow the screenshot below to identify the good item.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722104671451/44764c29-9114-4314-b73c-32ae3fd22aab.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-getting-some-prisma-code-to-preview">Getting some Prisma code to preview</h3>
<p>In your workspace, create a Prisma file ( if you already have one good, let's use it ).</p>
<blockquote>
<p>You can name your file as you want, but its extension must be <code>.prisma</code> so that the extension can be activated by VsCode.</p>
</blockquote>
<p>Here is an example of Prima code</p>
<pre><code class="lang-typescript">datasource db {
  provider = <span class="hljs-string">"sqlite"</span>
  url      = env(<span class="hljs-string">"DATABASE_URL"</span>)
}

generator client {
  provider      = <span class="hljs-string">"prisma-client-js"</span>
  binaryTargets = <span class="hljs-string">"native"</span>
}

model Post {
  id        Int      <span class="hljs-meta">@id</span> <span class="hljs-meta">@default</span>(autoincrement())
  title     <span class="hljs-built_in">String</span>
  body      <span class="hljs-built_in">String</span>
  createdAt DateTime <span class="hljs-meta">@default</span>(now())
}

model User {
  id                  Int       <span class="hljs-meta">@id</span> <span class="hljs-meta">@default</span>(autoincrement())
  firstName           <span class="hljs-built_in">String</span>
  lastName            <span class="hljs-built_in">String</span>
  verified            <span class="hljs-built_in">Boolean</span>   <span class="hljs-meta">@default</span>(<span class="hljs-literal">false</span>)
  email               <span class="hljs-built_in">String</span>    <span class="hljs-meta">@unique</span>
  hashedPassword      <span class="hljs-built_in">String</span>
  salt                <span class="hljs-built_in">String</span>
  resetToken          <span class="hljs-built_in">String</span>?
  resetTokenExpiresAt DateTime?
}
</code></pre>
<h3 id="heading-opening-the-preview">Opening the preview</h3>
<p>He got the extension, we got the file, let preview the ERD guys.</p>
<p>When you are in a file with the <code>.prisma</code> extension, you'll see a preview icon in the top right-hand corner of the editor's title bar. Click on it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722105438268/26db8039-4270-4508-a818-d823c21813ce.png" alt class="image--center mx-auto" /></p>
<p>And you got this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722105546912/af9de5a7-11d2-44e2-88be-0da8f2427072.png" alt class="image--center mx-auto" /></p>
<p>That is all, thank you for reading.</p>
<h3 id="heading-support-the-project"><strong>Support the project</strong></h3>
<ul>
<li><p>Leave a review of the extension <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=bocovo.prisma-erd-visualizer&amp;ssr=false#review-details"><strong>here</strong></a></p>
</li>
<li><p>Visit the repo here to leave a star or contribute <a target="_blank" href="https://github.com/BOCOVO/db-schema-visualizer"><strong>here</strong></a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Preview DBML code from Vscode]]></title><description><![CDATA[If you're a dbdocs or dbdiagram user, you've probably written DBML code from your editor (Vs code ). This extension enhances your experience by allowing you to view your DBML code in an ERD ( Entity Relation Diagram ) from your editor.
How does it wo...]]></description><link>https://juste.bocovo.me/preview-dbml-code-from-vscode</link><guid isPermaLink="true">https://juste.bocovo.me/preview-dbml-code-from-vscode</guid><category><![CDATA[dbml]]></category><category><![CDATA[vscode extensions]]></category><category><![CDATA[ERD (Entity-Relationship Diagrams)]]></category><dc:creator><![CDATA[Juste R. Bocovo]]></dc:creator><pubDate>Sun, 28 Apr 2024 22:58:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1714342845985/d9eedff0-53ec-4104-a1ea-eda362347143.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you're a <a target="_blank" href="https://dbdocs.io/">dbdocs</a> or <a target="_blank" href="https://dbdiagram.io/">dbdiagram</a> user, you've probably written DBML code from your editor (Vs code ). This extension enhances your experience by allowing you to view your DBML code in an ERD ( Entity Relation Diagram ) from your editor.</p>
<h3 id="heading-how-does-it-work">How does it work?</h3>
<h4 id="heading-install-the-extension">Install the extension</h4>
<p>Go to the extensions tab in your editor, search for <code>DBML Entity-Relationship Diagrams visualizer</code> and install it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714343606407/b4aebf51-ba7e-46d5-ac04-d5a091de1e0d.png" alt class="image--center mx-auto" /></p>
<h4 id="heading-write-your-dbml-code">Write your DBML code</h4>
<p>In your workspace, create a file with the <code>.dbml</code> extension and write your DBML code in it ( code example below )</p>
<pre><code class="lang-typescript">Table users {
  id integer
  username varchar
}

Table posts {
  id integer [primary key]
  title varchar
  body text [note: <span class="hljs-string">'Content of the post'</span>]
  user_id integer
}

Ref: posts.user_id &gt; users.id <span class="hljs-comment">// many-to-one</span>
</code></pre>
<h4 id="heading-preview-erd">Preview ERD</h4>
<p>When you're in a <code>.dbml</code> file, you'll see a preview icon in the top right-hand corner of the editor's title bar.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1714344322718/08899457-5cab-40b3-a63f-d0ceb47ac8a7.png" alt class="image--center mx-auto" /></p>
<p>When you click on this button, a new tab opens on the side displaying the preview.</p>
<p><img src="https://github.com/BOCOVO/db-schema-visualizer/assets/51182814/a59fd0c0-246d-4f00-be39-9885d88b8b85" alt class="image--center mx-auto" /></p>
<p>You can move tables, zoom in on the scene and even move around within it.</p>
<h3 id="heading-support-the-project">Support the project</h3>
<ul>
<li><p>Leave a review of the extension <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=bocovo.dbml-erd-visualizer&amp;ssr=false#review-details">here</a></p>
</li>
<li><p>Visit the repo here to leave a star or contribute <a target="_blank" href="https://github.com/BOCOVO/db-schema-visualizer">here</a></p>
</li>
</ul>
<p><strong>Enjoy</strong></p>
]]></content:encoded></item></channel></rss>