<?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[Frainer's Blog 📝]]></title>
        <description><![CDATA[Recent articles from Frainer's Blog. I write about tech, programming and whatever else I'm thinking about!]]></description>
        <link>https://fraineralex.dev/blog/</link>
        <image>
            <url>https://fraineralex.dev/blog/og.png</url>
            <title>Frainer&apos;s Blog 📝</title>
            <link>https://fraineralex.dev/blog/</link>
        </image>
        <generator>RSS for Node</generator>
        <lastBuildDate>Sat, 13 Jun 2026 21:50:05 GMT</lastBuildDate>
        <atom:link href="https://fraineralex.dev/blog/feed.xml" rel="self" type="application/rss+xml"/>
        <pubDate>Thu, 18 Jan 2024 00:00:00 GMT</pubDate>
        <language><![CDATA[en-US]]></language>
        <category><![CDATA[tech]]></category>
        <category><![CDATA[programming]]></category>
        <category><![CDATA[software]]></category>
        <dc:creator>Frainer Encarnación</dc:creator>
        <item>
            <title><![CDATA[Conquering React Hooks: A Comprehensive Guide]]></title>
            <description><![CDATA[
    <header>
      <figure>
        <img
          alt="undefined"
          loading="lazy"
          decoding="async"
          data-nimg="1"
          src="https://fraineralex.dev/images/blog/posts/cover/crafting-react-hooks.webp"
          style="margin-top: 2rem; color: transparent; min-width: 80%; border-radius: .75rem; margin-left: auto; margin-right: auto; width: 100%; height: auto;"
        />
        <figcaption style=" text-align: right; font-size: 0.875rem; line-height: 1.25rem; padding-inline-end: 2rem; color: darkgray; padding-inline-end: 2rem; padding-top: 0.25rem;  font-style: italic;">
          
        </figcaption>
      </figure>
      <p style=" margin-left: auto; margin-right: auto; text-transform: uppercase; text-align: center; padding-bottom: 2rem;"
        ><span style="margin-bottom: 0;">
          <time datetime="2024-01-24"
            >Jan 24, 2024</time
          >
          <span style="padding-left: 1rem; padding-right: 1rem;">•</span
          ><span style="margin-inline-end: 0;">18 min read</span>
          <span style="padding-left: 1rem; padding-right: 1rem;">|</span>
          
                  <a href="https://fraineralex.dev/tags/react" style="color: black; text-decoration-line: underline; text-underline-offset: 4px;">
                    React
                  </a>
                  <span style="padding-left: 10px; padding-right: 10px;"> • </span>
              
                  <a href="https://fraineralex.dev/tags/javascript" style="color: black; text-decoration-line: underline; text-underline-offset: 4px;">
                    JavaScript
                  </a>
                  <span style="padding-left: 10px; padding-right: 10px;"> • </span>
              
                  <a href="https://fraineralex.dev/tags/typescript" style="color: black; text-decoration-line: underline; text-underline-offset: 4px;">
                    TypeScript
                  </a>
                  
              
          </span>
      </p>  
    </header>
  <article style="text-wrap: balance;"><p>In this article, I will reveal in a clear and simplified way how React Hooks can work magic in your projects, just as I would have liked to learn when I discovered them.</p>
<h3>🪝 Hooks: The Magic of React</h3>
<p>In React, hooks are utilities that allow us to execute arbitrary code in our components based on specific actions. Hooks provide a way to reuse state and side-effect logic in functional components in a simpler and more declarative manner.</p>
<blockquote>
<p><strong>🚨 Important:</strong> This guide uses <code>TypeScript</code> code snippets to illustrate the concepts. If you are not familiar with TypeScript, feel free to ignore the typing in the examples.</p>
</blockquote>
<h2>🌱 Basic Hooks</h2>
<p>This reference guide will discuss all the Hooks natively available in React, but first, let’s start with the basic React Hooks: <code>useState</code>, <code>useEffect</code>, and <code>useContext</code>.</p>
<p><img src="https://fraineralex.dev/images/blog/posts/content/basic-hooks.webp" alt="React basic hooks image"></p>
<h2>⚡ useState</h2>
<p>It is a hook that allows functional components to manage and maintain their internal state. You can use it to declare state variables and access them in your functional components.</p>
<p><strong>The signature for the <code>useState</code> Hook is as follows:</strong></p>
<pre><code class="language-tsx">const [state, setState] = useState(initialState)
</code></pre>
<p>Here, <code>state</code> and <code>setState</code> refer to the state value and updater function returned on invoking <code>useState</code> with some <code>initialState</code>.</p>
<p>It’s important to note that when your component first renders and invokes <code>useState</code>, the <code>initialState</code> is the returned state from <code>useState</code>.</p>
<p>Also, to update state, the state updater function <code>setState</code> should be invoked with a new state value, as shown below:</p>
<pre><code class="language-tsx">setState(newValue)
</code></pre>
<p>By doing this, a new re-render of the component is queued. <code>useState</code> guarantees that the <code>state</code> value will always be the most recent after applying updates.</p>
<p><strong>Example of using <code>useState</code> in a React component about the follow card of X:</strong></p>
<pre><code class="language-tsx">export function XFollowCard({ fullName, userName, initialIsFollowing }: Props) {
  const [isFollowing, setIsFollowing] = useState(initialIsFollowing) // &lt;-- Definition

  const text = isFollowing ? &#39;Following&#39; : &#39;Follow&#39;

  const buttonClassName = isFollowing
    ? &#39;tw-followCard-button is-following&#39;
    : &#39;tw-followCard-button&#39;

  const handleClick = () =&gt; {
    setIsFollowing(!isFollowing) // Changing the state
  }

  return (
    &lt;article className=&#39;tw-followCard&#39;&gt;
      &lt;header className=&#39;tw-followCard-header&#39;&gt;
        &lt;img
          className=&#39;tw-followCard-avatar&#39;
          alt=&#39;user avatar&#39;
          src={`https://unavatar.io/${userName}`}
        /&gt;
        &lt;div className=&#39;tw-followCard-info&#39;&gt;
          &lt;strong&gt;{fullName}&lt;/strong&gt;
          &lt;span className=&#39;tw-followCard-infoUserName&#39;&gt;@{userName}&lt;/span&gt;
        &lt;/div&gt;
      &lt;/header&gt;

      &lt;aside&gt;
        &lt;button className={buttonClassName} onClick={handleClick}&gt;
          &lt;span className=&#39;tw-followCard-text&#39;&gt;{text}&lt;/span&gt;
          &lt;span className=&#39;tw-followCard-stopFollow&#39;&gt;Unfollow&lt;/span&gt;
        &lt;/button&gt;
      &lt;/aside&gt;
    &lt;/article&gt;
  )
}
</code></pre>
<h2>🎬 useEffect</h2>
<p>It is a React hook that allows performing side effects in functional components. You can use it to execute code in response to changes in the component, such as making API requests, subscribing to events, or updating the DOM. <code>useEffect</code> receives a function as an argument and executes it after the component is rendered or when certain dependencies change.</p>
<p>The basic signature of <code>useEffect</code> is as follows:</p>
<pre><code class="language-tsx">useEffect(() =&gt; {
  //...
})
</code></pre>
<p><strong>Example of using <code>useEffect</code> in a React component:</strong></p>
<pre><code class="language-tsx">const CAT_PREFIX_IMAGE_URL = &#39;https://cataas.com&#39;

export function useCatImage({ fact }: { fact: string }) {
  const [imageUrl, setImageUrl] = useState()

  useEffect(() =&gt; {
    if (!fact) return

    const threeFirstWords = fact.split(&#39; &#39;, 3).join(&#39; &#39;)

    fetch(
      `https://cataas.com/cat/says/${threeFirstWords}?size=50&amp;color=red&amp;json=true`
    )
      .then((res) =&gt; res.json())
      .then((response) =&gt; {
        const { url } = response
        setImageUrl(url)
      })
  }, [fact])

  return { imageUrl: `${CAT_PREFIX_IMAGE_URL}${imageUrl}` }
}
</code></pre>
<h3>🧹 Cleaning up an effect</h3>
<p>Some imperative code need to be cleaned up e.g. to prevent memory leaks. For example, subscriptions need to be cleaned up, timers need to be invalidated etc. To do this return a function from the callback passed to <code>useEffect</code>:</p>
<pre><code class="language-tsx">useEffect(() =&gt; {
  const subscription = props.apiSubscripton()

  return () =&gt; {
    // clean up the subscription
    subscription.unsubscribeApi()
  }
})
</code></pre>
<p>The clean-up function is guaranteed to be invoked before the component is removed from the user interface.</p>
<h3>⚠️ Avoid Infinite Loops</h3>
<p>When using <code>useEffect</code> in React, it&#39;s crucial to avoid infinite loops that can arise from incorrect effect configurations. One common mistake is modifying the state within the effect body in a way that triggers infinite renderings.</p>
<blockquote>
<p><strong>Common Cause of Infinite Loops:</strong> Directly Modifying State</p>
</blockquote>
<pre><code class="language-tsx">useEffect(() =&gt; {
  // Incorrect: Modifying state within the effect body
  setCount(count + 1)
}, [count])
</code></pre>
<p>This example causes an infinite loop by updating the state within the effect, triggering new renderings and re-executing the effect.</p>
<h3>✅ Solution</h3>
<pre><code class="language-tsx">useEffect(() =&gt; {
  // Correct: Use the setCount callback to update the state based on the previous state.
  // This ensures that the state update doesn&#39;t cause an infinite loop.
  setCount(prevCount =&gt; prevCount + 1)
}, [count])
</code></pre>
<p>Avoid infinite loops by ensuring that the dependencies in the <code>useEffect</code> dependency array are stable and do not change within the effect body. In this case, by using the <code>setCount</code> callback to update the state based on the previous state, we prevent the infinite loop.</p>
<h2>🤝 useContext</h2>
<p>The problem that <code>useContext</code> solves lies in the need to pass data through the component hierarchy without resorting to prop drilling, which is when props are manually passed through multiple levels of components. This approach can become cumbersome and impractical as the application grows, as each intermediate component has to relay the props, generating less clean and error-prone code.</p>
<h3>❌ Prop Drilling: The Challenge</h3>
<p>Imagine a scenario where we have a <code>ComponentA</code> that needs to pass data to <code>ComponentD</code>. Traditional prop drilling would involve passing the props through all intermediate components, even if <code>ComponentB</code> and <code>ComponentC</code> do not need that data.</p>
<pre><code class="language-tsx">// ComponentA.tsx
const ComponentA = ({ dataForD }: Props) =&gt; {
  return &lt;ComponentB dataForD={dataForD} /&gt;
}

// ComponentB.tsx
const ComponentB = ({ dataForD }: Props) =&gt; {
  return &lt;ComponentC dataForD={dataForD} /&gt;
}

// ComponentC.tsx
const ComponentC = ({ dataForD }: Props) =&gt; {
  return &lt;ComponentD dataForD={dataForD} /&gt;
}

// ComponentD.tsx
const ComponentD = ({ dataForD }: Props) =&gt; {
  // Use dataForD here
}
</code></pre>
<p>This process, known as prop drilling, can become unmanageable and complicated as more components are added to the hierarchy.</p>
<h3>✅ Solution: <code>useContext</code> to the Rescue</h3>
<p><code>useContext</code> greatly simplifies this task by allowing us to create and consume a context without manually passing props through each component. First, we create a context using <code>createContext</code>:</p>
<pre><code class="language-tsx">// ThemeContext.ts
import { createContext } from &#39;react&#39;
export const ThemeContext = createContext()
</code></pre>
<p>Then, we use the <code>Provider</code> component to wrap our component tree with the desired value:</p>
<pre><code class="language-tsx">// App.tsx
import React from &#39;react&#39;
import { ThemeContext } from &#39;./ThemeContext&#39;

const App = () =&gt; {
  return (
    &lt;ThemeContext.Provider value=&#39;dark&#39;&gt;
      {/* Nested components here */}
    &lt;/ThemeContext.Provider&gt;
  )
}
</code></pre>
<p>Finally, in any component within this context, we can use <code>useContext</code> to access the data without manually passing props:</p>
<pre><code class="language-tsx">// Button.tsx
import React, { useContext } from &#39;react&#39;
import { ThemeContext } from &#39;./ThemeContext&#39;

export const Button = () =&gt; {
  const theme = useContext(ThemeContext)
  return &lt;button className={theme}&gt;Click here&lt;/button&gt;
}
</code></pre>
<blockquote>
<p>Note that the value passed to useContext must be the context object, i.e., the return value from invoking React.createContext, not ContextObject.Provider or ContextObject.Consumer.</p>
</blockquote>
<p>This solution avoids the cumbersome prop drilling and provides a cleaner and more efficient way to share data across components in a React application. <code>useContext</code> makes data management more elegant and easy to maintain.</p>
<p>Goodbye, prop drilling! 👋</p>
<h2>🌟 Additional Hooks</h2>
<p>The following hooks are variants of the basic hooks discussed in the sections above. If you’re new to hooks don’t bother learning these right now. They are only needed for specific edge cases.</p>
<p><img src="https://fraineralex.dev/images/blog/posts/content/additional-hooks.webp" alt="React additional hooks image"></p>
<h2>📌 useRef</h2>
<p><code>useRef</code> in React is a hook that makes it easy to create mutable references. Unlike <code>useState</code>, <code>useRef</code> doesn&#39;t trigger component re-renders when its value changes, making it a powerful tool for holding data that doesn&#39;t directly affect the user interface.</p>
<p>Here’s how the <code>useRef</code> hook is used:</p>
<pre><code class="language-tsx">import { useRef } from &#39;react&#39;

const MyComponent = () =&gt; {
  const myRef = useRef(initialValue)
  // ...
}
</code></pre>
<h3>🥷🏻 Challenge</h3>
<p>The problem that <code>useRef</code> solves becomes apparent when we need to update values without triggering a visual representation update of the component. To illustrate this, let&#39;s consider a movie search scenario:</p>
<pre><code class="language-tsx">export function useMovies({ search }: { search: string }) {
  const [movies, setMovies] = useState([])
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState(null)

  const getMovies = async () =&gt; {
    // ❌ This is a bad practice because we are fetching
    // the movies and re-rendering the component again
    // even if the search is the same as the previous one.

    try {
      setLoading(true)
      setError(null)
      const newMovies = await searchMovies({ search })
      setMovies(newMovies)
    } catch (error: any) {
      setError(error.message)
    } finally {
      setLoading(false)
    }
  }

  return { movies, getMovies, loading, error }
}
</code></pre>
<p>In this case, using <code>useState</code> for the search term causes unnecessary renderings every time the search term changes. This is where <code>useRef</code> becomes an efficient solution by allowing us to update <code>search</code> without affecting the user interface:</p>
<pre><code class="language-tsx">export function useMovies({ search }: { search: string }) {
  const [movies, setMovies] = useState([])
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState(null)
  const previousSearch = useRef(search) // &lt;-- Define a ref

  const getMovies = async () =&gt; {
    // ✅ If the current search is the same to before search: return
    if (previousSearch.current === search) return

    try {
      setLoading(true)
      setError(null)
      previousSearch.current = search
      const newMovies = await searchMovies({ search })
      setMovies(newMovies)
    } catch (error: any) {
      setError(error.message)
    } finally {
      setLoading(false)
    }
  }

  return { movies, getMovies, loading, error }
}
</code></pre>
<p>With this implementation, <code>useRef</code> helps manage the value of <code>search</code> without causing unwanted visual updates, improving efficiency and the user experience.</p>
<h2>🧠 useMemo</h2>
<p>The <code>useMemo</code> hook in React is a powerful tool for optimizing performance by memorizing the result of a function. Its main purpose is to prevent unnecessary computations, reusing the previously calculated value if the dependencies haven&#39;t changed.</p>
<p>Here’s how the <code>useMemo</code> hook is used:</p>
<pre><code class="language-tsx">const readTime = useMemo(() =&gt; {
  const wordsPerMinute = 200
  const words = text.trim().split(/\s+/).length
  const value = Math.ceil(words / wordsPerMinute)
  return `${value} min read`
}, [text]) // only recompute if text changes
</code></pre>
<p>The problem that <code>useMemo</code> addresses becomes apparent when we need to perform expensive calculations in a component, but those calculations are not necessary every time the component renders. Let&#39;s take the example of the <code>Counter</code> component:</p>
<pre><code class="language-tsx">export function Counter({ count }: { count: number }) {
  const double = count * 2 // Costly calculation performed on every render

  return (
    &lt;div&gt;
      &lt;p&gt;Contador: {count}&lt;/p&gt;
      &lt;p&gt;Doble: {double}&lt;/p&gt;
    &lt;/div&gt;
  )
}
</code></pre>
<p>In this case, the double value is recalculated on every render, even if <code>count</code> hasn&#39;t changed. <code>useMemo</code> solves this by memorizing the result of the calculation only when the dependencies, in this case, the <code>count</code> prop, have changed:</p>
<pre><code class="language-tsx">import { useMemo } from &#39;react&#39;

export function Counter({ count }: { count: number }) {
  const double = useMemo(() =&gt; count * 2, [count])

  return (
    &lt;div&gt;
      &lt;p&gt;Contador: {count}&lt;/p&gt;
      &lt;p&gt;Doble: {double}&lt;/p&gt;
    &lt;/div&gt;
  )
}
</code></pre>
<p>With <code>useMemo</code>, if the <code>count</code> prop hasn&#39;t changed, the recalculation of double is avoided, and the previously calculated value is reused. This significantly improves the efficiency of the component, especially in situations where calculations are more resource-intensive.</p>
<h2>♻️ useCallback</h2>
<p>The <code>useCallback</code> hook in React provides a way to memorize functions. The main advantage is to avoid creating new functions on each render, returning the previously memorized function if the dependencies haven&#39;t changed.</p>
<p>Here’s how the <code>useCallback</code> hook is used:</p>
<pre><code class="language-tsx">const memoizedCallback = useCallback(callback, arrayDependency)
</code></pre>
<p>The problem that <code>useCallback</code> addresses becomes apparent when we need to pass functions to child components and want to avoid creating new instances of those functions on each render. Let&#39;s take the example of the <code>Counter</code> component:</p>
<pre><code class="language-tsx">function Counter({ count, onIncrement }: Props) {
  const handleIncrement = () =&gt; {
    onIncrement(count)
  }

  return (
    &lt;div&gt;
      &lt;p&gt;Contador: {count}&lt;/p&gt;
      &lt;button onClick={handleIncrement}&gt;Incrementar&lt;/button&gt;
    &lt;/div&gt;
  )
}
</code></pre>
<p>In this case, <code>handleIncrement</code> is recreated on every render, which is not efficient, especially if <code>onIncrement</code> and <code>count</code> haven&#39;t changed. <code>useCallback</code> addresses this by memorizing the function only when the dependencies change:</p>
<pre><code class="language-tsx">import { useCallback } from &#39;react&#39;

export function Counter({ count, onIncrement }: Props) {
  const handleIncrement = useCallback(() =&gt; {
    onIncrement(count)
  }, [count, onIncrement]) // only re-create if count or onIncrement change

  return (
    &lt;div&gt;
      &lt;p&gt;Contador: {count}&lt;/p&gt;
      &lt;button onClick={handleIncrement}&gt;Incrementar&lt;/button&gt;
    &lt;/div&gt;
  )
}
</code></pre>
<p>With <code>useCallback</code>, if <code>count</code> or <code>onIncrement</code> haven&#39;t changed, creating a new function is avoided, and the previously calculated function is reused. This improves efficiency and contributes to a more optimal component performance.</p>
<h2>🏷️ useId</h2>
<p><code>useId</code> is a React hook designed to generate unique identifiers, ideal for assigning them to HTML tag attributes. This practice becomes especially useful for improving accessibility by establishing specific relationships between elements.</p>
<p>Here’s how the <code>useId</code> hook is used:</p>
<pre><code class="language-tsx">const passwordHintId = useId()
</code></pre>
<p>Next, the generated ID is used in different attributes:</p>
<pre><code class="language-tsx">&lt;&gt;
  &lt;input type=&#39;password&#39; aria-describedby={passwordHintId} /&gt;
  &lt;p id={passwordHintId}&gt;
&lt;/&gt;
</code></pre>
<p>The problem that <code>useId</code> addresses arises when we need to assign unique identifiers to HTML elements, especially in situations where a component may appear multiple times on the screen. Let&#39;s take the example of the <code>PasswordField</code> component:</p>
<pre><code class="language-tsx">import { useId } from &#39;react&#39;

export function PasswordField() {
  const passwordHintId = useId()

  return (
    &lt;&gt;
      &lt;label&gt;
        Password:
        &lt;input type=&#39;password&#39; aria-describedby={passwordHintId} /&gt;
      &lt;/label&gt;
      &lt;p id={passwordHintId}&gt;
        The password must be 18 characters long and contain special characters.
      &lt;/p&gt;
    &lt;/&gt;
  )
}
</code></pre>
<p>In this case, <code>useId</code> is used to generate a unique ID (<code>passwordHintId</code>) that is assigned to both the <code>aria-describedby</code> attribute of the input and the <code>id</code> of the paragraph. This ensures that even if <code>PasswordField</code> appears multiple times on the screen, the generated IDs will not conflict.</p>
<pre><code class="language-tsx">export default function App() {
  return (
    &lt;&gt;
      &lt;h2&gt;Choose password&lt;/h2&gt;
      &lt;PasswordField /&gt;
      &lt;h2&gt;Confirm password&lt;/h2&gt;
      &lt;PasswordField /&gt;
    &lt;/&gt;
  )
}
</code></pre>
<p>In the <code>App</code> component, where <code>PasswordField</code> is used twice, <code>useId</code> ensures that automatically generated identifiers avoid duplicates and provide a robust solution for assigning unique IDs in repeated contexts. This contributes to improving accessibility and consistency in the application.</p>
<h2>🕹️ useReducer</h2>
<p><code>useReducer</code> is a React hook designed to manage the state of a component using an action-based and reduction-oriented approach, similar to the pattern used in Redux. This hook becomes preferable over <code>useState</code> when the state of a component is more complex or when state updates depend on the previous state or previous actions.</p>
<p><code>useReducer</code> takes two arguments: a reducing function and the initial state. The reducing function receives two arguments: the current state and an action that describes how the state should change. The reducing function returns the new state.</p>
<p><strong>Here’s how the <code>useReducer</code> hook is used:</strong></p>
<pre><code class="language-tsx">const [state, dispatch] = useReducer(reducer, initialArgument, init)
</code></pre>
<p>The problem that <code>useReducer</code> addresses arises when the state of a component becomes more complex, and state updates depend on multiple factors or actions. Let&#39;s take the example of the <code>Counter</code> component:</p>
<pre><code class="language-tsx">import { useState } from &#39;react&#39;

export const Counter = () =&gt; {
  const [count, setCount] = useState(0)

  const handleIncrement = () =&gt; {
    setCount(count + 1)
  }

  const handleDecrement = () =&gt; {
    setCount(count - 1)
  }

  return (
    &lt;div&gt;
      &lt;p&gt;Count: {count}&lt;/p&gt;
      &lt;button onClick={handleIncrement}&gt;Increment&lt;/button&gt;
      &lt;button onClick={handleDecrement}&gt;Decrement&lt;/button&gt;
    &lt;/div&gt;
  )
}
</code></pre>
<p>In this example, we use <code>useState</code> to manage the state of the counter. While this can work for simple cases, as the logic of the state becomes more complex or depends on previous actions, the code can become harder to maintain. <code>useReducer</code> provides a more organized structure and a more scalable solution for handling complex states and actions in situations where the code could become confusing using only <code>useState</code>. We would approach this problem with useReducer as follows:</p>
<pre><code class="language-tsx">// Define the reducing function
const counterReducer = (state: State, action: Action) =&gt; {
  switch (action.type) {
    case &#39;increment&#39;:
      return { count: state.count + 1 }
    case &#39;decrement&#39;:
      return { count: state.count - 1 }
    default:
      return state
  }
}

export const Counter = () =&gt; {
  // Use useReducer to manage the state of the counter
  const [state, dispatch] = useReducer(counterReducer, { count: 0 })

  return (
    &lt;div&gt;
      &lt;p&gt;Count: {state.count}&lt;/p&gt;
      &lt;button onClick={() =&gt; dispatch({ type: &#39;increment&#39; })}&gt;Increment&lt;/button&gt;
      &lt;button onClick={() =&gt; dispatch({ type: &#39;decrement&#39; })}&gt;Decrement&lt;/button&gt;
    &lt;/div&gt;
  )
}
</code></pre>
<h2>✨ useImperativeHandle</h2>
<p><code>useImperativeHandle</code> in React is a handy tool when you need to control and customize the external interface of a functional component, especially when working with refs. Imagine the challenge you would face without this hook.</p>
<h3>🤔 Challenge Without <code>useImperativeHandle</code>:</h3>
<p>Let&#39;s assume we have a functional component called <code>FancyInput</code> that encapsulates a text input. We want the parent component to access and manipulate the input value directly and also trigger focus on that input. Without <code>useImperativeHandle</code>, we might end up with less efficient and error-prone code.</p>
<pre><code class="language-tsx">export const FancyInput = () =&gt; {
  const inputRef = useRef&lt;HTMLInputElement&gt;(null)

  const focusInput = () =&gt; {
    if (inputRef.current) {
      inputRef.current.focus()
    }
  }

  return (
    &lt;div&gt;
      &lt;input ref={inputRef} /&gt;
      {/* Challenge: How to expose the `focusInput` method to the parent component? */}
    &lt;/div&gt;
  )
}
</code></pre>
<p>In this scenario, exposing the <code>focusInput</code> method to the parent component would be a challenging and inelegant task. This is where <code>useImperativeHandle</code> comes into play.</p>
<h3>✅ Solution with <code>useImperativeHandle</code>:</h3>
<pre><code class="language-tsx">export const FancyInput = forwardRef((props, ref) =&gt; {
  const inputRef = useRef&lt;HTMLInputElement&gt;(null)

  // Use useImperativeHandle to customize the external interface
  useImperativeHandle(ref, () =&gt; ({
    focus: () =&gt; {
      if (inputRef.current) {
        inputRef.current.focus()
      }
    },
    getValue: () =&gt; {
      return inputRef.current ? inputRef.current.value : &#39;&#39;
    },
  }))

  return (
    &lt;div&gt;
      &lt;input ref={inputRef} /&gt;
    &lt;/div&gt;
  )
})
</code></pre>
<p>With <code>useImperativeHandle</code>, we can now selectively expose the functions we want the parent component to use. This solution improves code clarity and provides a more efficient and controlled external interface.</p>
<h2>🧩 useLayoutEffect</h2>
<p><code>useLayoutEffect</code> in React is a powerful hook that allows you to perform synchronous operations after all mutations to the DOM have been completed but before the browser repaints the screen. Imagine the challenge you would face without this hook.</p>
<h3>🤔 Challenge Without <code>useLayoutEffect</code>:</h3>
<p>Imagine a scenario where we want to measure the dimensions of a DOM element and, based on those dimensions, perform certain actions in our functional component <code>ResizableBox</code>. Without <code>useLayoutEffect</code>, we could face issues when making these measurements asynchronously.</p>
<pre><code class="language-tsx">export const ResizableBox = () =&gt; {
  const boxRef = useRef&lt;HTMLDivElement&gt;(null)
  const [boxWidth, setBoxWidth] = useState(0)

  useEffect(() =&gt; {
    // Challenge: How to measure the dimensions of boxRef synchronously?
    // Measurements may not be available immediately.
    // This can cause issues if we depend on dimensions to perform actions.
  }, [])

  return &lt;div ref={boxRef}&gt;{/* Resizable box content */}&lt;/div&gt;
}
</code></pre>
<p>In this scenario, performing synchronous measurements of the dimensions of <code>boxRef</code> is challenging with <code>useEffect</code> because the measurements may not be available immediately. This is where <code>useLayoutEffect</code> comes into play.</p>
<h3>✅ Solution with <code>useLayoutEffect</code>:</h3>
<pre><code class="language-tsx">export const ResizableBox = () =&gt; {
  const boxRef = useRef&lt;HTMLDivElement&gt;(null)
  const [boxWidth, setBoxWidth] = useState(0)

  useLayoutEffect(() =&gt; {
    // Use useLayoutEffect to measure the dimensions of boxRef synchronously
    if (boxRef.current) {
      setBoxWidth(boxRef.current.offsetWidth)
    }
  }, [])

  return &lt;div ref={boxRef}&gt;{/* Resizable box content */}&lt;/div&gt;
}
</code></pre>
<p>With <code>useLayoutEffect</code>, we can perform synchronous measurements after the browser has completed all mutations to the DOM but before repainting the screen. This ensures that measurements are available immediately and avoids potential issues related to asynchrony.</p>
<h2>🐞 useDebugValue</h2>
<p><code>useDebugValue</code> in React is a specialized hook designed to enhance the debugging experience by providing additional information about the state of a component. Its main utility is to facilitate component identification in browser development tools.</p>
<p>The basic signature for <code>useDebugValue</code> is as follows:</p>
<pre><code class="language-tsx">useDebugValue(value)
</code></pre>
<p>When debugging a React application, it&#39;s common to face the challenge of quickly identifying the component you&#39;re interested in within the browser development tools. Without <code>useDebugValue</code>, information about a component can be limited and nonspecific.</p>
<p><strong>Here’s how the <code>useDebugValue</code> hook is used:</strong></p>
<h3>1. Adding a Descriptive Name:</h3>
<pre><code class="language-tsx">import { useDebugValue } from &#39;react&#39;

const useCustomHook = () =&gt; {
  const state =
    /* hook logic */

    // Provide a descriptive name for easy identification in development tools
    useDebugValue(&#39;Custom Hook&#39;)

  return state
}
</code></pre>
<h3>2. Displaying Array Content:</h3>
<pre><code class="language-tsx">import { useDebugValue } from &#39;react&#39;

const useArrayHook = (array: string[]) =&gt; {
  // hook logic

  // Show the content of the array in development tools
  useDebugValue(array.join(&#39;, &#39;))

  return /* result */
}
</code></pre>
<h3>3. Using State Information:</h3>
<pre><code class="language-tsx">import { useState, useDebugValue } from &#39;react&#39;

const useCounter = () =&gt; {
  const [count, setCount] = useState(0)

  // Use the counter value as information in development tools
  useDebugValue(`Counter: ${count}`)

  return [count, setCount]
}
</code></pre>
<p>By using <code>useDebugValue</code>, you can customize the information displayed about your hook or component in development tools, making it easier to identify and debug during development.</p>
<h2>🚀 Conclusion</h2>
<p>In this exploration of React Hooks, from the most basic concepts to the most advanced, I trust you have discovered the fascinating world that these hooks offer to simplify and empower your developments in React. Happy coding! ✨</p>
<h3>🔗 References</h3>
<ul>
<li><a href="https://react.dev/reference/react" target="_blank" rel="noopener noreferrer">https://react.dev/reference/react</a></li>
<li><a href="https://youtube.com/playlist?list=PLUofhDIg_38q4D0xNWp7FEHOTcZhjWJ29&si=38k-uyCK8hlf7DIk" target="_blank" rel="noopener noreferrer">https://www.youtube.com/@midulive</a></li>
</ul>
<h3>🌐 Additional Resources</h3>
<ul>
<li><a href="https://blog.logrocket.com/react-hooks-cheat-sheet-solutions-common-problems/" target="_blank" rel="noopener noreferrer">React Hooks Documentation: An Easy to Read Version</a></li>
</ul>
</article>]]></description>
            <link>https://fraineralex.dev/blog/crafting-react-hooks</link>
            <guid isPermaLink="false">https://fraineralex.dev/blog/crafting-react-hooks</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[typescript]]></category>
            <dc:creator><![CDATA[Frainer Encarnación]]></dc:creator>
            <pubDate>Wed, 24 Jan 2024 00:00:00 GMT</pubDate>
            <enclosure url="https://fraineralex.dev/blog/images/blog/posts/cover/rss/crafting-react-hooks.png" length="0" type="png"/>
        </item>
        <item>
            <title><![CDATA[Mastering Git Commit Messages]]></title>
            <description><![CDATA[
    <header>
      <figure>
        <img
          alt="undefined"
          loading="lazy"
          decoding="async"
          data-nimg="1"
          src="https://fraineralex.dev/images/blog/posts/cover/master-git-commit-message.webp"
          style="margin-top: 2rem; color: transparent; min-width: 80%; border-radius: .75rem; margin-left: auto; margin-right: auto; width: 100%; height: auto;"
        />
        <figcaption style=" text-align: right; font-size: 0.875rem; line-height: 1.25rem; padding-inline-end: 2rem; color: darkgray; padding-inline-end: 2rem; padding-top: 0.25rem;  font-style: italic;">
          Source: Roman Synkevych on Unsplash
        </figcaption>
      </figure>
      <p style=" margin-left: auto; margin-right: auto; text-transform: uppercase; text-align: center; padding-bottom: 2rem;"
        ><span style="margin-bottom: 0;">
          <time datetime="2024-01-20"
            >Jan 20, 2024</time
          >
          <span style="padding-left: 1rem; padding-right: 1rem;">•</span
          ><span style="margin-inline-end: 0;">7 min read</span>
          <span style="padding-left: 1rem; padding-right: 1rem;">|</span>
          
                  <a href="https://fraineralex.dev/tags/git" style="color: black; text-decoration-line: underline; text-underline-offset: 4px;">
                    Git
                  </a>
                  <span style="padding-left: 10px; padding-right: 10px;"> • </span>
              
                  <a href="https://fraineralex.dev/tags/terminal" style="color: black; text-decoration-line: underline; text-underline-offset: 4px;">
                    Terminal
                  </a>
                  
              
          </span>
      </p>  
    </header>
  <article style="text-wrap: balance;"><p>In this post, I&#39;ll show you how to improve your Git commit messages using industry best practices, aiming to ensure a clear and easily readable Git history for your projects.</p>
<h2>🧠 Understanding Git Commits</h2>
<p>A <code>commit</code> in Git captures a set of changes stored in a project&#39;s history, representing a logical unit of work. Commits are pivotal for version control, fostering effective collaboration among developers, organizing update records, and enabling easy rollback to previous versions.</p>
<h3>Commit Structure</h3>
<p><strong>Basic:</strong> <code>git commit -m &lt;message&gt;</code></p>
<p><strong>Detailed:</strong> <code>git commit -m &lt;title&gt; -m &lt;description&gt;</code></p>
<pre><code class="language-bash">$ git add .
$ git commit -m &quot;Implement user sign-in feature&quot;
</code></pre>
<blockquote>
<p><strong>🚨 Important:</strong> This article assumes you already understand basic Git workflow. If not, I suggest reading through the <a href="https://guides.github.com/introduction/git-handbook/" target="_blank" rel="noopener noreferrer">Git Handbook</a>.</p>
</blockquote>
<h2>🌟 <strong>The Importance of Well-Crafted Commit Messages</strong></h2>
<p>Commits are not just snapshots of code changes; they serve as a roadmap for your project&#39;s history. A poorly written commit message can lead to confusion, making it challenging to understand the context of changes. Let&#39;s explore why crafting meaningful commit messages matters.</p>
<p><strong>Take a look to a wrong commit messages example</strong></p>
<p><img src="https://fraineralex.dev/images/blog/posts/content/git-commit.webp" alt="Example of wrong commit messages"><br><em>Source: <a href="http://xkcd.com/" target="_blank" rel="noopener noreferrer">xkcd.com</a></em></p>
<p>Think of your commit messages as letters to your future self or collaborators. By investing time in writing informative messages, you create a documentation trail that can save hours of troubleshooting and enhance project maintenance, especially in large-scale projects.</p>
<h2>🤔 <strong>Why Commit Message Quality Matters</strong></h2>
<p>I challenge you to review old commit messages in your projects using <code>git log</code>. You may encounter unclear messages that provide little insight into the changes made. Without proper documentation, you might find yourself pondering over the purpose of certain code lines.</p>
<p>By adhering to good commit practices, you future-proof your work. Clear messages become a valuable asset during collaborative efforts, fostering better communication within engineering teams.</p>
<h2>🎬 <strong>6 Rules for Crafting Exceptional Commit Messages</strong></h2>
<p>There are 6 simple rules that will help maintain consistency, clarity, and effectiveness in your commit messages, improving communication within the development team and facilitating code history tracking. These rules are:</p>
<h3>1. Use Imperative Mood in the Subject Line</h3>
<p>When crafting a commit message, use the imperative mood in the subject line to convey the action taken. For example, instead of saying &quot;Added feature,&quot; use &quot;Add feature&quot; or &quot;Fix bug&quot; rather than &quot;Fixed bug.&quot; This provides a clear instruction on the intended state change.</p>
<p>To come up with thoughtful commits, consider the following:</p>
<ul>
<li>Why have I made these changes?</li>
<li>What effect have my changes made?</li>
<li>Why was the change needed?</li>
<li>What are the changes in reference to?</li>
</ul>
<p>The answer will be something like:</p>
<pre><code class="language-bash">- Add the new login page
- Fix a problem with the feed of the blog
- Change the main font family to Inter
- Remove a random article
</code></pre>
<h3>2. Avoid Periods and Ellipses in Commit Messages</h3>
<p>Refrain from using unnecessary punctuation in commit messages. The first line of a commit serves as the title and should not end with a period. Additionally, ellipses should be avoided for clear and concise instructions.</p>
<pre><code class="language-bash">git commit -m &quot;Add the new login page.&quot; # ❌
git commit -m &quot;Add the new login page...&quot; # ❌
git commit -m &quot;Add the new login page&quot; # ✅
</code></pre>
<h3>3. Keep the Subject Line Under 50 Characters</h3>
<p>Be brief and to the point. If your commit message is too lengthy, consider breaking it down into multiple commits. Ensure that the subject line accurately reflects the changes made.</p>
<pre><code class="language-bash">git commit -m &quot;Add the article &#39;How to install Bun on Windows&#39; and update the blog&#39;s description in the home page&quot; # ❌
git commit -m &quot;Add the article &#39;How to install Bun on Windows&#39;&quot; # ✅
git commit -m &quot;Update the blog&#39;s description in the home page&quot; # ✅
</code></pre>
<h3>4. Provide Necessary Context in the Commit Body</h3>
<p>When additional context is required, use the commit body instead of overcrowding the subject line. This can be achieved by using <code>git commit</code> without the <code>-m</code> flag.</p>
<pre><code class="language-bash"># Example
git commit fix: prevent racing of requests

Introduce a request id and a reference to latest request. Dismiss
incoming responses other than from latest request.

Remove timeouts which were used to mitigate the racing issue but are
obsolete now.
</code></pre>
<p>Remember that the first commit message line serves as the title, while subsequent lines form the body and should adhere to standard punctuation rules.</p>
<h3>5. Use Prefixes for Semantic Commits</h3>
<p>As your project grows, maintaining a readable history becomes crucial. To achieve this, you can add a prefix to give more meaning to the commits you make. This is called semantic commits and is done as follows:</p>
<pre><code class="language-bash">&lt;type&gt;[optional scope]: &lt;description&gt;

[optional body]

[optional footer(s)]

# Example:
fix: resolve login authentication bug
^-^  ^------------------------------^
│     │
│     └--&gt; # Description of the changes
│
└──------&gt; # Type of change

[optional body]
- Improved authentication logic to handle edge cases.
- Updated relevant unit tests.

[optional footer(s)]
Reviewed-by: X
Refs: #123
</code></pre>
<p>In <code>monorepositories</code> with multiple packages, you can also add information about the package affected by the commit. This is known as scope and would look like this:</p>
<pre><code class="language-bash">feat(backend): add a new table for the likes
fix(web): update the main font family to Inter
</code></pre>
<p>The commit type can include the following:</p>
<ul>
<li><code>feat</code> – a new feature is introduced with the changes</li>
<li><code>fix</code> – a bug fix has occurred</li>
<li><code>chore</code> – changes that do not relate to a fix or feature and don&#39;t modify src or test files (for example updating dependencies)</li>
<li><code>refactor</code> – refactored code that neither fixes a bug nor adds a feature</li>
<li><code>docs</code> – updates to documentation such as a the README or other markdown files</li>
<li><code>style</code> – changes that do not affect the meaning of the code, likely related to code formatting such as white-space, missing semi-colons, and so on.</li>
<li><code>test</code> – including new or correcting previous tests</li>
<li><code>perf</code> – performance improvements</li>
<li><code>ci</code> – continuous integration related</li>
<li><code>build</code> – changes that affect the build system or external dependencies</li>
<li><code>revert</code> – reverts a previous commit</li>
</ul>
<p>The commit type subject line should be all lowercase with a character limit to encourage succinct descriptions.</p>
<p>The optional commit body should be used to provide further detail that cannot fit within the character limitations of the subject line description.</p>
<p>It is also a good location to utilize <code>BREAKING CHANGE: &lt;description&gt;</code> to note the reason for a breaking change within the commit.</p>
<h3>6. Consider Using Commit Utilities</h3>
<p>Enhance your commit workflow by incorporating tools like <code>husky</code> for executing scripts before specific Git actions and <code>commitlint</code> to ensure commits follow a chosen convention. These utilities contribute to a more streamlined and standardized commit process.</p>
<pre><code class="language-bash">npm install husky -D
npx husky install
npm set-script prepare &quot;husky install&quot;
npm run prepare
npx husky add .husky/pre-push &quot;npm test&quot;
git add .husky/pre-push

git commit -m &quot;Keep calm and commit&quot;
git push -u origin master *# tests run before the push
</code></pre>
<p>With <code>commitlint</code>, you can enforce semantic, readable commits that adhere to predefined conventions.</p>
<pre><code class="language-bash"># 1. Install commitlint cli and conventional config

# For Mac and Linux:
npm install --save-dev @commitlint/{config-conventional,cli}
# For Windows:
npm install --save-dev @commitlint/config-conventional @commitlint/cli

# 2. Add hoook to check out the commit message
npx husky add .husky/commit-msg &#39;npx --no-install commitlint --edit &quot;$1&quot;&#39;
</code></pre>
<p>These tools, combined with practices like <code>conventional-changelog</code> and <code>commitizen</code>, contribute to an efficient and standardized commit workflow, ultimately improving project maintainability and collaboration.</p>
<p>By incorporating these rules and tools into your Git workflow, you&#39;ll contribute to a more readable and organized project history, making it easier for you and your collaborators to navigate and understand the changes made over time. Happy committing! 🚀</p>
<h2>🌐 Additional Resources</h2>
<ul>
<li><a href="https://www.conventionalcommits.org" target="_blank" rel="noopener noreferrer">Conventional Commits</a></li>
<li><a href="https://semver.org" target="_blank" rel="noopener noreferrer">Semantic Versioning</a></li>
<li><a href="https://www.freecodecamp.org/news/how-to-write-better-git-commit-messages" target="_blank" rel="noopener noreferrer">freeCodeCamp.org</a></li>
</ul>
</article>]]></description>
            <link>https://fraineralex.dev/blog/mastering-git-commit-messages</link>
            <guid isPermaLink="false">https://fraineralex.dev/blog/mastering-git-commit-messages</guid>
            <category><![CDATA[git]]></category>
            <category><![CDATA[terminal]]></category>
            <dc:creator><![CDATA[Frainer Encarnación]]></dc:creator>
            <pubDate>Sat, 20 Jan 2024 00:00:00 GMT</pubDate>
            <enclosure url="https://fraineralex.dev/blog/images/blog/posts/cover/rss/master-git-commit-message.png" length="0" type="png"/>
        </item>
        <item>
            <title><![CDATA[How to Install Multiple Versions of Node.js]]></title>
            <description><![CDATA[
    <header>
      <figure>
        <img
          alt="undefined"
          loading="lazy"
          decoding="async"
          data-nimg="1"
          src="https://fraineralex.dev/images/blog/posts/cover/how-to-install-nvm.webp"
          style="margin-top: 2rem; color: transparent; min-width: 80%; border-radius: .75rem; margin-left: auto; margin-right: auto; width: 100%; height: auto;"
        />
        <figcaption style=" text-align: right; font-size: 0.875rem; line-height: 1.25rem; padding-inline-end: 2rem; color: darkgray; padding-inline-end: 2rem; padding-top: 0.25rem;  font-style: italic;">
          Source: externlabs.com
        </figcaption>
      </figure>
      <p style=" margin-left: auto; margin-right: auto; text-transform: uppercase; text-align: center; padding-bottom: 2rem;"
        ><span style="margin-bottom: 0;">
          <time datetime="2024-01-18"
            >Jan 18, 2024</time
          >
          <span style="padding-left: 1rem; padding-right: 1rem;">•</span
          ><span style="margin-inline-end: 0;">6 min read</span>
          <span style="padding-left: 1rem; padding-right: 1rem;">|</span>
          
                  <a href="https://fraineralex.dev/tags/javascript" style="color: black; text-decoration-line: underline; text-underline-offset: 4px;">
                    JavaScript
                  </a>
                  <span style="padding-left: 10px; padding-right: 10px;"> • </span>
              
                  <a href="https://fraineralex.dev/tags/nodejs" style="color: black; text-decoration-line: underline; text-underline-offset: 4px;">
                    Node.js
                  </a>
                  <span style="padding-left: 10px; padding-right: 10px;"> • </span>
              
                  <a href="https://fraineralex.dev/tags/terminal" style="color: black; text-decoration-line: underline; text-underline-offset: 4px;">
                    Terminal
                  </a>
                  
              
          </span>
      </p>  
    </header>
  <article style="text-wrap: balance;"><p>In this article, I&#39;ll explain how you can install and manage multiple versions of Node.js with Node Version Manager (NVM) on Windows, Linux, and Mac and easily switch between them with a single command.</p>
<h2>🤔 What is NVM?</h2>
<p>Node Version Manager (NVM), as the name implies, is a tool for managing Node versions on your device.</p>
<p>Different projects on your device may be using different versions of Node. Using only one version (the one installed by <code>npm</code>) for these different projects may not give you accurate execution results.</p>
<p>For example, if you use a Node version of <strong>18.0.0</strong> for a project that uses <strong>20.0.0</strong>, you may get some errors. And if you update the Node version to <strong>20.0.0</strong> with npm and use it for a project that uses <strong>18.0.0</strong>, you may not get the expected experience.</p>
<p>In fact, you would most likely get a warning that says:</p>
<pre><code class="language-bash">This project requires Node version X
</code></pre>
<p>Instead of using npm to install and uninstall Node versions for your different projects, you can use <strong>nvm</strong>, which helps you effectively manage your node versions for each project.</p>
<p><a href="https://github.com/nvm-sh/nvm" target="_blank" rel="noopener noreferrer">NVM</a> allows you to install different versions of Node and switch between these versions depending on the project that you&#39;re working on via the command line.</p>
<blockquote>
<p><strong>🚨 Important:</strong> This guide assumes that you don&#39;t have a previous installation of <code>Node.js</code>. If you do, it might cause issues and conflicts. Before proceeding, make sure you have uninstalled any previous installations of <code>Node.js</code> and <code>npm</code>.</p>
</blockquote>
<h2>🐧 How to Install NVM on Mac, Linux or Windows WSL?</h2>
<p><strong>This would be the recommended method if your operating system is based on UNIX</strong> (like Mac, Linux, or Windows WSL), as it offers various advantages, such as handling different versions of Node simultaneously.</p>
<h3>1. Run the nvm installer</h3>
<p>To install and update <em>nvm</em>, you need to execute the installation script. You can download and run the code from the terminal using the following command:</p>
<pre><code class="language-bash">curl -o- &lt;https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh&gt; | bash

# or

wget -qO- &lt;https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh&gt; | bash
</code></pre>
<p>You can use <code>curl</code> or <code>bash</code> depending on the command available on your device.</p>
<p>This script will clone the <a href="https://github.com/nvm-sh/nvm" target="_blank" rel="noopener noreferrer">nvm repository</a> into the <code>~/.nvm</code> directory and attempt to add the execution lines depending on your terminal language (<code>~/.bash_profile</code>, <code>~/.zshrc</code>, <code>~/.profile</code>, or <code>~/.bashrc</code>).</p>
<h3>2. Update your profile configuration</h3>
<p>In case it wasn&#39;t possible for some reason, it might ask you to manually add the code lines. <strong>This is only necessary if it couldn&#39;t be done automatically.</strong> The lines to add would be these:</p>
<pre><code class="language-bash">export NVM_DIR=&quot;$([ -z &quot;${XDG_CONFIG_HOME-}&quot; ] &amp;&amp; printf %s &quot;${HOME}/.nvm&quot; || printf %s &quot;${XDG_CONFIG_HOME}/nvm&quot;)&quot;
[ -s &quot;$NVM_DIR/nvm.sh&quot; ] &amp;&amp; \\\\. &quot;$NVM_DIR/nvm.sh&quot;
</code></pre>
<p>After doing this, you may need to restart the terminal or open a new tab to use the <code>nvm</code> command.</p>
<p>This command above loads nvm for use.</p>
<h3>3. Reload the shell configuration</h3>
<p>With your profile configuration updated, now you will reload the configuration for your terminal to use:</p>
<pre><code class="language-bash">source ~/.bashrc
</code></pre>
<p>With this command executed, nvm is ready for you to use. You can confirm that nvm is installed correctly by running:</p>
<pre><code class="language-bash">nvm -v
</code></pre>
<p>This should show the version of nvm installed.</p>
<h2>🪟 How to Install NVM on Windows?</h2>
<p><code>nvm-windows</code>, although sharing the name with <code>nvm</code>, is not from the same creators and, therefore, has some differences. And among those differences is, of course, the way to install it. For <code>nvm-windows</code>, follow these steps:</p>
<ol>
<li>Go to the <a href="https://github.com/coreybutler/nvm-windows/releases" target="_blank" rel="noopener noreferrer">nvm-windows releases section</a>.</li>
<li>Download and run the <code>nvm-setup.exe</code> file from the latest available release.</li>
<li>Run the <code>nvm-setup.exe</code> file.</li>
<li>Follow the guided package installation steps and choose the desired configuration.</li>
<li>Once completed, open a <code>PowerShell</code> terminal and run:</li>
</ol>
<p>When done, you can confirm that nvm has been installed by running:</p>
<pre><code class="language-bash">nvm -v
</code></pre>
<p>If nvm was installed correctly, this command will show you the nvm version installed.</p>
<p>And with this, we are ready to work with <code>nvm-windows</code>. If you encounter any issues, you can <strong>check the <a href="https://github.com/coreybutler/nvm-windows/wiki/Common-Issues" target="_blank" rel="noopener noreferrer">Common Issues section of the repository</a> to see if your problem has a solution.</strong></p>
<h2>🕹️ How NVM Works?</h2>
<p>With nvm installed, you can now install, uninstall, and switch between different Node versions on your Windows, Linux, or Mac device.</p>
<p>You can install Node versions like this:</p>
<pre><code class="language-bash">nvm install --lts
</code></pre>
<p>This will install the <strong>long-term support version of Node</strong>. Currently, it is version 20, but in the future, it will be 22 and so on.</p>
<blockquote>
<p>LTS or long-term support means that it is a version that will receive support for a longer period than other versions. Generally, it is up to 30 months of support for critical errors. If you are going to use Node in production, it&#39;s best to use only LTS versions.</p>
</blockquote>
<p>If you prefer, you can also install a specific version either by indicating the major or directly the exact version:</p>
<pre><code class="language-bash">nvm install 21 # this will install the latest version 21 of Node.js
nvm install 12.6.0 # this will install exactly version 21.6.0
</code></pre>
<h2>🚀 Using a Node.js Version With NVM</h2>
<p>Sometimes you may have more than one installed version of Node.js on your user. To see all the versions of Node.js you have installed, you can use the <code>nvm ls</code> command. To see the versions available for installation, you have to use <code>nvm ls-remote</code>.</p>
<p>Once you have more than one on your system, you&#39;ll want to switch between those versions. To do this, run <code>nvm use &lt;version-you-want-to-use&gt;</code> for example:</p>
<pre><code class="language-bash">nvm use 20
nvm use 21
nvm use --lts
</code></pre>
<p>If you want one of these to be your default version, so that it is used the next time you open a tab, you have to create an alias for that version called <code>default</code>.</p>
<p>For example, let&#39;s say you have version 16 and 18 installed, and now you install version 20, and you want this to be the default version from now on. You should do the following:</p>
<pre><code class="language-bash">nvm install 20
nvm alias default 20
</code></pre>
<blockquote>
<p>The first time you run <code>nvm install</code>, it will make that version the default.</p>
</blockquote>
<h2>⚠️ Possible Problems</h2>
<ul>
<li>On Mac, you&#39;ll need to have Xcode development tools installed. When you run the <code>nvm</code> installation script for the first time, a window may appear asking you to do this. Once installed, try installing <code>nvm</code> again with the same script as before.</li>
<li>Remember, as I mentioned, after the installation, you may need to restart the terminal or create a new tab before you can run the <code>nvm</code> command.</li>
<li>If you have any further issues, you can check the <a href="https://github.com/nvm-sh/nvm#troubleshooting-on-linux" target="_blank" rel="noopener noreferrer">Troubleshooting on Linux section in the nvm repository.</a></li>
</ul>
</article>]]></description>
            <link>https://fraineralex.dev/blog/how-to-install-multiple-versions-nodejs-nvm</link>
            <guid isPermaLink="false">https://fraineralex.dev/blog/how-to-install-multiple-versions-nodejs-nvm</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[terminal]]></category>
            <dc:creator><![CDATA[Frainer Encarnación]]></dc:creator>
            <pubDate>Thu, 18 Jan 2024 00:00:00 GMT</pubDate>
            <enclosure url="https://fraineralex.dev/blog/images/blog/posts/cover/rss/how-to-install-nvm.png" length="0" type="png"/>
        </item>
    </channel>
</rss>