<?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: Antoine Mincy</title>
    <description>The latest articles on DEV Community by Antoine Mincy (@simplymincy).</description>
    <link>https://dev.to/simplymincy</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%2F254290%2F0a34a2ea-d014-4584-9399-fff0ceeb0471.jpg</url>
      <title>DEV Community: Antoine Mincy</title>
      <link>https://dev.to/simplymincy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/simplymincy"/>
    <language>en</language>
    <item>
      <title>Hook Dev.to blogs to your react app</title>
      <dc:creator>Antoine Mincy</dc:creator>
      <pubDate>Wed, 13 Oct 2021 02:23:54 +0000</pubDate>
      <link>https://dev.to/simplymincy/connect-devto-blogs-to-your-react-app-3bk3</link>
      <guid>https://dev.to/simplymincy/connect-devto-blogs-to-your-react-app-3bk3</guid>
      <description>&lt;p&gt;So, I love the Dev.to community and more so I love how easy it is to create a blog. So, I was looking for a way to have my blogs that I publish on here go straight to my personal site. Thankfully, this was pretty easy due to dev's &lt;a href="https://developers.forem.com/api"&gt;api&lt;/a&gt; and a couple react hooks. Here is how I implemented mine on my &lt;a href="//www.simplymincy.info"&gt;personal site&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contents
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Direct to a specific blog article&lt;/li&gt;
&lt;li&gt;List your blog articles on a page&lt;/li&gt;
&lt;li&gt;Dynamically go to a blog article from a list&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;In a rush? Here is the &lt;a href="https://github.com/ajmincy/devBlogToReact"&gt;Github Repo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the sake of time I am going to make a few assumptions here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You are familiar with React and React Hooks&lt;br&gt;
You have a basic understanding of an API&lt;br&gt;
You have at least one published article on Dev.to&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. Direct to a specific blog article
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8NSdjtSj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u677gxd16j8akakr4gty.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8NSdjtSj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u677gxd16j8akakr4gty.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's start with creating a basic react app:  &lt;code&gt;npx create-react-app dev-blog&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Once the app is done installing let's do our usual boilerplate clean up of the &lt;code&gt;App.js&lt;/code&gt; file. Here is mine:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function App() {

    return (
        &amp;lt;div&amp;gt;
            Dev Blog
        &amp;lt;/div&amp;gt;
    );
}

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

&lt;/div&gt;
&lt;p&gt;Now let's take a look at the api docs &lt;a href="https://developers.forem.com/api"&gt;here&lt;/a&gt;. While their api is still in beta, as you can see there are several ways you can retrieve data from the site. As you explore different paths and responses you may come across a few that are not correct or not returning but I have yet to come across one and overall am pretty pleased with their work. &lt;/p&gt;

&lt;p&gt;The path I recommend is under &lt;code&gt;articles&lt;/code&gt; and named the &lt;em&gt;A published article by path&lt;/em&gt; &lt;a href="https://developers.forem.com/api#operation/getArticleByPath"&gt;&lt;code&gt;GET&lt;/code&gt; &lt;/a&gt; call. Let's add a constant named blogPath to our code and we want to set that const to &lt;code&gt;https://dev.to/api/articles/{Your UserName}/{Your Article ID}&lt;/code&gt; Simply navigate to a blog post you want show to get that Article ID. Here is mine. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function App() {
const blogPath = 'https://dev.to/api/articles/simplymincy/test-post-2-2j8a`';
    return (
        &amp;lt;div&amp;gt;
            Dev Blog
        &amp;lt;/div&amp;gt;
    );
}

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

&lt;/div&gt;
&lt;p&gt;The next thing we want to do is make a call with that const to get the response body. To do this we can use &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt; and a package commonly used with react called &lt;code&gt;axios&lt;/code&gt;, which will be used to make our http requests.  Let's go ahead and install that package &lt;code&gt;npm i axios&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;After that installs let's use the useState hook and set it to be our article Body response.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from  "react";
import axios from  "axios";

