<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Code With Joseph</title>
    <description>The latest articles on DEV Community by Code With Joseph (@joeskills).</description>
    <link>https://dev.to/joeskills</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F795097%2Fb1866176-ad61-4235-b642-75485cc121c9.jpg</url>
      <title>DEV Community: Code With Joseph</title>
      <link>https://dev.to/joeskills</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joeskills"/>
    <language>en</language>
    <item>
      <title>Why is the useEffect hook used in fetching data in React?</title>
      <dc:creator>Code With Joseph</dc:creator>
      <pubDate>Tue, 11 Jun 2024 15:50:29 +0000</pubDate>
      <link>https://dev.to/joeskills/why-is-the-useeffect-hook-used-in-fetching-data-in-react-2nhd</link>
      <guid>https://dev.to/joeskills/why-is-the-useeffect-hook-used-in-fetching-data-in-react-2nhd</guid>
      <description>&lt;p&gt;To make this as simple as possible, I'll &lt;em&gt;avoid talking about Next.js&lt;/em&gt;. So you want to &lt;em&gt;fetch data from a server&lt;/em&gt;? What's the first thing that comes to your mind? Create a &lt;em&gt;function to handle the request&lt;/em&gt;. &lt;strong&gt;That makes sense. What could go wrong here?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from 'react';