function App() {
const blogPath = 'https://dev.to/api/articles/simplymincy/test-post-2-2j8a`';
const [articleBody, setArticleBody] = useState();

    return (
        &amp;lt;div&amp;gt;
            Dev Blog
        &amp;lt;/div&amp;gt;
    );
}

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

&lt;/div&gt;
&lt;p&gt;To actually get that response we will need to now use useEffect and axios to make that call using the blogPath we created. It should look something like I have below with us checking for the response.data and setting that to our setArticleBody. Be sure to set a dependency here in your useEffect or this call will continuously run in the background. We only want this to update if there is a page load so we can set it dependent to the blogPath.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Axios makes it really easy to make requests. Feel free to check out their &lt;a href="https://axios-http.com/docs/intro"&gt;docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from  "react";
import axios from  "axios";

function App() {
const blogPath = 'https://dev.to/api/articles/simplymincy/test-post-2-2j8a`';

const [articleBody, setArticleBody] = useState();

    useEffect(() =&amp;gt; {
        axios.get(blogPath).then((response) =&amp;gt; {
            setArticleBody(response.data);
        });
    }, [blogPath]);

    return (
        &amp;lt;div&amp;gt;
            Dev Blog
        &amp;lt;/div&amp;gt;
    );
}

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

&lt;/div&gt;
&lt;p&gt;Now at this point you would think we could replace the contents in the return with one of the properties we are getting in our response. I mean for sure "&lt;em&gt;body_html&lt;/em&gt;" property should work right? Just use that and place that in the return. I am sure you know the problem with trying that but if you don't it is because that return is not real &lt;code&gt;HTML&lt;/code&gt;. It is &lt;code&gt;jsx&lt;/code&gt;. So, it will not do any formatting. So, instead let's go with the "&lt;em&gt;body_markdown&lt;/em&gt;" property instead and to get the markdown formatting to show up correctly on our page we are going to use another package &lt;code&gt;react-markdown&lt;/code&gt;. This package converts your markdown code into code &lt;code&gt;jsx&lt;/code&gt; can understand and displays it properly. So, let's install that package and make those updates shall we:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function App() {
const blogPath = 'https://dev.to/api/articles/simplymincy/test-post-2-2j8a`';

const [articleBody, setArticleBody] = useState();

    useEffect(() =&amp;gt; {
        axios.get(blogPath).then((response) =&amp;gt; {
            setArticleBody(response.data);
        });
    }, [blogPath]);

    if (!articleBody) return  null;

    const markdown = articleBody.body_markdown;

    return (
        &amp;lt;div&amp;gt;
            &amp;lt;ReactMarkdown&amp;gt;{markdown}&amp;lt;/ReactMarkdown&amp;gt;
        &amp;lt;/div&amp;gt;
    );
}

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

&lt;/div&gt;
&lt;p&gt;I've also added a simple check on the body response to see if it exists and to return null if it doesn't. That way our app will not crash if that path no longer exists.&lt;/p&gt;

&lt;p&gt;At this point you should be able to see the page loaded with your article. This is pretty basic but we can do some more dynamic things with this api.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. List a collection of articles on a page
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sarDbH-X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67jyvmfu34bz7ahne7u9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sarDbH-X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67jyvmfu34bz7ahne7u9.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, first thing we want to do here is make a new component. Let's call it &lt;code&gt;Article.js&lt;/code&gt; because this is where we will return... well our articles. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const Article = () =&amp;gt; {
        return ();
 };

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

&lt;/div&gt;
&lt;p&gt;And since we did all that work already in our &lt;code&gt;App.js&lt;/code&gt; file. Let's just move that over to this &lt;code&gt;Article.js&lt;/code&gt; file. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from  "react";
import axios from  "axios";
import ReactMarkdown from  "react-markdown";

const Article = () =&amp;gt; {

const blogPath = `https://dev.to/api/articles/simplymincy/test-post-2-2j8a`;
const [articleBody, setArticleBody] = useState();

    useEffect(() =&amp;gt; {
        axios.get(blogPath).then((response) =&amp;gt; {
            setArticleBody(response.data);
        });  
    }, [blogPath]);

    if (!articleBody) return  null;

const markdown = articleBody.body_markdown;

    return (  
        &amp;lt;div&amp;gt; Dev Blog
            &amp;lt;ReactMarkdown&amp;gt;{markdown}&amp;lt;/ReactMarkdown&amp;gt;
        &amp;lt;/div&amp;gt;
    );
};

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

&lt;/div&gt;
&lt;p&gt;Our &lt;code&gt;App.js&lt;/code&gt; should be empty now and look like this:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from  "react";

function App() {

return (
&amp;lt;div&amp;gt;
Empty App
&amp;lt;/div&amp;gt;

);

}

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

&lt;/div&gt;
&lt;p&gt;Before we do anything else to that file let's create our collection component &lt;code&gt;Collection.js&lt;/code&gt; with some of the same imports as before:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from  "react";
import axios from  "axios";

const Collection = () =&amp;gt; {

return ();    
};
export  default Collection;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;And we want to retrieve the data similar to how we did with the Article component but we want to use this url &lt;code&gt;https://dev.to/api/articles?username={Your UserName}&lt;/code&gt; to get the collection of articles instead.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from  "react";
import axios from  "axios";

const Collection = () =&amp;gt; {
    const collectionPath = `https://dev.to/api/articles?username=simplymincy`;
    const [articleCollection, setArticleCollection] = useState();

    useEffect(() =&amp;gt; {
        axios.get(collectionPath).then((response) =&amp;gt; {
            setArticleCollection(response.data);
        });
    }, [collectionPath]);

    if (!articleCollection) return  null;

    return  &amp;lt;div&amp;gt;Dev Collection&amp;lt;/div&amp;gt;;
};

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

&lt;/div&gt;
&lt;p&gt;Since we will be getting an array of data we will use the &lt;code&gt;map()&lt;/code&gt; method to display every element. It should look something like I have below where we are taking that &lt;code&gt;articleCollection&lt;/code&gt; and spitting out every &lt;code&gt;article&lt;/code&gt; (You can name that whatever you like) based on its &lt;code&gt;id&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const list = articleCollection.map((article) =&amp;gt; (

    &amp;lt;div  key={article.id}&amp;gt;
        Data we want to display here
    &amp;lt;/div&amp;gt;
));
    return (
        &amp;lt;div&amp;gt;Dev Collection
            {list}
        &amp;lt;/div&amp;gt;
    );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;I also want to display an image and the title of the article so I will add a couple more but feel free to add whatever you like here based off the api.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from  "react";
import axios from  "axios";

const Collection = () =&amp;gt; {
    const collectionPath = `https://dev.to/api/articles?username=simplymincy`;
    const [articleCollection, setArticleCollection] = useState();

        useEffect(() =&amp;gt; {
            axios.get(collectionPath).then((response) =&amp;gt; {
                setArticleCollection(response.data);
            });
        }, [collectionPath]);

    if (!articleCollection) return  null;
    const list = articleCollection.map((article) =&amp;gt; (

        &amp;lt;div  key={article.id}&amp;gt;
            &amp;lt;div&amp;gt;
                &amp;lt;div&amp;gt;
                    &amp;lt;img  src={article.social_image}  alt="Article Images"  /&amp;gt;
                &amp;lt;/div&amp;gt;
                    &amp;lt;div&amp;gt;
                        &amp;lt;h4&amp;gt;{article.title}&amp;lt;/h4&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        ));

    return (

        &amp;lt;div&amp;gt;
            Dev Collection
            {list}
        &amp;lt;/div&amp;gt;
    );
};

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

&lt;/div&gt;
&lt;p&gt;Let's now import the Collection component in our &lt;code&gt;App.js&lt;/code&gt; file&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from  "react";
import Collection from  "./Collection";

function App() {

    return (
        &amp;lt;React.Fragment&amp;gt;
            &amp;lt;Collection/&amp;gt;
        &amp;lt;/React.Fragment&amp;gt;
    );
}

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