function FetchDataComponent() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  // Bad practice: Fetching data directly within the component rendering logic
  const fetchData = async () =&amp;gt; {
    setLoading(true);
    setError(null);

    try {
      const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      const data = await response.json();
      setData(data);
    } catch (error) {
      setError(error.message);
    } finally {
      setLoading(false);
    }
  };

  // Simulating a bad approach: Directly calling fetchData within the component rendering logic
  fetchData();

  return (
    &amp;lt;div className="fetch-data-container"&amp;gt;
      &amp;lt;h1&amp;gt;Fetch Data Example&amp;lt;/h1&amp;gt;
      {loading &amp;amp;&amp;amp; &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;}
      {error &amp;amp;&amp;amp; &amp;lt;p&amp;gt;Error: {error}&amp;lt;/p&amp;gt;}
      {data &amp;amp;&amp;amp; (
        &amp;lt;div&amp;gt;
          &amp;lt;h2&amp;gt;{data.title}&amp;lt;/h2&amp;gt;
          &amp;lt;p&amp;gt;{data.body}&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  );
}

export default FetchDataComponent;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Back to React basics
&lt;/h2&gt;

&lt;p&gt;I think this is a &lt;em&gt;straightforward answer&lt;/em&gt;. &lt;strong&gt;Infinite loops!&lt;/strong&gt; Because when the state of a component changes, the component and its children get re-rendered. Using a &lt;code&gt;useState&lt;/code&gt; hook to modify the &lt;strong&gt;state without any constraints causes an infinite loop&lt;/strong&gt; to occur. &lt;/p&gt;

&lt;h3&gt;
  
  
  Effects! Effects! Effects!
&lt;/h3&gt;

&lt;p&gt;Effects should happen &lt;strong&gt;after the render phase&lt;/strong&gt; of your component. Effects usually happen when the &lt;strong&gt;state&lt;/strong&gt; of a component changes, the &lt;strong&gt;props&lt;/strong&gt; of a component change, &lt;strong&gt;DOM manipulation&lt;/strong&gt;, &lt;strong&gt;data fetching&lt;/strong&gt;, and even &lt;strong&gt;user interaction&lt;/strong&gt; causes effects to happen which causes a component to re-render. By using a &lt;code&gt;useEffect&lt;/code&gt; hook, you make sure &lt;strong&gt;the effect happens after the initial render&lt;/strong&gt; and also re-renders depending on what is placed in the dependency array (the second parameter) of the &lt;code&gt;useEffect&lt;/code&gt; hook. This means if the &lt;strong&gt;dependency array is empty, it only runs once.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Add a &lt;code&gt;useEffect&lt;/code&gt; hook, right?
&lt;/h2&gt;

&lt;p&gt;Let's say I add a &lt;code&gt;useEffect&lt;/code&gt; hook, we get &lt;strong&gt;controlled effects&lt;/strong&gt;, and we can make sure the effects only occur once &lt;strong&gt;after the initial render&lt;/strong&gt;. Plus, sometimes we only want to &lt;strong&gt;fetch data once&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState, useEffect } from 'react';

function FetchDataComponent() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() =&amp;gt; {
    const fetchData = async () =&amp;gt; {
      setLoading(true);
      setError(null);

      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
        if (!response.ok) {
          throw new Error('Network response was not ok');
        }
        const data = await response.json();
        setData(data);
      } catch (error) {
        setError(error.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []); // Empty dependency array means this effect runs once after the initial render

  return (
    &amp;lt;div className="fetch-data-container"&amp;gt;
      &amp;lt;h1&amp;gt;Fetch Data Example&amp;lt;/h1&amp;gt;
      {loading &amp;amp;&amp;amp; &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;}
      {error &amp;amp;&amp;amp; &amp;lt;p&amp;gt;Error: {error}&amp;lt;/p&amp;gt;}
      {data &amp;amp;&amp;amp; (
        &amp;lt;div&amp;gt;
          &amp;lt;h2&amp;gt;{data.title}&amp;lt;/h2&amp;gt;
          &amp;lt;p&amp;gt;{data.body}&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  );
}

export default FetchDataComponent;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  But is something missing?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;It can't be that simple&lt;/em&gt;. Can it? What happens when you want to change the data you fetched &lt;strong&gt;because of user interaction&lt;/strong&gt;? A lot of the time, &lt;strong&gt;data isn't static in a React application&lt;/strong&gt;. Let's assume we want to create a &lt;strong&gt;product listing app&lt;/strong&gt; that &lt;strong&gt;fetches different items&lt;/strong&gt; based on &lt;strong&gt;different categories&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState, useEffect } from 'react';

const categories = ['Electronics', 'Clothing', 'Books'];

function ProductListComponent() {
  const [selectedCategory, setSelectedCategory] = useState(null);
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() =&amp;gt; {
    if (!selectedCategory) return;

    const fetchProducts = async () =&amp;gt; {
      setLoading(true);
      setError(null);

      try {
        // Simulate fetching data from an API based on the selected category
        const response = await fetch(`https://api.example.com/products?category=${selectedCategory}`);
        if (!response.ok) {
          throw new Error('Network response was not ok');
        }
        const data = await response.json();
        setProducts(data);
      } catch (error) {
        setError(error.message);
      } finally {
        setLoading(false);
      }
    };

    fetchProducts();
  }, [selectedCategory]);

  return (
    &amp;lt;div className="product-list-container"&amp;gt;
      &amp;lt;h1&amp;gt;Product List&amp;lt;/h1&amp;gt;
      &amp;lt;div&amp;gt;
        {categories.map(category =&amp;gt; (
          &amp;lt;button key={category} onClick={() =&amp;gt; setSelectedCategory(category)}&amp;gt;
            {category}
          &amp;lt;/button&amp;gt;
        ))}
      &amp;lt;/div&amp;gt;
      {loading &amp;amp;&amp;amp; &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;}
      {error &amp;amp;&amp;amp; &amp;lt;p&amp;gt;Error: {error}&amp;lt;/p&amp;gt;}
      {products.length &amp;gt; 0 &amp;amp;&amp;amp; (
        &amp;lt;ul&amp;gt;
          {products.map(product =&amp;gt; (
            &amp;lt;li key={product.id}&amp;gt;
              &amp;lt;h2&amp;gt;{product.name}&amp;lt;/h2&amp;gt;
              &amp;lt;p&amp;gt;Price: ${product.price}&amp;lt;/p&amp;gt;
              &amp;lt;p&amp;gt;{product.description}&amp;lt;/p&amp;gt;
            &amp;lt;/li&amp;gt;
          ))}
        &amp;lt;/ul&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  );
}

export default ProductListComponent;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;useEffect&lt;/code&gt; can't provide everything
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; shines when you're trying to control effects in your app, but for data fetching, the concept doesn't reach far.&lt;/p&gt;

&lt;h3&gt;
  
  
  Loading &amp;amp; Error States
&lt;/h3&gt;

&lt;p&gt;You must have noticed that I've been &lt;strong&gt;manually setting loading and error states&lt;/strong&gt;. Which creates &lt;strong&gt;extra lines of code and complexity&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Race Conditions
&lt;/h3&gt;

&lt;p&gt;A race condition occurs when &lt;strong&gt;multiple asynchronous tasks are trying to update the same value at the same time.&lt;/strong&gt; Since there are three &lt;strong&gt;different buttons to fetch different data&lt;/strong&gt; for each, a request &lt;strong&gt;to fetch one category might be slower&lt;/strong&gt; than the other. Making &lt;strong&gt;your state unpredictable and inconsistent&lt;/strong&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  Example of a race condition
&lt;/h4&gt;

&lt;p&gt;Let's assume a user &lt;strong&gt;clicks on the &lt;code&gt;electronics&lt;/code&gt; button, but quickly changes it to the &lt;code&gt;clothing&lt;/code&gt; button&lt;/strong&gt;. The user clicked the &lt;code&gt;clothing&lt;/code&gt; button last. &lt;strong&gt;The component gets re-rendered, but the previous fetch is still happening simultaneously with the new one&lt;/strong&gt;. So &lt;code&gt;clothing&lt;/code&gt; data should show up? &lt;strong&gt;If the request for fetching &lt;code&gt;electronics&lt;/code&gt; data was slower than &lt;code&gt;clothing&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;electronics&lt;/code&gt; should finish last&lt;/strong&gt;. And that's the data that'll show up. This makes the state inconsistent, &lt;strong&gt;like the user didn't click the &lt;code&gt;clothing&lt;/code&gt; button last&lt;/strong&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  How to fix a race condition
&lt;/h4&gt;

&lt;p&gt;You can fix this issue by using &lt;strong&gt;a cleanup function in your &lt;code&gt;useEffect&lt;/code&gt; and a boolean flag&lt;/strong&gt;. This is a solution from the React official docs. The way this works is through closures. When the component is re-rendered, the &lt;strong&gt;cleanup function updates the state of the previous effect&lt;/strong&gt; using the &lt;code&gt;ignore&lt;/code&gt; boolean flag. You can also add &lt;code&gt;AbortController&lt;/code&gt; and &lt;code&gt;AbortSignal&lt;/code&gt; to prevent unnecessary network traffic from the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  if (!selectedCategory) return;

  let ignore = true; // Flag to track component mount status

  const fetchProducts = async () =&amp;gt; {
    setLoading(true);
    setError(null);

    try {
      const response = await fetch(`https://api.example.com/products?category=${selectedCategory}`);
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      const data = await response.json();
      if (ignore) {
        setProducts(data);
      }
    } catch (error) {
      if (ignore) {
        setError(error.message);
      }
    } finally {
      if (ignore) {
        setLoading(false);
      }
    }
  };

  fetchProducts();

  // Cleanup function to set the flag to false
  return () =&amp;gt; {
    ignore = false;
  };
}, [selectedCategory]);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lack of caching
&lt;/h3&gt;

&lt;p&gt;You have to &lt;strong&gt;manually cache your data for every request&lt;/strong&gt; when using the &lt;code&gt;useEffect&lt;/code&gt; hook to fetch data. Caching helps with a good user experience. Caching is important because it &lt;strong&gt;makes your app seem fast&lt;/strong&gt;, let's assume a user clicks to another page and then goes back, without caching the user will see a loader (if you have one) again because the &lt;strong&gt;data was re-fetched again&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Fix for caching
&lt;/h4&gt;

&lt;p&gt;We can use the browser's local storage to save the fetched data and use it when needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
    if (!selectedCategory) return;

    // Check if data is available in local storage
    const cachedData = localStorage.getItem(`products_${selectedCategory}`);
    if (cachedData) {
      setProducts(JSON.parse(cachedData));
      return;
    }

    let ignore = false; // Flag to track component unmount status

    const fetchProducts = async () =&amp;gt; {
      setLoading(true);
      setError(null);

      try {
        const response = await fetch(`https://api.example.com/products?category=${selectedCategory}`);
        if (!response.ok) {
          throw new Error('Network response was not ok');
        }
        const data = await response.json();
        if (!ignore) {
          setProducts(data);
          localStorage.setItem(`products_${selectedCategory}`, JSON.stringify(data)); // Save data to local storage
        }
      } catch (error) {
        if (!ignore) {
          setError(error.message);
        }
      } finally {
        if (!ignore) {
          setLoading(false);
        }
      }
    };

    fetchProducts();

    // Cleanup function to set the flag to true
    return () =&amp;gt; {
      ignore = true;
    };
  }, [selectedCategory]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Refetches
&lt;/h3&gt;

&lt;p&gt;In some apps, you might build, the &lt;strong&gt;data you fetch has to change constantly&lt;/strong&gt;. To &lt;strong&gt;avoid it from getting &lt;em&gt;stale&lt;/em&gt;&lt;/strong&gt;, you need to perform background updates and re-fetches. The number of available products could change or the number of reviews could also change.&lt;/p&gt;

&lt;h4&gt;
  
  
  Let's add a quick fix
&lt;/h4&gt;

&lt;p&gt;We can use an interval to re-fetch the data and then clear the interval in the cleanup function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// UseEffect to fetch data when selectedCategory changes
  useEffect(() =&amp;gt; {
    if (!selectedCategory) return;

    // Check if data is available in local storage
    const cachedData = localStorage.getItem(`products_${selectedCategory}`);
    if (cachedData) {
      setProducts(JSON.parse(cachedData));
    } else {
      fetchProducts(selectedCategory);
    }

    let ignore = false; // Flag to track component unmount status

    // Interval for refetching data periodically
    const intervalId = setInterval(() =&amp;gt; {
      fetchProducts(selectedCategory, ignore);
    }, 60000); // Refetch every 60 seconds

    // Cleanup function to clear the interval and set the flag to true
    return () =&amp;gt; {
      clearInterval(intervalId);
      ignore = true;
    };
  }, [selectedCategory]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Let's bring in React Query
&lt;/h2&gt;

&lt;p&gt;From all these problems we weren't just talking about data fetching we were also talking about &lt;strong&gt;managing the state in the app properly&lt;/strong&gt;. &lt;strong&gt;React Query isn't just for data fetching&lt;/strong&gt;, it's an &lt;strong&gt;async state manager&lt;/strong&gt;. It fixes all the bugs from the &lt;code&gt;useEffect&lt;/code&gt; hook. It comes with &lt;strong&gt;caching, error &amp;amp; loading states, automatic query invalidation &amp;amp; re-fetches, and no race conditions&lt;/strong&gt;. There are other data-fetching libraries like SWR, but &lt;strong&gt;React Query has better flexibility with its features, is more performant, and has a larger community&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does it look like as a solution?
&lt;/h3&gt;

&lt;p&gt;Well now, React Query fixes those bugs better and your &lt;strong&gt;code is more concise and easier to read&lt;/strong&gt;. React Query manages the complexities of &lt;strong&gt;managing your state properly&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from 'react';
import { useQueryClient, useQuery, useMutation } from 'react-query';

const categories = ['Electronics', 'Clothing', 'Books'];

function ProductListComponent() {
  const queryClient = useQueryClient();
  const [selectedCategory, setSelectedCategory] = useState(null);

  // Query to fetch products
  const fetchProducts = async (category) =&amp;gt; {
    const response = await fetch(`https://api.example.com/products?category=${category}`);
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  };

  // Mutation to fetch products and invalidate the query
  const mutation = useMutation(fetchProducts, {
    onSuccess: (data, variables) =&amp;gt; {
      // Invalidate and refetch
      queryClient.setQueryData(['products', variables], data);
      queryClient.invalidateQueries(['products', variables]);
    },
  });

  // Query to get products
  const { data: products, isLoading, isError } = useQuery(
    ['products', selectedCategory],
    () =&amp;gt; fetchProducts(selectedCategory),
    {
      enabled: !!selectedCategory, // Only fetch when selectedCategory is truthy
      staleTime: 5 * 60 * 1000, // Cache data for 5 minutes
    }
  );

  // Handler for category selection
  const handleCategoryClick = (category) =&amp;gt; {
    setSelectedCategory(category);
    mutation.mutate(category);
  };

  return (
    &amp;lt;div className="product-list-container"&amp;gt;
      &amp;lt;h1&amp;gt;Product List&amp;lt;/h1&amp;gt;
      &amp;lt;div&amp;gt;
        {categories.map(category =&amp;gt; (
          &amp;lt;button key={category} onClick={() =&amp;gt; handleCategoryClick(category)}&amp;gt;
            {category}
          &amp;lt;/button&amp;gt;
        ))}
      &amp;lt;/div&amp;gt;
      {isLoading &amp;amp;&amp;amp; &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;}
      {isError &amp;amp;&amp;amp; &amp;lt;p&amp;gt;Error fetching data&amp;lt;/p&amp;gt;}
      {products &amp;amp;&amp;amp; (
        &amp;lt;ul&amp;gt;
          {products.map(product =&amp;gt; (
            &amp;lt;li key={product.id}&amp;gt;
              &amp;lt;h2&amp;gt;{product.name}&amp;lt;/h2&amp;gt;
              &amp;lt;p&amp;gt;Price: ${product.price}&amp;lt;/p&amp;gt;
              &amp;lt;p&amp;gt;{product.description}&amp;lt;/p&amp;gt;
            &amp;lt;/li&amp;gt;
          ))}
        &amp;lt;/ul&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  );
}

export default ProductListComponent;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;At least now, you can see &lt;strong&gt;why the &lt;code&gt;useEffect&lt;/code&gt; hook isn't the best thing&lt;/strong&gt; when &lt;strong&gt;managing async state&lt;/strong&gt; in your app. It might be okay for fetching data, but it doesn't have enough features to make &lt;strong&gt;state predictable&lt;/strong&gt;. So you can fetch your data without React Query. But with React Query your &lt;strong&gt;code and your state become more maintainable&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/amrguaily/useeffect-some-issues-with-data-fetching-in-effects-21nn"&gt;https://dev.to/amrguaily/useeffect-some-issues-with-data-fetching-in-effects-21nn&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/sakethkowtha/react-query-vs-useswr-122b"&gt;https://dev.to/sakethkowtha/react-query-vs-useswr-122b&lt;/a&gt;&lt;br&gt;
&lt;a href="https://tkdodo.eu/blog/why-you-want-react-query"&gt;https://tkdodo.eu/blog/why-you-want-react-query&lt;/a&gt;&lt;br&gt;
&lt;a href="https://medium.com/@omar1.mayallo4/react-hooks-useeffect-problems-in-data-fetching-5e2abc37a1c9"&gt;https://medium.com/@omar1.mayallo4/react-hooks-useeffect-problems-in-data-fetching-5e2abc37a1c9&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=SYs5E4yrtpY"&gt;https://www.youtube.com/watch?v=SYs5E4yrtpY&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;You can hear more from me on:&lt;br&gt;
&lt;a href="https://x.com/code_withjoseph"&gt;Twitter (X)&lt;/a&gt; | &lt;a href="https://www.instagram.com/codewithjosephwebdev"&gt;Instagram&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>data</category>
    </item>
    <item>
      <title>Simplest guide to Next.js APIs</title>
      <dc:creator>Code With Joseph</dc:creator>
      <pubDate>Fri, 07 Jun 2024 00:12:41 +0000</pubDate>
      <link>https://dev.to/joeskills/simplest-guide-to-nextjs-apis-204g</link>
      <guid>https://dev.to/joeskills/simplest-guide-to-nextjs-apis-204g</guid>
      <description>&lt;h2&gt;
  
  
  What Makes Next.js APIs So Special?
&lt;/h2&gt;

&lt;p&gt;I'm assuming you know what APIs are. APIs are an important part of developing functional web apps. Next.js has introduced the feature to create route handlers for APIs since version 9.0 in 2019. There are lots of ways to build a separate backend (like Ruby, PHP, Express.js, Django, etc.) other than Next.js, &lt;em&gt;&lt;strong&gt;so why even do it in Next.js?&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  It might not be that great
&lt;/h2&gt;

&lt;p&gt;By default, Next.js route handlers use serverless functions, which means in some cases you might have &lt;strong&gt;cold starts&lt;/strong&gt;, &lt;strong&gt;high cost for scaling&lt;/strong&gt;, and &lt;strong&gt;vendor lock-in&lt;/strong&gt; since it requires serverless platforms like Vercel to work properly. It also has &lt;strong&gt;limitations when it comes to using complex middleware,&lt;/strong&gt; unlike a library like Express.js, which was meant to be used for routing on a server. &lt;/p&gt;

&lt;h2&gt;
  
  
  But it's not that bad
&lt;/h2&gt;

&lt;p&gt;But most of these issues are automatically taken care of by Vercel (which provides amazing &lt;strong&gt;caching &amp;amp; optimization&lt;/strong&gt; strategies) and &lt;strong&gt;serverless functions can be scalable and cost-effective&lt;/strong&gt; if done properly. Here are some more benefits of using Next.js as both your frontend and backend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hot reloading:&lt;/strong&gt; This means when developing, you get the same hot reload features as your frontend for your API routes, which makes development faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency of your codebase:&lt;/strong&gt; It greatly simplifies development by keeping the frontend and backend logic in the same place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File-based routing&lt;/strong&gt;: API routes use a simple file-based routing system that easily integrates into your Next.js project structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No additional setup:&lt;/strong&gt; There's no need to configure additional middleware or create a separate server. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplication:&lt;/strong&gt; It has built-in features to simplify common tasks when developing your API.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  API routes in the Next.js app router
&lt;/h1&gt;

&lt;p&gt;The app router uses a &lt;strong&gt;file-based routing system&lt;/strong&gt; that starts from the &lt;code&gt;app&lt;/code&gt; directory. You can &lt;strong&gt;mirror URL paths by defining API routes in a nested folder structure&lt;/strong&gt;. By doing this, you create &lt;em&gt;Node.js serverless functions that act as API endpoints&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
└── api/
    └── hello/
        └── route.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating API routes
&lt;/h2&gt;

&lt;p&gt;The API route file is usually named &lt;code&gt;route.js&lt;/code&gt; or &lt;code&gt;route.ts&lt;/code&gt; (for TypeScript users). This has to be in an &lt;code&gt;api&lt;/code&gt; folder in the &lt;code&gt;app&lt;/code&gt; folder. You can define &lt;strong&gt;functions in the &lt;code&gt;route.js&lt;/code&gt; files that handle different HTTP methods&lt;/strong&gt; (such as GET, POST, PUT, PATCH, etc.). For example, when you can make a &lt;code&gt;GET&lt;/code&gt; request to &lt;code&gt;/api/hello&lt;/code&gt; it would be handled by a &lt;code&gt;GET&lt;/code&gt; function in &lt;code&gt;app/api/hello/route.js&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Request methods and API route functions
&lt;/h3&gt;

&lt;p&gt;The standard convention is that within the &lt;code&gt;route.js&lt;/code&gt; or &lt;code&gt;route.ts&lt;/code&gt; file, you name an exported function with the &lt;strong&gt;HTTP method you want it to handle in your API endpoint in uppercase&lt;/strong&gt;. The functions usually look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app/api/users/route.js

export async function GET(request) {
  // Simulate a database call to fetch users
  const users = [
    { id: 1, name: 'John Doe' },
    { id: 2, name: 'Jane Doe' },
  ];

  // Return the users as a JSON response
  return NextResponse.json(users);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  NextResponse and Request
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;NextResponse&lt;/code&gt; is a &lt;strong&gt;helper class&lt;/strong&gt; that extends the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Response"&gt;web Response API&lt;/a&gt; with &lt;strong&gt;additional convenience methods&lt;/strong&gt;, which are used to create responses. You can use it to rewrite, redirect, set headers, or create and send JSON responses.&lt;/p&gt;




&lt;p&gt;The &lt;code&gt;Request&lt;/code&gt;: When you define functions by using HTTP methods in creating your API endpoints, &lt;strong&gt;the functions receive a &lt;code&gt;Request&lt;/code&gt; object as an argument&lt;/strong&gt; which contains information about the incoming request. The object uses the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Request"&gt;web Request API&lt;/a&gt;. You can use it to read the request query parameters, &lt;strong&gt;read the request body&lt;/strong&gt;, or access the request headers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic routes
&lt;/h2&gt;

&lt;p&gt;By using &lt;strong&gt;square brackets&lt;/strong&gt;, when naming your folders before the &lt;code&gt;route.ts&lt;/code&gt; or &lt;code&gt;route.js&lt;/code&gt; file, you can create a dynamic route for your API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
  └── api/
      └── users/
          └── [userId]/
              └── route.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Accessing a dynamic route
&lt;/h3&gt;

&lt;p&gt;The dynamic route parameters can be accessed from the &lt;strong&gt;route handler function's second argument&lt;/strong&gt;, which has the &lt;code&gt;params&lt;/code&gt; object.&lt;br&gt;
Take a look at this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app/api/users/[userId]/route.ts

export async function GET(request: Request, { params }: { params: { userId: string }}) {
const {userId} = params

  // Simulate a database call to fetch users
  const users = [
    { id: 1, name: 'John Doe' },
    { id: 2, name: 'Jane Doe' },
  ];

  //filter user by id
  const user = users.filter((user) =&amp;gt; user.id == userId)

  // Return the users as a JSON response
  return NextResponse.json(user);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope that wasn't complicated, and you got something out of this.&lt;br&gt;
You can hear more from me on:&lt;br&gt;
&lt;a href="https://x.com/code_withjoseph"&gt;Twitter (X)&lt;/a&gt; | &lt;a href="https://www.instagram.com/codewithjosephwebdev"&gt;Instagram&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>simple</category>
    </item>
    <item>
      <title>How to quickly add a rich text editor to your Next.js project using TipTap</title>
      <dc:creator>Code With Joseph</dc:creator>
      <pubDate>Wed, 05 Jun 2024 03:20:04 +0000</pubDate>
      <link>https://dev.to/joeskills/how-to-add-a-rich-text-editor-to-your-nextjs-project-using-tiptap-1fil</link>
      <guid>https://dev.to/joeskills/how-to-add-a-rich-text-editor-to-your-nextjs-project-using-tiptap-1fil</guid>
      <description>&lt;p&gt;&lt;a href="https://tiptap.dev/"&gt;Tiptap&lt;/a&gt; is an open source headless wrapper around &lt;a href="https://prosemirror.net/"&gt;ProseMirror&lt;/a&gt;. ProseMirror is a toolkit for building rich text WYSIWYG editors. The best part about Tiptap is that it's headless, which means you can customize and create your rich text editor however you want. I'll be using TailwindCSS for this tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to get Tiptap working
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 - Install Tiptap into your project
&lt;/h3&gt;

&lt;p&gt;Tiptap is framework-agnostic, it integrates with many popular frameworks, even PHP and vanilla JavaScript. &lt;br&gt;
There are three packages (&lt;code&gt;@tiptap/react&lt;/code&gt;, &lt;code&gt;@tiptap/pm&lt;/code&gt;, and &lt;code&gt;@tiptap/starter-kit&lt;/code&gt;) you need to install that provide all the necessary extensions for you to add Tiptap to your Next.js project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @tiptap/react @tiptap/pm @tiptap/starter-kit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 - Create a Tiptap component
&lt;/h3&gt;

&lt;p&gt;To use Tiptap in your next.js project, you need to add a new Component. And add this piece of code to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'use client'

import { useEditor, EditorContent } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'

const Tiptap = () =&amp;gt; {
  const editor = useEditor({
    extensions: [
      StarterKit,
    ],
    content: '&amp;lt;p&amp;gt;Hello World! 🌎️&amp;lt;/p&amp;gt;',
  })

  return (
    &amp;lt;EditorContent editor={editor} /&amp;gt;
  )
}

export default Tiptap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me break it down. &lt;code&gt;Starterkit&lt;/code&gt; is a collection of the most useful extensions in Tiptap for getting started. Extensions are a powerful way to extend the functionality of your Tiptap editor, for example, the &lt;a href="https://tiptap.dev/docs/editor/api/extensions/history"&gt;History plugin&lt;/a&gt; that helps you track changes when editing your document and provides redo and undo options. &lt;code&gt;useEditor&lt;/code&gt; is a hook provided by Tiptap that it initializes an editor instance. This instance provides the interface through which you can interact with the editor's functionality. &lt;code&gt;EditorContent&lt;/code&gt; binds your editor instance and the DOM element where your content is rendered. The content property is optional, but it determines the initial state of your editor. That's all you need to get your rich text editor up and running with Tiptap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing your editor
&lt;/h2&gt;

&lt;p&gt;Since Tiptap comes raw, it allows you to choose how your editor looks like. By default, it doesn't come with a menu bar for editing your document, but you can add it by using the &lt;code&gt;slotBefore&lt;/code&gt; prop in &lt;code&gt;EditorContent&lt;/code&gt;. What the &lt;code&gt;slotBefore&lt;/code&gt; prop does is that it tells &lt;code&gt;EditorContent&lt;/code&gt; that there should be some content at the top of the editor. To create our menu bar, we can just use buttons. Let's create a menu bar and add a button to toggle boldness.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;div className="flex flex-wrap gap-2"&amp;gt;
 &amp;lt;button
        onClick={() =&amp;gt; editor.chain().focus().toggleBold().run()}
        disabled={!editor.can().chain().focus().toggleBold().run()}
        className={editor.isActive("bold") ? "is-active" : ""}
      &amp;gt;
        bold
      &amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That feels like a lot, doesn't it? Let me take it slowly. The commands that are passed into the &lt;code&gt;onClick&lt;/code&gt; prop, and the &lt;code&gt;disabled&lt;/code&gt; prop are a chain of commands. Each of them is explained below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;editor&lt;/code&gt; should be a Tiptap instance,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chain()&lt;/code&gt; is used to tell the editor you want to execute multiple commands,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;focus()&lt;/code&gt; sets the focus back to the editor,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;toggleBold()&lt;/code&gt; marks the selected text bold, or removes the bold mark from the text selection if it’s already applied and&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;run()&lt;/code&gt; will execute the chain.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isActive()&lt;/code&gt; checks if something is applied to the selected text already.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;!editor.can()&lt;/code&gt;: Checks if the &lt;code&gt;toggleBold&lt;/code&gt; command can be executed. If it can't, the &lt;code&gt;!&lt;/code&gt; operator negates the result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm also using an &lt;code&gt;is-active&lt;/code&gt; class to provide UI feedback when the button is toggled.&lt;/p&gt;

&lt;p&gt;Now, the Tiptap component should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'use client'

import { useEditor, EditorContent } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'

const Tiptap = () =&amp;gt; {
  const editor = useEditor({
    extensions: [
      StarterKit,
    ],
    content: '&amp;lt;p&amp;gt;Hello World! 🌎️&amp;lt;/p&amp;gt;',
  })

  return (
    &amp;lt;EditorContent editor={editor} slotBefore={&amp;lt;div className="flex flex-wrap gap-2"&amp;gt;
 &amp;lt;button
        onClick={() =&amp;gt; editor.chain().focus().toggleBold().run()}
        disabled={!editor.can().chain().focus().toggleBold().run()}
        className={editor.isActive("bold") ? "is-active" : ""}
      &amp;gt;
        bold
      &amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;} /&amp;gt;
  )
}

export default Tiptap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can add more buttons to toggle more things in your text like headings, paragraphs, redo/undo, blockquotes, bullet lists, and a lot more.&lt;/p&gt;

&lt;h3&gt;
  
  
  (Optional) Use the &lt;code&gt;@tailwindcss/typography&lt;/code&gt; to get the best typography styles for your editor
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;@tailwindcss/typography&lt;/code&gt; plugin applies typography styles to your HTML elements that follow best practices. By default, TailwindCSS applies minimalistic styles and it may not include detailed typography styles. The content on your Tiptap editor is rendered as HTML by using this plugin you're telling your editor to inherit the typography styles provided by TailwindCSS such as margins, font styles, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev @tailwindcss/typography
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use it by installing and then adding it to your list of plugins in your &lt;code&gt;tailwind.config.ts&lt;/code&gt; or &lt;code&gt;tailwind.config.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig } from 'tailwindcss';

export default defineConfig({
  mode: 'jit',
  purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [
    require('@tailwindcss/typography'), // Add the typography plugin
    // other plugins
  ],
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All you have to do is to add the plugin. Your Tailwind config file might look different from this, but it's only the plugin that's necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating an output from your editor
&lt;/h2&gt;

&lt;p&gt;There are two ways you can get your content from Tiptap. The first way is through JSON, and the second option is with HTML. Tiptap doesn't support Markdown as an output format. But it supports Markdown when you're editing your content. Here's an example in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const json = editor.getJSON()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const html = editor.getHTML()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also listen for changes to store your content continuously as it changes. By adding the &lt;code&gt;onUpdate&lt;/code&gt; hook provided by Tiptap that is triggered on every change, generating the data, and storing it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const editor = useEditor({
    extensions: [
      StarterKit,
    ],
  // triggered on every change
  onUpdate: ({ editor }) =&amp;gt; {
    const json = editor.getJSON()
    // send the content to an API here
  },
    content: '&amp;lt;p&amp;gt;Hello World! 🌎️&amp;lt;/p&amp;gt;',
  })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's also one last option for storing your content, which is &lt;a href="https://yjs.dev/"&gt;y.js&lt;/a&gt;. You can head to &lt;a href="https://tiptap.dev/docs"&gt;Tiptap's official docs&lt;/a&gt; to learn more about storing your content and how to customize it better.&lt;/p&gt;

&lt;p&gt;That's it, that's all you need to get started with Tiptap in your Next.js project.&lt;/p&gt;

&lt;p&gt;You can hear more from me on: &lt;br&gt;
&lt;a href="https://x.com/code_withjoseph"&gt;Twitter (X)&lt;/a&gt; | &lt;a href="https://www.instagram.com/codewithjosephwebdev"&gt;Instagram&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>An Easy Guide To Next14 Authentication With Kinde</title>
      <dc:creator>Code With Joseph</dc:creator>
      <pubDate>Sat, 01 Jun 2024 01:08:25 +0000</pubDate>
      <link>https://dev.to/joeskills/an-easy-guide-to-next14-authentication-with-kinde-auth-5f50</link>
      <guid>https://dev.to/joeskills/an-easy-guide-to-next14-authentication-with-kinde-auth-5f50</guid>
      <description>&lt;p&gt;This is a simple tutorial on adding authentication to your Next14 app using &lt;a href="https://kinde.com/"&gt;Kinde&lt;/a&gt;. To follow this tutorial, you need a Kinde account. Kinde is a powerful user authentication service that integrates in minutes. They offer an amazing free tier for their service and the signup process is straightforward.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmjzvd4rj32amsm47c71.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmjzvd4rj32amsm47c71.jpg" alt="Image description" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To continue the signup process, Kinde will ask you to add your business name and a domain name for Kinde to host your app. It also sets a default region for where your data will be stored, but you can modify it if necessary. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6w1wmejrt2zq5n1opqhb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6w1wmejrt2zq5n1opqhb.jpg" alt="Image description" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After clicking next, it will ask you if you want to start a project from scratch or add Kinde to your existing codebase. Since we're adding Kinde to our Next.js app, I'll choose the latter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp9rw5w0948tvvyvv0lw3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp9rw5w0948tvvyvv0lw3.jpg" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To provide the right docs, Kinde will also ask about the tech you're using on your app. We're using Next.js, so just click that and continue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy65k3g85ullk2ecva31j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy65k3g85ullk2ecva31j.jpg" alt="Image description" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To complete the signup process, you need to choose the ways your users can be authenticated with Kinde. By default, Kinde provides email authentication, but you can add other authentication providers like Google or GitHub.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6eeul40i6i3tx5omb3du.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6eeul40i6i3tx5omb3du.jpg" alt="Image description" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the signup process is done, Kinde will lay out ways for you to integrate it into your app with their guides. You can just click on the connect to Next.js codebase option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffpt56m50xydvre0btp72.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffpt56m50xydvre0btp72.jpg" alt="Image description" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be redirected to a quick start guide for adding Kinde to your existing Next.js project. Scroll down and copy the npm or yarn installation command to install the Kinde Next.js SDK as a dependency. Also, copy the environment variables provided by Kinde into a .env.local file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i @kinde-oss/kinde-auth-nextjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvipba05w2uzn7zq796t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvipba05w2uzn7zq796t.jpg" alt="Image description" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We're almost done, the last thing you need to do is to create an api folder in your app directory, add an auth folder within it, within the auth folder a dynamic segment that looks like this [kindeauth], add a route.js file to it, and finally copy this inside of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {handleAuth} from "@kinde-oss/kinde-auth-nextjs/server";
export const GET = handleAuth();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎉You're done! You've successfully added authentication using Kinde to your Next14 app.&lt;/p&gt;

&lt;p&gt;To start your auth flow in your app, you use the LoginLink and RegisterLink components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {RegisterLink, LoginLink} from "@kinde-oss/kinde-auth-nextjs/components";
&amp;lt;LoginLink&amp;gt;Sign in&amp;lt;/LoginLink&amp;gt;
&amp;lt;RegisterLink&amp;gt;Sign up&amp;lt;/RegisterLink&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔥Happy coding!&lt;/p&gt;

&lt;p&gt;You hear more from me on:&lt;br&gt;
&lt;a href="https://x.com/code_withjoseph"&gt;X&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kinde</category>
      <category>nextjs</category>
      <category>authentication</category>
      <category>react</category>
    </item>
    <item>
      <title>How to host your Next14 app on Netlify in 2 minutes</title>
      <dc:creator>Code With Joseph</dc:creator>
      <pubDate>Fri, 31 May 2024 02:03:09 +0000</pubDate>
      <link>https://dev.to/joeskills/how-to-host-your-next14-app-on-netlify-in-2-minutes-566f</link>
      <guid>https://dev.to/joeskills/how-to-host-your-next14-app-on-netlify-in-2-minutes-566f</guid>
      <description>&lt;p&gt;To follow this tutorial, you need to create a Netlify account and sign in to it, also the code for your Next app should be hosted on an online repository. I’m using GitHub to host the code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbdxoj4a7fzp0me8d0f1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbdxoj4a7fzp0me8d0f1.jpg" alt="Image description" width="800" height="399"&gt;&lt;/a&gt; &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Add a new site🔗:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You will be taken to your Netlify dashboard after you log in. After you click on the add new site button. It will bring up a popup menu, choose the 'import an existing project' option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrk9r1syyz4t2nzul89j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgrk9r1syyz4t2nzul89j.jpg" alt="Image description" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Choose your code repository platform👨‍💻:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Click on the platform of your choice and grant Netlify access to it. I'll choose GitHub because I'm using it to host my code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzx9e1okw05q7q0x0vc2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzx9e1okw05q7q0x0vc2.jpg" alt="Image description" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Pick the repository of your Next.js app👩🏻‍💻:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After choosing a platform, Netlify will show you a list of repositories hosted on your platform. Pick the repository that contains the Next14 app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqckz9hfz9ie471cw1oqp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqckz9hfz9ie471cw1oqp.jpg" alt="Image description" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Choose the correct branch &amp;amp; build settings⚙️:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Netlify automatically infers if you're using Next.js, the build settings will allow your app to run normally, but you'll also be able to customize your site name, build command, the base directory, and your publish directory here. This is where you can also add your environment variables. If you're using a different branch other than the default main branch, you can switch to it with the select menu. Once you're done, click on deploy 'site name' at the bottom.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxtsw66s66oy45l88tw2p.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxtsw66s66oy45l88tw2p.jpg" alt="Image description" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;You Next14 app is now live⚡&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Your site is live! If there were no build errors, all you have to do is wait for Netlify to deploy your site. Once it's done deploying, it'll provide a domain name for you that you can use to visit your site. You might need to reload the page if you're being shown 'site in progress' for a long time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1k42vhwg6nnfjrbfkow.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1k42vhwg6nnfjrbfkow.jpg" alt="Image description" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Happy Coding! &lt;br&gt;
You can hear more from me on:&lt;br&gt;
𝕏 - &lt;a href="https://x.com/code_withjoseph"&gt;https://x.com/code_withjoseph&lt;/a&gt;&lt;/p&gt;

</description>
      <category>netlify</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>howto</category>
    </item>
  </channel>
</rss>