&lt;/div&gt;
&lt;p&gt;We should now see a collection of our published articles on our page. Now the last thing we want to do (besides adding some css to have it more appeasing on our eyes) is have each article clickable and navigate to that particular article onClick. Let's do that now. &lt;/p&gt;
&lt;h2&gt;
  
  
  3. Navigate to a blog article from a list
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1qmQ07s9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/snuf968mhn0ua2u3qq3v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1qmQ07s9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/snuf968mhn0ua2u3qq3v.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this we are going to use another common package that is used with React and that is &lt;code&gt;react-router-dom&lt;/code&gt;. So, let's install that and before we get the &lt;code&gt;Collection&lt;/code&gt; component ready to have a clickable element we need to go to our &lt;code&gt;App.js&lt;/code&gt; file and make a few changes. Right now our app is a single page app. Being that we will at the very least now have 2 pages we can now navigate, we need to set up some routes. This is a decent enough change so for this one I am going to show the fully updated &lt;code&gt;App.js&lt;/code&gt; file and then explain.&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 from "react";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import Article from "./Article";
import Collection from "./Collection";

function App() {
  return (
    &amp;lt;React.Fragment&amp;gt;
      &amp;lt;BrowserRouter basename={"/"}&amp;gt;
        &amp;lt;Switch&amp;gt;
          &amp;lt;Route
            exact
            path={`${process.env.PUBLIC_URL}/`}
            component={Collection}
          /&amp;gt;
          &amp;lt;Route
            exact
            path={`${process.env.PUBLIC_URL}/Article/simplymincy/:path`}
            component={Article}
          /&amp;gt;
        &amp;lt;/Switch&amp;gt;
      &amp;lt;/BrowserRouter&amp;gt;
    &amp;lt;/React.Fragment&amp;gt;
  );
}

export default App;

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

&lt;/div&gt;



&lt;p&gt;I am now using the &lt;code&gt;react-router-dom&lt;/code&gt; package in our most top level component because I want to set up the different routes I spoke of before. Hence why we are using the &lt;code&gt;BrowserRouter&lt;/code&gt;, &lt;code&gt;Switch&lt;/code&gt;, and &lt;code&gt;Route&lt;/code&gt; methods. The &lt;code&gt;BrowserRouter&lt;/code&gt; tag is used to push, replace, and pop the various return states we will now have in our app. Inside of that we set a &lt;code&gt;Switch&lt;/code&gt; tag which works very similiar to a switch statement meaning that it returns the first child it has that matches a location and as you can see we have 2 &lt;code&gt;Route&lt;/code&gt; tags. There are a lot of properties you can set for these and I highly recommend looking over the docs &lt;a href="https://reactrouter.com/web/guides/quick-start"&gt;here&lt;/a&gt;, but for my example I am checking for an exact match on the path property and I am setting the components to the 2 components we created earlier. Looking closer you will see that I have the &lt;code&gt;Collection&lt;/code&gt; component set as my base url and the route with the &lt;code&gt;Article&lt;/code&gt; component with a more unique path. The &lt;code&gt;/Article/simplymincy/&lt;/code&gt; was simply what I chose here but you can have your path be anything as long as it is unique. &lt;/p&gt;

&lt;p&gt;Last thing, I want to point out here is the &lt;code&gt;:path&lt;/code&gt; piece you see in that url. We use this here so that when we do eventually click on a link in our &lt;code&gt;Collection&lt;/code&gt; component we will pass it some parameters. We do that by importing &lt;code&gt;react-router-dom&lt;/code&gt; to our component and using the &lt;code&gt;Link&lt;/code&gt; method. Think of this as an &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag. Here is the updated file now:&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, { useEffect, useState } from  "react";
    import axios from  "axios";
    import { Link } from  "react-router-dom";

    const Collection = () =&amp;gt; {
        const collectionPath = `https://dev.to/api/articles?username=simplymincy`;

        const [articleCollection, setArticleCollection] = useState();

        useEffect(() =&amp;gt; {

            axios.get(collectionPath).then((response) =&amp;gt; {
                setArticleCollection(response.data);
            });
        }, [collectionPath]);

        if (!articleCollection) return  null;

        const list = articleCollection.map((article) =&amp;gt; (

            &amp;lt;div  key={article.id}&amp;gt;
                &amp;lt;div&amp;gt;
                    &amp;lt;div&amp;gt;
                        &amp;lt;img  src={article.social_image}  alt="Article Images"  /&amp;gt;
                    &amp;lt;/div&amp;gt;
                    &amp;lt;div&amp;gt;
                        &amp;lt;h4&amp;gt;{article.title}&amp;lt;/h4&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div&amp;gt;
                    &amp;lt;Link  to={`/Article/simplymincy/${article.slug}`}&amp;gt;Read&amp;lt;/Link&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        ));

    return (

        &amp;lt;div&amp;gt;

            Dev Collection
                {list}
        &amp;lt;/div&amp;gt;
        );
    };

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

&lt;/div&gt;



&lt;p&gt;As you will notice in the &lt;code&gt;Link&lt;/code&gt; tag we are using the same url that we set in the Article route in the &lt;code&gt;App.js&lt;/code&gt; file. That is key, because remember we are using exact match here. If they do not match it will not return our &lt;code&gt;Article&lt;/code&gt; component. Which leads us to our last step. Remember when we set the &lt;code&gt;:path&lt;/code&gt; in our &lt;code&gt;Article&lt;/code&gt; route well we did that so we can set some value and pass it through our components freely. In this case we are going to use a value we get from our api call, which is &lt;code&gt;slug&lt;/code&gt;. This by the definition of the dev.to api is used to uniquely identify the articles users create. This is not only perfect to have our urls be unique but also will be able to get passed through so our &lt;code&gt;Article&lt;/code&gt; component can make a direct call on that path to gets its blog content. This update is rather small. We just want to &lt;code&gt;import { useParams } from  "react-router-dom";&lt;/code&gt; and then replace our blogPath const with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const params = useParams();
    const blogPath = `https://dev.to/api/articles/simplymincy/${params.path}`;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we are doing here is passing in the parameters from the link we clicked on in the Collection component and we will set that slug to be the end of our blogPath. That way no matter what article we click on, it will know which one to retrieve its content for and display.&lt;/p&gt;

&lt;p&gt;AND THATS IT! &lt;/p&gt;

&lt;p&gt;At this point you should have all of your articles in a collection displaying and be able to click and display each article dynamically. With the API you can do a lot more such as GET and POST comments, likes, and other useful stats pertaining to your blog. I did not add any styling in here either. I leave that up to you. Here is an example of how I implemented mine.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;From my personal site&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OkbrrIGR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/94v9u8z5c8ch1f9chs2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OkbrrIGR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/94v9u8z5c8ch1f9chs2b.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Refactr.Tech (2021)</title>
      <dc:creator>Antoine Mincy</dc:creator>
      <pubDate>Tue, 31 Aug 2021 20:13:03 +0000</pubDate>
      <link>https://dev.to/simplymincy/test-post-2-2j8a</link>
      <guid>https://dev.to/simplymincy/test-post-2-2j8a</guid>
      <description>&lt;p&gt;It is only fitting that my first blog is about this conference. Even though I have been in the tech field for close to 10 years now, Refactr was the first conference I ever attended in 2019. It was also the first one they ever held. The focus on inclusion and diversity was a major factor, due to me struggling with finding my voice in the tech industry. That was not the only plus. There were several different speakers and paths like many conferences I imagine but seeing myself in so many people and hearing their wins and struggles made me feel seen. I learned so much about the pain points in our industry and was motivated to do my part to help not only my organization do better in these areas but our industry as a whole. Our QA department benefited greatly as well. We took the cypress.io workshop and got a solid foundation that we are still building on today. Moving our testing efforts from 100% manual testing to 90% automation and 10% discovery testing.&lt;/p&gt;

&lt;p&gt;The first question you may be asking is " was Refactr.tech conference 2021 just as great?" Well, no. &lt;em&gt;BUT&lt;/em&gt; that is not the fault of the organizers. Considering we are still in a pandemic, this year was virtual and therefore a lot of the value I got from in person networking was gone. Having said that, I still enjoyed the conference and have thoughts on a few of the topics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 1
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Growing in our Careers
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Speaker Lara Hogan
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0Wab2D4f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x7n6ud16b7h1okiutdr4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0Wab2D4f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x7n6ud16b7h1okiutdr4.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The focus of this talk was all the things you should look for in a mentor or if you are the one doing the mentoring, a mentee. It was gathered from an AWS &lt;a href="https://aws.amazon.com/blogs/startups/how-to-use-mentorship-for-startup-success/"&gt;article&lt;/a&gt; and for the most part there was nothing new here. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure the relationship is beneficial to both parties &lt;/li&gt;
&lt;li&gt;look for a mentor with a good work life balance &lt;/li&gt;
&lt;li&gt;do not be afraid to walk away if it is not beneficial &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;you know the usual stuff you hear when it comes to mentor advice. The one thing that did catch my attention however, was the idea of &lt;strong&gt;Sponsorships&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Now up until this point I always thought of sponsorships as a synonym for mentor, but Lara says that is not the case. A sponsor is someone who is not just telling a person what they should be doing but actively advocating for that person. This means if that mentor of yours is at your job, they are looking for opportunities for you to grow and they are advertising your name as a person people should consider to do a job. Lara emphasized the power of sponsorship over just mentoring. Especially in marginalized groups. She stated that marginalized people are over-mentored and &lt;strong&gt;UNDER&lt;/strong&gt; sponsored. For someone like me who struggled finding a place in the tech space early in my career, I can totally relate to that statement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where to start with AWS as a Developer
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Speaker Sam Julien &lt;a href="https://twitter.com/samjulien"&gt;@samjulien&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pjr7vPmP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/walldqafcce18bdrrxjo.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pjr7vPmP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/walldqafcce18bdrrxjo.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was the second topic that caught my attention during day 1 of the conference. Our company relies heavily on AWS and besides the simple tasks I do day to day when connecting to our server, I am total noob. So, when Sam started to talk about what it takes to learn AWS I was all ears. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cloud is a way to virtualize your network infrastructure. When thinking about vertical or horizontal scaling of your business, the cloud solution helps with the capital vs. operating expenses problem, by providing a service that handles that for a fraction of the costs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After going over the basics, Sam went over some key services developers should get familiar with such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2&lt;/li&gt;
&lt;li&gt;Lamda&lt;/li&gt;
&lt;li&gt;S3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;He also mentioned some pitfalls to watch out for while learning AWS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pay attention to your billing. You are billed each month so if you are not on top of things you may be surprised by that end of the month bill. To combat this, clean up your resources after working or setting them up. Do not just leave them up while you are simply learning the tools.&lt;/li&gt;
&lt;li&gt;Use labs and the free tier&lt;/li&gt;
&lt;li&gt;Set up billing alarms. This is good not just for learning but in general. Let's say you have an app/site out in production and you know your average traffic rate per month and adjust your billing to handle that expense. Well, all it takes is one viral moment or a confusion in url to make that site much more popular than you intended. Billing alarms are a good way to stay on top of those moments.&lt;/li&gt;
&lt;li&gt;Identify and Access Management. Use the principle of least privilege. In other words, only give access to the people that need it and make sure their levels of access is proportionate to their needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lastly, he went over the certification paths depending on the job you may want to take in the future. He also mentioned you do not need these certifications to apply for jobs, but are great if you are looking for a deep understanding of cloud services and tooling in a given area such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cloud Practitioner exam &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Practitioner&lt;/strong&gt; - &lt;em&gt;Supervising the architecting and deployment of applications within AWS platforms.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Associate Exams&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solutions arch&lt;/strong&gt; - &lt;em&gt;responsible for evaluating an organization's business needs and determining how IT can support those needs leveraging software&lt;/em&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SysOps Admin&lt;/strong&gt; - &lt;em&gt;responsible for providing the necessary knowledge related to the working of cloud computing, IT and business applications to improve service delivery&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer&lt;/strong&gt; - &lt;em&gt;create applications that are served on the cloud&lt;/em&gt;

&lt;ol&gt;
&lt;li&gt;Profesional Exams&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solutions arch&lt;/strong&gt;  - &lt;em&gt;Same as it was with the associate exam but you should have a deeper understanding at this point&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DevOps Engineer&lt;/strong&gt; - &lt;em&gt;A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Day 2
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Moving beyond Performative Racial Equity in Tech
&lt;/h3&gt;

&lt;h5&gt;
  
  
  &lt;em&gt;a conversation with&lt;/em&gt;
&lt;/h5&gt;

&lt;h4&gt;
  
  
  Albrey Bristo-Brown &amp;amp; Nicole Sanchez
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t5osaf8_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mth5x7qyjql0jr7q74ks.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t5osaf8_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mth5x7qyjql0jr7q74ks.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was not the typical powerpoint presentation. This was more a conversation between the two presenters. If you have worked in a tech company in the past couple years, you might be familiar with this format. This is a pattern many diversity training companies take, as they want to not come off as preaching to a group and have the topic be more approachable.&lt;/p&gt;

&lt;p&gt;The business is now in high demand according to Nicole, she has been doing this for decades and there was a big difference in 2020. She is doing many more talks than before and states part of that is because white America was not listening before but now they are. She then stated right after that it is because people of color are speaking up more and not afraid of any of the repercussions that might come from it. The engagement is actually there and we are no longer waiting on the sideline for action to happen. There &lt;em&gt;seemed&lt;/em&gt; to be a sense of urgency after the George Floyd video. This is when the conversation got interesting. They then break down how much of that was genuine. &lt;/p&gt;

&lt;p&gt;The stat they threw out was 3.8 billion went towards helping black equity over that time but only 7% went towards education. Often companies made a one time commitment by donating money but this was more of a thing companies did to not be singled out for not doing anything. Those donations were often hollow without any follow up actions to do their part in battling racial inequalities. This is where the term Performative Racial Equity comes to play. I kind of wish I had this term in my vocabulary last year, because I remember telling my team that very thing when they were all trying to figure out what to do to make a statement that they too supported BLM after the George Floyd video. You see I am 1 of 3 black people in the company, and I believe the only black engineer. Yet, it was not until I saw the company trying really hard to make a statement in support of BLM when it was now convenient to do so, that I felt disgusted by my companies lack of proactive support before:&lt;/p&gt;

&lt;p&gt;So what do we do. Albrey and Nicole talked about a few solutions. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Donate your time and not just your money. &lt;/li&gt;
&lt;li&gt;Be sure to have open and honest dialogue with your employees. &lt;/li&gt;
&lt;li&gt;When it comes to building a working environment where minorities and underrepresented people feel comfortable expressing themselves, do not have too many managers passed around. It is hard to establish a relationship of trust and more so a connection where that manager will take action, if they are constantly being moved around. &lt;/li&gt;
&lt;li&gt;The last solution I found the most revealing. They stated that black women are usually the ones with the most hurdles they must overcome in not only the tech space, but any space in general. So, if a company can help solve the issues black women are having in the company then usually that helps with a lot of the other problems in the organizations with your underrepresented groups.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Day 3
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Career Progression
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Speaker Mekka Okereke
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uXCdcDst--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uloxvp7xdyyjz13rj8mt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uXCdcDst--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uloxvp7xdyyjz13rj8mt.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following notes I got from my coworker Alex since I was out on day 3 but based on these notes I really wish I was there to hear the talk Mekka gave. As a person who has thrived in the scrum team dynamic his presentation clearly put some things in the forefront of my mind. He states in order to progress in your career you have to do these 4 things:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt; Skills. To perform at the next level&lt;/li&gt;
&lt;li&gt;Opportunity. To demonstrate those skills&lt;/li&gt;
&lt;li&gt;Perform. Put it all together&lt;/li&gt;
&lt;li&gt;Be Recognized. Most important&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nothing mind blowing here but number 4 is the one that struck me. When working in scrum the idea is that no &lt;em&gt;one&lt;/em&gt; person owns a ticket/task. It is the responsibility of the team to get tickets done. There are a lot of pros to that if you are doing proper pairing and swarming. For example, context of the ticket is shared amongst the team and you do not have to waste time getting others up to speed when it comes to code reviews and testing, others are able to fill in gaps of knowledge and cover technical blindspots you may or may not be aware of and generally the team is able to get the most important tickets done faster, but to Mekka's point, a con  is that your actual contributions may get lost in all that shuffle.  &lt;/p&gt;

&lt;p&gt;He mentions that people need to see that you've done the work and that you are able to put it all together yourself. Just because you do good work, it does not mean you will automatically get recognized. Worse case scenario, if you do not advocate for yourself and your work, your work could be undervalued. &lt;/p&gt;

&lt;p&gt;This made me think to one of the retro items our team started to include in our sprint. We added in our team working agreement that we can assign tickets to individuals in Jira but we should look at that person as the one driving that ticket. Meaning work should not be done in a silo. Look to pair when you can on the work. Until reading over the notes on Mekka's speech, I always thought of that as counterintuitive to scrum. Just the idea of putting your name on a task felt anti-scrum, but in a profession such as tech where it is sometimes easy to get overlooked, it might just be the best compromise to being recognized as an individual while still working in a team setting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Topics and Thoughts
&lt;/h2&gt;

&lt;h4&gt;
  
  
  As I mentioned there was so much great content from the conference that I will not be able to go over here simply because I could go on and on about each topic and presenter. They do plan to update their youtube channel &lt;a href="https://www.youtube.com/channel/UCfBdXCYPCHEXX8ISwOQM08A"&gt;Refactr.tech&lt;/a&gt; with all of the content soon. So, I highly recommend you look out for the ones I did not mention in my highlights:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;MicroControllers (Tara Walker)&lt;/li&gt;
&lt;li&gt;Diabetes and technology (Diana Rodriguez)&lt;/li&gt;
&lt;li&gt;Effective testing approaches for your application (Cecelia Martinez)&lt;/li&gt;
&lt;li&gt;Fault Text: The adversities in automated alternative text (Henri Helvetica)&lt;/li&gt;
&lt;li&gt;Accessibility isn't Hard: Getting people to see it's easy can be (Sarrah Vesselov)&lt;/li&gt;
&lt;li&gt;ARIA: A grande method of accessible markup ( Chris Demars)&lt;/li&gt;
&lt;li&gt;Accessible Components (Homer Gaines)&lt;/li&gt;
&lt;li&gt;Shapeshifters (Sophia Prater)&lt;/li&gt;
&lt;li&gt;Gitforked (Chloe Condon)&lt;/li&gt;
&lt;li&gt;Keeping up with the Caldwells (Nick &amp;amp; Tia Caldwell)&lt;/li&gt;
&lt;li&gt;Data as a Weapon (Ayodele Odubela)&lt;/li&gt;
&lt;li&gt;7 secrets of highly successful developers (Kim Maida)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Before the virtual conference even began they held a virtual job fair free for anyone that had the link information. In there, you got to network with several top companies, recruiters and other job seekers. I was not interested in going myself but I told several friends and coworkers and they all talked about how much they enjoyed the experience.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Considering the circumstances they did an awesome job with this conference. Timing and presentations were well put together. There were great discussions after each presentation and the music was great during intermission. Seriously go check out their playlist: &lt;a href="https://open.spotify.com/playlist/6KAMh6nhenQIAuy6CSe8lI?si=b33f4ebbb7a94f41"&gt;90's Mixtape&lt;/a&gt; . Hopefully the next one is in person so we can all dance to it. &lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
