<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ create-react-app - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ create-react-app - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 17 May 2026 11:36:29 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/create-react-app/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Migrate from create-react-app to Vite using Jest and Browserslist ]]>
                </title>
                <description>
                    <![CDATA[ The React team no longer recommends using create-react-app (CRA) as a bundler to create a new React application. The team and community realized that even though CRA was a jump-starter, it lacked the flexibility needed to configure or manage large an... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-migrate-from-create-react-app-to-vite/</link>
                <guid isPermaLink="false">66bb8f98caaeb78feb348947</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ vite ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Saheed Oladele ]]>
                </dc:creator>
                <pubDate>Fri, 06 Oct 2023 18:01:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/pexels-tima-miroshnichenko-5380664.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The React team no longer recommends using <a target="_blank" href="https://github.com/facebook/create-react-app">create-react-app (CRA)</a> as a bundler to create a new React application. The team and community realized that even though CRA was a jump-starter, it lacked the flexibility needed to configure or manage large and complex applications.</p>
<p>Nowadays, the team recommends using <a target="_blank" href="https://react.dev/learn/start-a-new-react-project#production-grade-react-frameworks">production-grade React frameworks</a> like <a target="_blank" href="https://nextjs.org/">NextJS</a>, <a target="_blank" href="https://www.freecodecamp.org/news/p/b2e8aa42-17f7-486f-9fab-b47f9704248b/Remix">Remix</a>, <a target="_blank" href="https://www.gatsbyjs.com/">Gatsby</a>, or <a target="_blank" href="https://expo.dev/">Expo</a> for native apps. While frameworks are the preferred choice, the React team also recommend using <a target="_blank" href="https://vitejs.dev/">Vite</a> or <a target="_blank" href="https://parceljs.org/">Parcel</a> for custom build processes.</p>
<p>This is partly because the <a target="_blank" href="https://www.npmjs.com/package/create-react-app">CRA package has not been updated</a> for about a year. This may cause some problems where packages already updated to more recent versions cannot be used within an existing application. As a result, you may need to update existing applications by replacing the CRA package with the recommended alternatives — Vite or Parcel.</p>
<p>This article walks you through the steps for migrating a production-based application from CRA to Vite. You will learn the "why" of each step, how to retain <code>Jest</code> for tests, and how to update your <code>browserslist</code> since it doesn't work with <code>vite</code> out of the box.</p>
<p>In the conclusion section, you can find a sample pull request that includes all the changes. At the end of each step, you will find a sample commit text which shows the code change required per step.</p>
<h2 id="heading-step-1-install-vite-and-plugins">Step 1: Install <code>Vite</code> and Plugins</h2>
<p>Here are the commands to install the packages we need:</p>
<pre><code class="lang-bash">yarn add vite @vitejs/plugin-react vite-tsconfig-paths

OR

npm install vite @vitejs/plugin-react vite-tsconfig-paths
</code></pre>
<p>Apart from Vite, we are adding two plugins — <code>@vitejs/plugin-react</code> and  <code>vite-tsconfig-paths</code>.</p>
<p>The <code>vitejs/plugin-react</code> <a target="_blank" href="https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md#vitejsplugin-react-">plugin</a> enables fast refresh in development, uses automatic JSX runtime, and custom Babel plugins or presets. It enriches your React development experience.</p>
<p>The <code>vite-tsconfig-paths</code> <a target="_blank" href="https://github.com/aleclarson/vite-tsconfig-paths">plugin</a> resolves imports for TypeScript's path mapping. For example, you can use <code>components/ComponentName</code> instead of <code>./../components/ComponentName</code>.</p>
<h3 id="heading-other-vite-plugins">Other Vite plugins</h3>
<p>Another plugin you could consider is <code>vite-plugin-svgr</code>, which <a target="_blank" href="https://github.com/pd4d10/vite-plugin-svgr">transforms</a> SVG into React components and uses <a target="_blank" href="https://github.com/gregberge/svgr">svgr</a> under the hood. I left it out since we do not have such a use case in the application I’m migrating.</p>
<p>You can also checkout other official Vite plugins <a target="_blank" href="https://vitejs.dev/plugins/">here</a>.</p>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/2b37990690f7898117b1a0cb89e1118451bd24d9">Step 1 sample commit</a>.</p>
<h2 id="heading-step-2-create-a-vite-config-file">Step 2: Create a <code>Vite</code> config file</h2>
<p>On running <code>vite</code> in the command terminal, Vite tries to find a <code>vite.config.ts</code> file inside the project's root directory. You can read more on <a target="_blank" href="https://vitejs.dev/config/">Vite's page</a> for how to further configure this file for i<a target="_blank" href="https://vitejs.dev/config/#config-intellisense">ntellisense</a>, <a target="_blank" href="https://vitejs.dev/config/#conditional-config">environment based configurations</a>, <a target="_blank" href="https://vitejs.dev/config/#async-config">async configuration</a>, and <a target="_blank" href="https://vitejs.dev/config/#using-environment-variables-in-config">env variables usage</a>.</p>
<p>At your application’s root, create a file named <code>vite.config.ts</code> with the following content:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vite'</span>
<span class="hljs-keyword">import</span> react <span class="hljs-keyword">from</span> <span class="hljs-string">'@vitejs/plugin-react'</span>
<span class="hljs-keyword">import</span> viteTsconfigPaths <span class="hljs-keyword">from</span> <span class="hljs-string">'vite-tsconfig-paths'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
    <span class="hljs-comment">// depending on your application, base can also be "/"</span>
    <span class="hljs-attr">base</span>: <span class="hljs-string">''</span>,
    <span class="hljs-attr">plugins</span>: [react(), viteTsconfigPaths()],
    <span class="hljs-attr">server</span>: {    
        <span class="hljs-comment">// this ensures that the browser opens upon server start</span>
        <span class="hljs-attr">open</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-comment">// this sets a default port to 3000  </span>
        <span class="hljs-attr">port</span>: <span class="hljs-number">3000</span>, 
    },
})
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/557e8fbda9f8a19bf58ae0eeb1aa81e14111729a">Step 2 sample commit</a>.</p>
<h2 id="heading-step-3-create-a-vite-types-file-reference">Step 3: Create a <code>Vite</code> Types File Reference</h2>
<p>This step is needed to reference a type declarations file which aids type checks and Intellisense. By default, Vite types are for a NodeJS environment. For client side code, <a target="_blank" href="https://vitejs.dev/guide/env-and-mode.html#intellisense-for-typescript">Vite provides the type definitions</a> in <a target="_blank" href="https://github.com/vitejs/vite/blob/main/packages/vite/client.d.ts"><code>vite/client.d.ts</code></a>.</p>
<p>At your application’s root, create a file named <code>vite-env.d.ts</code> with the following content:</p>
<pre><code class="lang-js"><span class="hljs-comment">/// &lt;reference types="vite/client" /&gt;</span>
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/3002d2dbe1a421c0f31f57658ddde3030e898d1a">Step 3 sample commit</a>.</p>
<h2 id="heading-step-4-move-the-indexhtml-file">Step 4: Move the <code>index.html</code> File</h2>
<p>Vite has a <a target="_blank" href="https://vitejs.dev/guide/#index-html-and-project-root">root directory</a> which your files are served from. Since <code>index.html</code> is the entry point for Vite's server, the file needs to be in the root directory.</p>
<p>From the public directory, move the <code>index.html</code> file to the root of your project.</p>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/940f1f743fe6a380b157b86256aef7e29b2457a1">Step 4 sample commit</a>.</p>
<h2 id="heading-step-5-update-the-indexhtml-file">Step 5: Update the <code>index.html</code> File</h2>
<p>Two updates are necessary here:</p>
<h3 id="heading-remove-publicurl">Remove <code>%PUBLIC_URL%</code></h3>
<p>Vite <a target="_blank" href="https://vitejs.dev/guide/#index-html-and-project-root">automatically resolves</a> URLs inside <code>index.html</code>, so there's no need for <code>%PUBLIC_URL%</code> placeholders. You can do a search and replace inside your <code>index.html</code> file for this. Be sure to remove all occurrences.</p>
<p>Before:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"%PUBLIC_URL%/favicon.svg"</span> /&gt;</span>
</code></pre>
<p>After:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.svg"</span> /&gt;</span>
</code></pre>
<h3 id="heading-add-module-script-to-the-bottom-of-the-body-tag">Add module script to the bottom of the body tag</h3>
<p>Vite treats <code>index.html</code> <a target="_blank" href="https://vitejs.dev/guide/#index-html-and-project-root">as source code and part of the module graph</a>. It resolves <code>&lt;script type="module" src="..."&gt;</code> that references your JavaScript source code.</p>
<p>At the bottom of the body tag in <code>index.html</code> file, add the script as shown below:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    {/* others here */}
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/src/index.tsx"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/406b9765c5c166a0bafff6332f8a908156b794c4">Step 5 sample commit</a>.</p>
<h2 id="heading-step-6-replace-cra-with-vite">Step 6: Replace CRA with <code>Vite</code></h2>
<p>You can now remove CRA, add <code>Vite</code> scripts to the <code>package.json</code> file, and update <code>tsconfig.json</code>.</p>
<h3 id="heading-remove-cra">Remove CRA</h3>
<p>To remove CRA, run the following command. This will remove <code>react-scripts</code> from our installed packages.</p>
<pre><code class="lang-bash">yarn remove react-scripts

OR

npm uninstall react-scripts
</code></pre>
<p>After running the command above, delete the <code>react-app-env.d.ts</code> file.</p>
<h3 id="heading-add-vite-scripts-to-the-packagejson-file">Add Vite scripts to the <code>package.json</code> file</h3>
<p>With Vite installed, you can use the <code>vite</code> binary in your scripts. This could mean replacing <code>react-scripts</code> in a few places. Your focus should be on the <code>start</code> and <code>build</code> keys. The <code>preview</code> key is an addition which helps to preview production build locally.</p>
<p>Note that <code>start</code> is <code>vite</code> and not <code>vite start</code>.</p>
<pre><code class="lang-javascript">{  
  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"start"</span>: <span class="hljs-string">"vite"</span>, <span class="hljs-comment">// start dev server</span>
    <span class="hljs-string">"build"</span>: <span class="hljs-string">"tsc &amp;&amp; vite build"</span>, <span class="hljs-comment">// build for production</span>
    <span class="hljs-string">"preview"</span>: <span class="hljs-string">"vite preview"</span> <span class="hljs-comment">// locally preview production build</span>
  }
},
</code></pre>
<h3 id="heading-update-tsconfigjson">Update <code>tsconfig.json</code></h3>
<p>Here, your focus should be on the <code>isolatedModules</code>, <code>lib</code>, <code>target</code>, and <code>types</code>. For more options, here is a <a target="_blank" href="https://github.com/vitejs/create-vite-app/blob/master/template-react-ts/tsconfig.json">sample tsconfig file from Vite</a>.</p>
<pre><code class="lang-javascript">{  
    <span class="hljs-string">"compilerOptions"</span>: {    
        <span class="hljs-string">"lib"</span>: [<span class="hljs-string">"dom"</span>, <span class="hljs-string">"dom.iterable"</span>, <span class="hljs-string">"esnext"</span>],    
        <span class="hljs-string">"target"</span>: <span class="hljs-string">"ESNext"</span>,    
        <span class="hljs-string">"types"</span>: [<span class="hljs-string">"vite/client"</span>],
        <span class="hljs-string">"isolatedModules"</span>: <span class="hljs-literal">true</span>,
    },
 }
</code></pre>
<h3 id="heading-update-processenvreactappvariable-optional">Update <code>process.env.REACT_APP_VARIABLE</code> (optional)</h3>
<p>This is necessary if your application uses environment variable. Vite uses <code>import.meta.env.REACT_APP_VARIABLE</code> instead of <code>process.env.REACT_APP_VARIABLE</code>. You can find more details on <a target="_blank" href="https://vitejs.dev/guide/env-and-mode.html">Vite's env variables and modes here</a>.</p>
<p>Before:</p>
<pre><code class="lang-javascript">process.env.REACT_APP_VARIABLE
</code></pre>
<p>After:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span>.meta.env.REACT_APP_VARIABLE
</code></pre>
<h3 id="heading-replace-react-with-vite-optional">Replace <code>REACT_</code> with <code>VITE_</code> (optional)</h3>
<p>You only need this if you updated <code>process.env</code> above. Replace your <code>REACT_</code> environment variables to start with <code>VITE_</code>. This is needed because Vite filters out any env variable not starting with <code>VITE_</code>.</p>
<p>Before:</p>
<pre><code class="lang-javascript">REACT_APP_API_BASE
</code></pre>
<p>After:</p>
<pre><code class="lang-javascript">VITE_APP_API_BASE
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/775b3e841f107c2116e46d2a94b3ca9e697561e9">Step 6 sample commit</a>.</p>
<h2 id="heading-step-7-run-your-application">Step 7: Run your Application</h2>
<pre><code class="lang-bash">yarn start

OR

npm start
</code></pre>
<p>Congratulations! You have successfully completed the first step in migrating your application from CRA to Vite. You should see a screen that looks like the image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Screenshot-2023-10-05-at-17.21.43-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>No sample commit. ;)</p>
<h2 id="heading-possible-blockers-and-their-solutions">Possible blockers and their solutions</h2>
<h3 id="heading-global-is-not-defined-error"><code>global</code> is not defined error</h3>
<p>If you have this error, define global inside your <code>vite.config.ts</code> file as shown below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vite'</span>;
<span class="hljs-keyword">import</span> react <span class="hljs-keyword">from</span> <span class="hljs-string">'@vitejs/plugin-react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-comment">// ...</span>
  <span class="hljs-attr">define</span>: {
    <span class="hljs-comment">// here is the main update</span>
    <span class="hljs-attr">global</span>: <span class="hljs-string">'globalThis'</span>,
  },
});
</code></pre>
<h3 id="heading-if-you-use-emotionreact-or-emotioncss">If you use <code>@emotion/react</code> or <code>@emotion/css</code></h3>
<p>You need to inform Vite about this. To do this, install <code>@emotion/babel-plugin</code>.</p>
<pre><code class="lang-shell">yarn add @emotion/babel-plugin

OR

npm install @emotion/babel-plugin
</code></pre>
<p>Then update your Vite's <code>react</code> plugin in the <code>vite.config.ts</code> as shown below:</p>
<pre><code class="lang-javscript">import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import viteTsconfigPaths from 'vite-tsconfig-paths';
import svgr from 'vite-plugin-svgr';

export default defineConfig({
  // ...
  plugins: [
    // here is the main update
    react({
      jsxImportSource: '@emotion/react',
      babel: {
        plugins: ['@emotion/babel-plugin'],
      },
    }),
  ],
  // ...
});
</code></pre>
<h3 id="heading-oh-no-my-unit-tests-are-not-working">Oh no, my unit tests are not working!</h3>
<p>At this point, try running your unit tests — <code>yarn test</code> or <code>npm run test</code>. It’s possible that they don’t work. The following steps highlight how you can fix your unit tests.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Screenshot-2023-10-06-at-16.20.33.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Your unit tests are not working because CRA uses <code>react-scripts test</code> to run tests, so we want to switch to using <code>jest</code>.</p>
<h2 id="heading-step-8-install-jest-and-typescript-related-dependencies">Step 8: Install Jest and TypeScript-related Dependencies</h2>
<p>To start with, you need to install <code>jest</code>, <code>ts-jest</code>, and <code>jest-environment-jsdom</code>. <code>jest</code> will be our new binary for running the tests, <code>[ts-jest](https://www.npmjs.com/package/ts-jest)</code> is a transformer with source map support which allows you to run tests in TypeScript projects, and <code>jest-environment-jsdom</code> imitates the browser's behavior during test runs.</p>
<pre><code class="lang-shell">yarn add -D jest @types/jest ts-jest jest-environment-jsdom

OR

npm install --save-dev jest @types/jest ts-jest jest-environment-jsdom
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/66283764d616c4572ecd53d51ac1711f30fbe8e0">Step 8 sample commit</a>.</p>
<h2 id="heading-step-9-update-jest-config">Step 9: Update Jest Config</h2>
<p>This depends on your current Jest configuration. If it is configured inside <code>package.json</code>, you can update as follows. Here, you focus on <code>preset</code>, <code>testEnvironment</code>, <code>moduleNameMapper</code>, and <code>modulePaths</code>.</p>
<p><code>preset</code> is set to <code>ts-jest/presets/js-with-ts</code> to allow TypeScript with JavaScript. You can also just set it to <code>ts-jest</code> depending on your application.</p>
<p><code>moduleNameMapper</code> configures Jest to gracefully handle assets such as stylesheets and images.</p>
<pre><code class="lang-json">  <span class="hljs-string">"jest"</span>: {
    <span class="hljs-attr">"preset"</span>: <span class="hljs-string">"ts-jest/presets/js-with-ts"</span>,
    <span class="hljs-attr">"testEnvironment"</span>: <span class="hljs-string">"jest-environment-jsdom"</span>,
    <span class="hljs-attr">"moduleNameMapper"</span>: {
      <span class="hljs-attr">"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$"</span>: <span class="hljs-string">"&lt;rootDir&gt;/__mocks__/fileMock.js"</span>,
      <span class="hljs-attr">"\\.(css|less)$"</span>: <span class="hljs-string">"&lt;rootDir&gt;/__mocks__/styleMock.js"</span>
    },
    <span class="hljs-attr">"modulePaths"</span>: [
      <span class="hljs-comment">// you can update this to match your application setup</span>
      <span class="hljs-string">"&lt;rootDir&gt;/src"</span>
    ],
  },
</code></pre>
<p>Since we referenced a file in <code>moduleNameMapper</code> above, we need to create the file and it's corresponding files. Step 10 takes care of this. This setup is explained further in <a target="_blank" href="https://jestjs.io/docs/webpack#handling-static-assets">Jest's documentation here</a>.</p>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/4383f05fce07ac1de3c80d04f581e40218f8c83b">Step 9 sample commit</a>.</p>
<h2 id="heading-step-10-add-the-mocks-directory-to-the-root-of-your-project">Step 10: Add the <code>__mocks__</code> Directory to the Root of Your Project</h2>
<p>At the root of your project, create a folder named <code>__mocks__</code>.</p>
<p>Inside the created <code>__mocks__</code> folder, add a file named <code>styleMock.js</code> and add the following content:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = {}
</code></pre>
<p>Inside the created <code>__mocks__</code> folder, add a file named <code>fileMock.js</code> and add the following content.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = <span class="hljs-string">'test-file-stub'</span>
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/d6da2a8984176041fcbfe08ca2bf0e9339fb25b4">Step 10 sample commit</a>.</p>
<h2 id="heading-step-11-update-the-packagejson-scripts">Step 11: Update the <code>package.json</code> Scripts</h2>
<p>Now that we have <code>jest</code> properly installed, we can replace <code>react-scripts tests</code> with <code>jest</code>. Changes should be as shown below. If you do not have the <code>test:coverage</code> or <code>test:debug</code> keys in your code before, feel free to ignore.</p>
<p>Before:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"react-scripts test"</span>,
    <span class="hljs-attr">"test:coverage"</span>: <span class="hljs-string">"react-scripts test --coverage ."</span>,
    <span class="hljs-attr">"test:debug"</span>: <span class="hljs-string">"react-scripts test --inspect-brk --runInBand --no-cache"</span>
}
</code></pre>
<p>After:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"jest"</span>,
    <span class="hljs-comment">// you can add this to keep watch mode on</span>
    <span class="hljs-attr">"test:watch"</span>: <span class="hljs-string">"jest --watch"</span>,
    <span class="hljs-attr">"test:coverage"</span>: <span class="hljs-string">"jest --coverage ."</span>,
    <span class="hljs-attr">"test:debug"</span>: <span class="hljs-string">"jest --inspect-brk --runInBand --no-cache"</span>
}
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/e27a66593954ffcb36d77c3e86076444a0cf82e5">Step 11 sample commit</a>.</p>
<h2 id="heading-step-12-run-your-tests">Step 12: Run your Tests</h2>
<pre><code class="lang-shell">yarn test

OR

npm test
</code></pre>
<p>If you face a problem related to <code>import.meta</code>, you can resolve this by moving all your environment keys to a single file and mocking this file in your test. You can take a <a target="_blank" href="https://github.com/suretrust/stock-ticker/commit/07d15d1f000ec2cef7ec6dd01fccb43af3e67d30">look at this commit</a> to have a better understanding of what I mean.</p>
<p>No sample commit. :)</p>
<p>Ah, it works! But how about the browserslist config?</p>
<h2 id="heading-what-is-browserslist-config">What is browserslist config?</h2>
<p>This is a configuration used to share your target or supported browsers among multiple frontend repositories. </p>
<p>There are various standards depending on the industry. For example, in EdTech, it's possible that all users learning online use similar browsers in terms of brand, version, and screen size. This list of the commonly used browsers can easily become a standard for the EdTech industry.</p>
<p>A sample application of the browserslist config is when you need to be compatible with older browsers. Passing this range to the browserslist config helps your bundler to compile your code using polyfills that are compatible with your target browsers. This way, your page has optimized performance with good user experience.</p>
<p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Polyfill">Mozilla defines a Polyfill</a> as a piece of code (usually JavaScript on the Web) used to provide modern functionality on older browsers that do not natively support it.</p>
<p>Browserslist config is often set in the <code>package.json</code> or <code>.browserslistrc</code> file as shown below.</p>
<h3 id="heading-packagejson"><code>package.json</code></h3>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"browserslist"</span>: [
    <span class="hljs-string">"iOS &gt;= 9"</span>,
    <span class="hljs-string">"Android &gt;= 4.4"</span>,
    <span class="hljs-string">"last 2 versions"</span>,
    <span class="hljs-string">"&gt; 0.2%"</span>,
    <span class="hljs-string">"not dead"</span>
  ]
}
</code></pre>
<h3 id="heading-browserslistrc"><code>.browserslistrc</code></h3>
<pre><code class="lang-javascript">iOS &gt;= <span class="hljs-number">9</span>
Android &gt;= <span class="hljs-number">4.4</span>
last <span class="hljs-number">2</span> versions
&gt; <span class="hljs-number">0.2</span>%
not dead
</code></pre>
<p>You can also <a target="_blank" href="https://modernjs.dev/builder/en/guide/advanced/browserslist">read more about Browserslist here</a>.</p>
<h2 id="heading-why-is-browserslist-a-problem-with-vite">Why is <code>browserslist</code> a Problem with Vite?</h2>
<p>Vite uses ESBuild under the hood which expects a different format to the usual <code>browserslist</code> format.</p>
<p>ESBuild expected format: <code>['es2015', 'safari11', 'ios11']</code></p>
<p>Browserslist format: <code>['defaults', 'Safari &gt;= 11', 'ios_saf &gt;= 11']</code></p>
<p>As a result of this discrepancy, Vite ignores your <code>browserslist</code> configuration which is currently in the <code>package.json</code> or <code>.brwserslistrc</code> file. </p>
<p>To fix this, you can use a package called <a target="_blank" href="https://github.com/marcofugaro/browserslist-to-esbuild"><code>browserslist-to-esbuild</code></a> which does this conversion under the hood and pass the config to <code>build.target</code> inside the <code>vite.config.ts</code> file. Steps 13 and 14 take care of this.</p>
<h2 id="heading-step-13-install-browserslist-to-esbuild">Step 13: Install <code>browserslist-to-esbuild</code></h2>
<pre><code class="lang-shell">yarn add browserslist-to-esbuild

OR 

npm install browserslist-to-esbuild
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/fc7239af0a0da0b4bd844f8d17b3860b794f0ea5">Step 13 sample commit</a>.</p>
<h2 id="heading-step-14-confiure-the-browserslist-in-vite-config">Step 14: Confiure the <code>browserslist</code> in Vite Config</h2>
<p>In the <code>vite.config.ts</code> file, update as shown below.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vite'</span>
<span class="hljs-keyword">import</span> browserslistToEsbuild <span class="hljs-keyword">from</span> <span class="hljs-string">'browserslist-to-esbuild'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  ..
  build: {
    <span class="hljs-comment">// --&gt; ["chrome79", "edge92", "firefox91", "safari13.1"]</span>
    <span class="hljs-attr">target</span>: browserslistToEsbuild(), 
  },
  ..
})
</code></pre>
<p>And then, you can pass your configs as shown below,</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  ..
  build: {
    <span class="hljs-comment">// you can also pass your usual browserslist config here</span>
    <span class="hljs-attr">target</span>: browserslistToEsbuild([
        <span class="hljs-string">'&gt;0.2%'</span>,
        <span class="hljs-string">'not dead'</span>,
        <span class="hljs-string">'not op_mini all'</span>
    ]),
  },
  ..
})
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/b8758cd4ac9e0e1d79e361b1b0097714bc6a85ae">Step 14 sample commit</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Voilà! You're done and your application is fully migrated.</p>
<p>Missing any step? Here is a <a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1">sample pull request that highlights all the changes</a> involved.</p>
<p>You have learned the "why" and "how" of replacing <code>create-react-app</code> with <code>Vite</code>. I hope you are as proud of yourself as I was of myself for what I have learned in the process of the migration.</p>
<p>Alrighty, that it! Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Securely Access Secret API keys using Netlify Functions in a React App ]]>
                </title>
                <description>
                    <![CDATA[ In this article, you will learn how to securely access secret API keys using Netlify functions in a React app. Netlify provides rich features that help you easily deploy Single Page Applications built using frameworks like React, Vue and Angular amon... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-access-secret-api-keys-using-netlify-functions-in-a-react-app/</link>
                <guid isPermaLink="false">66d45f63246e57ac83a2c773</guid>
                
                    <category>
                        <![CDATA[ Application Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ information security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Netlify ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joseph Mawa ]]>
                </dc:creator>
                <pubDate>Mon, 28 Jun 2021 21:17:02 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/06/pexels-noelle-otto-906018.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, you will learn how to securely access secret API keys using Netlify functions in a React app.</p>
<p>Netlify provides rich features that help you easily deploy Single Page Applications built using frameworks like <a target="_blank" href="https://reactjs.org/">React</a>, <a target="_blank" href="https://v3.vuejs.org/">Vue</a> and <a target="_blank" href="https://angular.io/">Angular</a> among others. This takes away the burden of coding and maintaining server-side code.</p>
<p>In some cases, a front-end app needs to communicate with an external third-party API. Some of the third-party APIs require secret API keys to access.</p>
<p>Let's imagine a situation where you want to include weather alerts on your front-end app. As a result, you sign up for <a target="_blank" href="https://openweathermap.org/api">open weather map</a> API's paid plan which requires a secret API key to access.</p>
<p>In such situations, you'll need to take care to ensure that you don't expose the secret API key on the front end.</p>
<p>Netlify provides functionality on its web user interface which you can use to hide API keys. But the API key can be accessed from the client side if the environment variable in which it is stored is accessed from the front-end code.</p>
<h2 id="heading-what-youll-learn-in-this-article">What You'll Learn in This Article</h2>
<p>In this article, you are going to hide the secret API key on the Netlify UI and securely access it using Netlify functions in a React app created using <a target="_blank" href="https://create-react-app.dev/">create-react-app(CRA)</a>. Using Netlify functions makes sure that the API key is not exposed on the client-side.</p>
<p>The process should be similar for other frameworks, though we are using <a target="_blank" href="https://reactjs.org/">React</a> in this article.</p>
<p>By the end of this article, you will be able to do the following:</p>
<ul>
<li><p>Add a Netlify function to a React app</p>
</li>
<li><p>Use Netlify functions to securely access secret API keys</p>
</li>
<li><p>Use the <a target="_blank" href="https://docs.netlify.com/cli/get-started/">netlify-cli</a> tool to test your Netlify functions</p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Outlined below are some of the prerequisites for this article. It is worth pointing out that you can still follow along even if you don't check off every one.</p>
<p>You can Google if there is something you don't understand or post a question on the <a target="_blank" href="https://forum.freecodecamp.org/">freeCodeCamp forum</a>. We shall be happy to help.</p>
<ul>
<li><p>Have at least a basic understanding of <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript">JavaScript</a>, the <a target="_blank" href="https://reactjs.org/">React</a> framework, and a version control system like <a target="_blank" href="https://git-scm.com/">Git</a>.</p>
</li>
<li><p>Have <a target="_blank" href="https://nodejs.org/en/">Node</a> installed on your machine. If you don't have it installed, you can download it for your system from the <a target="_blank" href="https://nodejs.org/en/download/">Node downloads page</a>.</p>
</li>
<li><p>Have <a target="_blank" href="https://git-scm.com/">Git</a> installed on your machine. If you don't have it installed, you can do so from the <a target="_blank" href="https://git-scm.com/downloads">Git downloads page</a>.</p>
</li>
<li><p>Have a text editor like <a target="_blank" href="https://code.visualstudio.com/">VS code</a> or <a target="_blank" href="https://atom.io/">Atom</a> installed.</p>
</li>
<li><p>Have a <a target="_blank" href="https://www.netlify.com/">Netlify</a> account. If you don't have one, you can <a target="_blank" href="https://app.netlify.com/signup">sign up</a> at no cost using your email address.</p>
</li>
<li><p>Have a basic knowledge of Netlify's <a target="_blank" href="https://docs.netlify.com/site-deploys/create-deploys/#deploy-with-git">continuous deployment</a> feature. You will use it to deploy your React app to Netlify from <a target="_blank" href="https://github.com/">GitHub</a>.</p>
</li>
<li><p>Have a <a target="_blank" href="https://github.com/">GitHub</a> account because we'll be using Netlify's <a target="_blank" href="https://docs.netlify.com/site-deploys/create-deploys/#deploy-with-git">continuous deployment</a> feature. If you don't have an account, you can <a target="_blank" href="https://github.com/">sign up</a> using your email address.</p>
</li>
</ul>
<h2 id="heading-how-to-use-environment-variables-in-a-react-app-created-using-create-react-app">How to Use Environment Variables in a React App Created using <code>create-react-app</code></h2>
<p>In this section, you will learn how to use environment variables in a React app created using <a target="_blank" href="https://create-react-app.dev/"><code>CRA</code></a>. If you are already familiar with how to do this, then you can skip to the next section.</p>
<p>React apps created using <a target="_blank" href="https://create-react-app.dev/">CRA</a> come configured so you can create custom environment variables in <code>.env</code> file and then access them in your codebase using <code>process.env</code>.</p>
<p>To use this feature, you can follow the steps below. These steps assume you have already created a React app using <a target="_blank" href="https://create-react-app.dev/">CRA</a>.</p>
<h3 id="heading-step-1-create-a-env-file-at-the-root-of-the-project-directory">Step 1 - Create a <code>.env</code> file at the root of the project directory</h3>
<p>Start by creating a <code>.env</code> file at the root of the project directory. You can then add your environment variables in the <code>.env</code> file so that they look like the below.</p>
<pre><code class="lang-shell">REACT_APP_FIRST_SECRET=12345678
REACT_APP_SECOND_SECRET=123456789
</code></pre>
<p>In the above <code>.env</code> file, the environment variables are <code>REACT_APP_FIRST_SECRET</code> and <code>REACT_APP_SECOND_SECRET</code>. Their corresponding values are on the right-hand side. You need to take note of a few things when using environment variables with <a target="_blank" href="https://create-react-app.dev/">CRA</a>:</p>
<ul>
<li><p>The environment variable should always start with <code>REACT_APP</code> and then be followed by the variable name for it to work. For example, you can name the variable containing your API key <code>REACT_APP_API_KEY</code>.</p>
</li>
<li><p>There should be no spacing before and after the <code>=</code>.</p>
</li>
</ul>
<h3 id="heading-step-2-access-the-environment-variable-in-your-app-using-processenv">Step 2 - Access the environment variable in your app using <code>process.env</code></h3>
<p>You can then access those environment variables in your React app using <code>process.env.REACT_APP_FIRST_SECRET</code> and <code>proces.env.REACT_APP_SECOND_SECRET</code>. These variables are added to your codebase at build time, so you should restart your development server if you are running the app on <code>localhost</code> for the changes to take effect.</p>
<p>Accessing the environment variable like that prevents you from pushing your secret API key to a remote Git hosting service like <a target="_blank" href="https://github.com/">GitHub</a>.</p>
<p><a target="_blank" href="https://create-react-app.dev/">CRA</a> adds the <code>.gitignore</code> file by default. You just need to add <code>.env</code> file to it so that Git will ignore your <code>.env</code> file when you commit your changes.</p>
<p>What you have just learned about environment variables will keep your secrets safe in development.</p>
<p>But what will happen if you do the same thing in production since the environment variables are added to your codebase at build time? The next section will answer that question.</p>
<h2 id="heading-accessing-environment-variables-from-a-react-app-created-using-creat-react-app-exposes-your-api-keys">Accessing environment variables from a React app created using <code>creat-react-app</code> exposes your API keys</h2>
<p>Yes, indeed it does. Unfortunately, some absolute beginners think otherwise. That included me when I was just starting. But even the <a target="_blank" href="https://create-react-app.dev/">create-react-app documentation</a> states that:</p>
<blockquote>
<p>Environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files - <a target="_blank" href="https://create-react-app.dev/">create-react-app documentation</a></p>
</blockquote>
<p>To illustrate this, I have built a <a target="_blank" href="https://netlify-secrets-demo.netlify.app/">simple demo app</a> and deployed it to Netlify. This is a simple React app created using <a target="_blank" href="https://create-react-app.dev/">CRA</a>. If you are interested, you can fork the <a target="_blank" href="https://github.com/nibble0101/netlify-secrets-demo-app">project repository</a> and deploy the app to Netlify under your account.</p>
<p>In this app, I am fetching a placeholder todo item from the <a target="_blank" href="https://jsonplaceholder.typicode.com/todos">JSON placeholder API</a> and then displaying it to the user.</p>
<p>The <a target="_blank" href="https://jsonplaceholder.typicode.com/todos">JSON placeholder API</a> does not need an API key to access. But for this illustration, I am using the base URL as the "secret" which I don't want to expose.</p>
<p>Most web-based APIs require passing the API key as a query parameter when authorizing users. While deploying the app, I have set the value of <code>REACT_APP_TODO_BASE_URL</code> to <code>https://jsonplaceholder.typicode.com/todos</code> on Netlify's web interface.</p>
<p>There are two ways you can access the value which I have hidden in the environment variable from the front-end:</p>
<ol>
<li><p>By inspecting the app's codebase</p>
</li>
<li><p>By inspecting the Network tab in the <a target="_blank" href="https://developer.chrome.com/docs/devtools/">Chrome DevTools</a></p>
</li>
</ol>
<h3 id="heading-how-to-inspect-the-apps-codebase">How to inspect the app's codebase</h3>
<p>To inspect the app's codebase, follow the steps below:</p>
<ol>
<li><p>Navigate to the deployed <a target="_blank" href="https://netlify-secrets-demo-app.netlify.app/">demo app</a>.</p>
</li>
<li><p>Open the browser developer tools. You can open them by pressing the key combination <code>CTRL + SHIFT + I</code> on Chrome or right-clicking and then selecting the Inspect option in Chrome. Click the <code>Sources</code> tab. This is what it looks like for me in Chrome if the <code>Sources</code> tab is active. It might look different in other browsers though.</p>
<p> <img src="https://www.freecodecamp.org/news/content/images/2021/06/005-01-sources-tab.png" alt="005-01-sources-tab" width="600" height="400" loading="lazy"></p>
</li>
<li><p>In the <code>Sources</code> tab, you should see <code>top</code> folder under the <code>Page</code> tab. Then navigate from the <code>top</code> folder to <code>main.e54a1b49.chunk.js</code> by following the path <code>top/netlify-secrets-demo-app.netlify.app/static/js/main.e54a1b49.chunk.js</code>. <code>main.e54a1b49.chunk.js</code> is a one-line minifed file that is not readable.</p>
<p> <img src="https://www.freecodecamp.org/news/content/images/2021/06/005-02-sources-folder.png" alt="005-02-sources-folder" width="600" height="400" loading="lazy"></p>
</li>
<li><p>Click the<code>{}</code> symbol at the bottom left of the panel to pretty-print the code in a readable format.</p>
</li>
<li><p>The secret that we hid in the environment variable is right there in the codebase on line 37 as shown in the image below.</p>
<p> <img src="https://www.freecodecamp.org/news/content/images/2021/06/005-03-pretty-code.png" alt="005-03-pretty-code" width="600" height="400" loading="lazy"></p>
</li>
</ol>
<h3 id="heading-how-to-inspect-the-newtwork-tab-in-the-devtoolshttpsdeveloperchromecomdocsdevtools">How to inspect the Newtwork tab in the <a target="_blank" href="https://developer.chrome.com/docs/devtools/">Devtools</a></h3>
<ol>
<li><p>Navigate to the deployed <a target="_blank" href="https://netlify-secrets-demo-app.netlify.app/">demo app</a></p>
</li>
<li><p>Open the browser developer tool and then open the Network Tab. The network Tab should look like in the image below in chrome. It might look different in other browsers.</p>
<p> <img src="https://www.freecodecamp.org/news/content/images/2021/06/005-04-network-tab.png" alt="005-04-network-tab" width="600" height="400" loading="lazy"></p>
</li>
<li><p>Click the <code>Get another todo</code> button in the browser. You should be able to see another row in the open panel indicating that another request has been made. Mine looks like in the image below.</p>
<p> <img src="https://www.freecodecamp.org/news/content/images/2021/06/005-05-network-request-made.png" alt="005-05-network-request-made" width="600" height="400" loading="lazy"></p>
</li>
<li><p>Click the last row. Another panel will open showing the request and response headers. Again our "secret" has been exposed.</p>
<p> <img src="https://www.freecodecamp.org/news/content/images/2021/06/005-06-response-header-open.png" alt="005-06-response-header-open" width="600" height="400" loading="lazy"></p>
</li>
</ol>
<p>As you can see from the above, your API key may not be visible in the codebase that has been committed to <a target="_blank" href="https://github.com/">GitHub</a> but it is still accessible on the client-side. Now you know what would happen if your key is for a paid plan.</p>
<p>To keep your secret key secret, you need to access your environment variable using <a target="_blank" href="https://www.netlify.com/products/functions/">Netlify functions</a>.</p>
<p>In the next section, you will learn how to securely access environment variables using Netlify functions. You will do that by adding Netlify functions to a React app and then deploying it to Netlify.</p>
<h2 id="heading-how-to-securely-access-environment-variables-with-netlify-functions">How to Securely Access Environment Variables with Netlify Functions</h2>
<p>In this section, you will fork a simple React app which was created using <a target="_blank" href="https://create-react-app.dev/">CRA</a> and then add a Netlify function to it. You will then use your function to access the environment variable instead of accessing it from your front-end code.</p>
<p>This will ensure that you don't expose your secret API key as illustrated in the section above. You will then deploy the app to Netlify using Netlify's <a target="_blank" href="https://docs.netlify.com/site-deploys/create-deploys/#deploy-with-git">continuous deployment</a> feature.</p>
<h3 id="heading-what-is-a-netlify-function">What is a Netlify function?</h3>
<p>This is a function that you can use for executing server-side code without having to deploy your own server.</p>
<p>According to the <a target="_blank" href="https://docs.netlify.com/functions/overview/">documentation</a>, if you use Netlify functions, you are indirectly using AWS’s serverless Lambda functions which are used for running on-demand, server-side code without having to run a dedicated server.</p>
<p>Below are some of the reasons why you might need to use Netlify functions.</p>
<ul>
<li><p>Fetch live data from an API</p>
</li>
<li><p>Return dynamic images</p>
</li>
<li><p>Send automated emails</p>
</li>
</ul>
<p>To start using Netlify functions, create a folder at the root of the project directory and name it <code>netlify</code>.</p>
<p>Inside the Netlify folder, you have to create another folder called <code>functions</code>. In the <code>functions</code> folder, you can create a file that contains a function that executes your code. As a result, the path to the files containing your functions should be <code>netlify/functions</code>.</p>
<p>This is the default location where Netlify will look for your functions. If you want to change the directory where your functions are located inside <code>netlify</code> folder, then you need to add that information to a <code>netlify.toml</code> configuration file at the root of the project directory so that Netlify knows where to look for them.</p>
<p>Using <code>netlify.toml</code> is outside the scope of this article. We shall be using the default configuration.</p>
<p>Below is what a Netlify function looks like. Let's assume that I have created a <code>todo.js</code> file in <code>netlify/functions</code> and added the code below to it.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> axios = <span class="hljs-built_in">require</span>(<span class="hljs-string">"axios"</span>);

<span class="hljs-built_in">exports</span>.handler = <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">event, context</span>) </span>{
  <span class="hljs-comment">//Securely access environment variables here</span>
};
</code></pre>
<p>You will notice that the function has two parameters, <code>event</code> and <code>context</code>. If the function needs a dependency, make sure you add it to your project's <code>package.json</code> file.</p>
<p>In this case, I have added <code>axios</code> as a dependency. This function is executed whenever we hit the <code>netlify/functions/todo</code> endpoint.</p>
<p>There are other ways of triggering Netlify functions, but for this article let's focus on the simplest use case.</p>
<p>Data that have been passed from the front-end can be accessed in the <code>event</code> parameter. In the body of the function, you can do whatever you want including securely accessing your API key and sending data back to the front-end.</p>
<p>That is what you need to know to start using Netlify functions. If you want to dive deeper and explore what else you can do with them, take a look at the <a target="_blank" href="https://docs.netlify.com/functions/overview/">documentation</a>.</p>
<p>Now that you understand the basics of <a target="_blank" href="https://docs.netlify.com/functions/overview/">Netlify functions</a>, follow the steps below to learn how to implement them in a codebase.</p>
<p>You will fork <a target="_blank" href="https://github.com/nibble0101/netlify-secrets-demo-app">this demo app</a> and then add Netlify functions to it. It is a simple React project created using <a target="_blank" href="https://create-react-app.dev/">CRA</a>.</p>
<h3 id="heading-step-1-how-to-fork-the-project-under-your-own-github-account">Step 1 - How to fork the project under your own GitHub account</h3>
<p>In this step, you are going to fork the <a target="_blank" href="https://github.com/nibble0101/netlify-secrets-demo-app">demo app</a> under your own GitHub account. It is necessary to fork the project under your account so that you will be able to deploy it to Netlify.</p>
<p>If you are not interested in forking the project but would like to implement Netlify functions to your project, then skip to step 6.</p>
<p>If you don't know how to fork a GitHub repository, you can follow the steps described in the <a target="_blank" href="https://docs.github.com/en/get-started/quickstart/fork-a-repo">how to fork a repo</a> section of the GitHub documentation.</p>
<h3 id="heading-step-2-how-to-clone-the-project-to-your-local-machine">Step 2 - How to clone the project to your local machine</h3>
<p>In this step, you are going to clone the project to your local machine by running the command below (assuming you forked the project under your accoun). Do not forget to replace <code>GITHUB_USER_NAME</code> with your GitHub username.</p>
<pre><code class="lang-shell">git clone git@github.com:GITHUB_USER_NAME/netlify-secrets-demo-app.git
</code></pre>
<p>or</p>
<pre><code class="lang-shell">git clone https://github.com/GITHUB_USER_NANE/netlify-secrets-demo-app.git
</code></pre>
<p>After successfully cloning the project to your machine, you should be able to see the <code>netlify-secrets-demo-app</code> folder containing your project in the directory where the project was cloned.</p>
<p>You can navigate to the project directory and open it in your favorite text editor.</p>
<p>In the next step, you will install dependencies.</p>
<h3 id="heading-step-3-how-to-install-dependencies">Step 3 - How to install dependencies</h3>
<p>In this step, you will install dependencies by running the command below on the terminal.</p>
<pre><code class="lang-shell">npm install
</code></pre>
<p>The above command will install the dependencies you need. The installation process might take a couple of minutes so you need to be patient.</p>
<p>In the next step, you will create a <code>.env</code> file and add environment variables to it.</p>
<h3 id="heading-step-4-how-to-create-a-env-file">Step 4 - How to create a <code>.env</code> file</h3>
<p>In this step, you are going to create a <code>.env</code> file at the root of the project directory by running the command below on the terminal:</p>
<pre><code class="lang-shell">touch .env
</code></pre>
<p>You should be able to see the <code>.env</code> file created at the root of the project directory. Copy and paste the contents of the <code>example.env</code> file in it.</p>
<p>Since we'll be using Netlify functions to access environment variables, you don't need to prefix the variable name with <code>REACT_APP</code> as described at the beginning of the article. Change <code>REACT_APP_TODO_BASE_URL</code> environment variable to <code>TODO_BASE_URL</code> and set its value to <code>https://jsonplaceholder.typicode.com/todos</code>.</p>
<p>In the next step, you will add Netlify functions to your app.</p>
<h3 id="heading-step-5-how-to-add-netlify-functions-to-your-app">Step 5 - How to add Netlify functions to your app</h3>
<p>In this step, you will add a Netlify function to the app and use it to securely access your environment variables.</p>
<p>As I mentioned above, by default, Netlify will look for your functions inside the <code>functions</code> directory which must be located inside the <code>netlify</code> folder.</p>
<p>If you are keeping the functions in a different directory inside the <code>netlify</code> folder, then you need to provide additional information inside <code>netlify.toml</code> configuration file at the root of the project directory. This will make sure that Netlify knows where to locate your functions. But in this article, we'll be using the Netlify default configuration.</p>
<p>Create a folder at the root of the project directory and name it <code>netlify</code>. In the <code>netlify</code> folder create another folder and call it <code>functions</code>. In the <code>functions</code> folder, create <code>todo.js</code> file.</p>
<p>Copy and paste the code below in the <code>todo.js</code> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> axios = <span class="hljs-built_in">require</span>(<span class="hljs-string">"axios"</span>);

<span class="hljs-built_in">exports</span>.handler = <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">event, context</span>) </span>{
  <span class="hljs-built_in">console</span>.log(event);
  <span class="hljs-built_in">console</span>.log(context);
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { id } = event.queryStringParameters;
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">`<span class="hljs-subst">${process.env.TODO_BASE_URL}</span>/<span class="hljs-subst">${id}</span>`</span>);
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">statusCode</span>: <span class="hljs-number">200</span>,
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">title</span>: response.data.title }),
    };
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">statusCode</span>: <span class="hljs-number">404</span>,
      <span class="hljs-attr">body</span>: err.toString(),
    };
  }
};
</code></pre>
<p>We'll send data from the front-end as the value of the <code>id</code> parameter in the query string. It is accessible in the <code>queryStringParameters</code> property of the <code>event</code> object.</p>
<p>You can also <code>console.log</code> the <code>event</code> and <code>context</code> parameters to see what their properties are.</p>
<p>We securely access the environment variable and use <code>axios</code> to fetch our todo. If it is successful, we send back a response object with a <code>statusCode</code> of 200 with the data in the body of the response object. If there is an error we return a <code>statusCode</code> of 404 and the error is sent back in the body of the response object.</p>
<p>The function you have added above will be exposed to your front-end code via <code>/.netlify/functions/todo</code> endpoint. It will be executed whenever you hit the <code>/.netlify/functions/todo</code> endpoint. Now let's execute the function from the front-end.</p>
<p>Navigate to the <code>App.js</code> component in the <code>src</code> folder. In the <code>useEffect</code> hook on line 15, instead of accessing <code>process.env.</code> on the front-end, we instead make a <code>GET</code> request to our endpoint exposed by the Netlify function we declared in the previous step.</p>
<p>So change line 15 from:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> url = <span class="hljs-string">`<span class="hljs-subst">${process.env.REACT_APP_TODO_BASE_URL}</span>/<span class="hljs-subst">${todoId}</span>`</span>;
</code></pre>
<p>to:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> url = <span class="hljs-string">`/.netlify/functions/todo?id=<span class="hljs-subst">${todoId}</span>`</span>;
</code></pre>
<p>Your <code>App.js</code> component should now look like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [todoId, setTodoId] = useState(<span class="hljs-number">1</span>);
  <span class="hljs-keyword">const</span> [todo, setTodo] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getNewTodo</span>(<span class="hljs-params"></span>) </span>{
    setTodoId(<span class="hljs-function">(<span class="hljs-params">todoId</span>) =&gt;</span> (todoId === <span class="hljs-number">20</span> ? <span class="hljs-number">1</span> : todoId + <span class="hljs-number">1</span>));
  }

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchTodo</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">const</span> url = <span class="hljs-string">`/.netlify/functions/todo?id=<span class="hljs-subst">${todoId}</span>`</span>;
      <span class="hljs-keyword">try</span> {
        setLoading(<span class="hljs-literal">true</span>);
        <span class="hljs-keyword">const</span> todo = <span class="hljs-keyword">await</span> fetch(url).then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> res.json());
        setTodo(todo.title);
      } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-built_in">console</span>.log(err);
      } <span class="hljs-keyword">finally</span> {
        setLoading(<span class="hljs-literal">false</span>);
      }
    }
    fetchTodo();
  }, [todoId]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{getNewTodo}</span>&gt;</span> Get another todo <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{loading ? "Loading..." : todo}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>In the code above we are storing <code>todo</code> and <code>todoId</code> in state. Notice that the <code>GET</code> request we are making to the <code>/.netlify/functions/todo</code> endpoint in the <code>useEffect</code> hook. We are passing the <code>todoId</code> as the value of the query parameter <code>id</code>.</p>
<p>After making the fetch request, our <code>todo.js</code> function will be invoked. Inside <code>todo.js</code> as explained above, we'll access the environment variable and fetch the todo which is returned by the function for the front-end code to use. This keeps our environment variable safe since it is not accessible from the front-end. The front-end only consumes what the function returns.</p>
<p>In the next step, you will test whether the function you have just defined works as intended.</p>
<h3 id="heading-step-6-how-to-test-your-netlify-function">Step 6 - How to test your Netlify function</h3>
<p>In this step, you will use <a target="_blank" href="https://docs.netlify.com/cli/get-started/">netlify-cli</a> to test whether the function you defined works as intended.</p>
<p>Run the command below to install <code>netlify-cli</code> globally. The installation will take a bit of time, so be patient:</p>
<pre><code class="lang-js">npm install netlify-cli -g
</code></pre>
<p>After <code>netlify-cli</code> is installed globally, run this command to test your function:</p>
<pre><code class="lang-js">netlify dev
</code></pre>
<p>Running the above command successfully will start a local development server on port 8888. You will also see the <code>event</code> and <code>context</code> parameters printed on the console when your function is invoked.</p>
<p>You can also test the function by running the command below on another terminal. Make sure the server is running before running the command below otherwise you will get an error.</p>
<pre><code class="lang-js">netlify functions:invoke --querystring <span class="hljs-string">"id=1"</span>
</code></pre>
<p>This command will invoke the function with the specified query string. You will be prompted to make some selections on the terminal. Just press enter.</p>
<p>Successfully running the above command will fetch our todo which will then be printed on the terminal.</p>
<pre><code class="lang-js">{<span class="hljs-string">"title"</span>:<span class="hljs-string">"delectus aut autem"</span>}
</code></pre>
<p>In the next step, you will deploy the project on your local machine to GitHub.</p>
<h3 id="heading-step-7-how-to-commit-your-changes-and-push-to-github">Step 7 - How to commit your changes and push to GitHub</h3>
<p>In this step, you will commit the changes on your local machine and push them to GitHub using the commands below.</p>
<pre><code class="lang-shell">git commit -m "Add netlify functions"
git push origin master
</code></pre>
<p>In the next step, you will use netlify's <a target="_blank" href="https://docs.netlify.com/site-deploys/create-deploys/#deploy-with-git">continuous ceployment</a> feature to deploy the app from GitHub.</p>
<h3 id="heading-step-8-how-to-deploy-the-app-to-netlify-from-github">Step 8 - How to deploy the app to Netlify from GitHub</h3>
<p>In this step, you will use Netlify's <a target="_blank" href="https://docs.netlify.com/site-deploys/create-deploys/#deploy-with-git">continuous deployment</a> feature to deploy from GitHub.</p>
<p>This step requires you to have a Netlify account. If you haven't signed up, you can do so from the <a target="_blank" href="https://app.netlify.com/signup">signup page</a> at no cost.</p>
<p>Log in to your Netlify account and follow the process for linking a GitHub repository to Netlify for continuous deployment <a target="_blank" href="https://docs.netlify.com/configure-builds/get-started/#basic-build-settings">as described in the documentation</a>. Do not forget to add the environment variable <code>TODO_BASE_URL</code> and set its value to <code>https://jsonplaceholder.typicode.com/todos</code> under the advanced settings as you deploy the app to Netlify.</p>
<p>And there you have it! That is how you hide secret API keys using Netlify functions. I hope you enjoyed reading the article.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article we learned how to:</p>
<ul>
<li><p>Add a Netlify function to a React app</p>
</li>
<li><p>Use Netlify functions to securely access secret API keys</p>
</li>
<li><p>Use the <a target="_blank" href="https://docs.netlify.com/cli/get-started/">netlify-cli</a> tool to test your Netlify functions</p>
</li>
</ul>
<p>With <a target="_blank" href="https://www.netlify.com/products/functions/">netlify's serverless functions</a>, you can send emails, fetch data from an API like we just did, and much more. It has equipped front-end developers with the tools to write back-end code without worrying about server maintenance.</p>
<p>You can explore more about what else you can do with Netlify functions in the <a target="_blank" href="https://docs.netlify.com/functions/overview/">functions section of the documentation</a>.</p>
<p>Finally, if you have any questions about what we've covered in this article, feel free to ask on the <a target="_blank" href="https://forum.freecodecamp.org/">freeCodeCamp forum</a> or DM me on <a target="_blank" href="https://twitter.com/MJMAWA">Twitter</a>. You can also ask your question in the <a target="_blank" href="https://answers.netlify.com/">Netlify forum</a>.</p>
<p>Thanks for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Search and Filter Components in React ]]>
                </title>
                <description>
                    <![CDATA[ If you're building a React app, you want your users to be able to search and get exact results. And if you are getting tons of items from an API, then you need to create a way for users to be able to find various items easily. For this tutorial ]]>
                </description>
                <link>https://www.freecodecamp.org/news/search-and-filter-component-in-reactjs/</link>
                <guid isPermaLink="false">66d46168246e57ac83a2c7e7</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Spruce Emmanuel ]]>
                </dc:creator>
                <pubDate>Fri, 04 Jun 2021 21:34:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/05/wirxeocmd6tpnn9c5oqc.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you're building a React app, you want your users to be able to search and get exact results. And if you are getting tons of items from an API, then you need to create a way for users to be able to find various items easily.</p>
<p>For this tutorial we are going to be using one of <a target="_blank" href="https://www.frontendmentor.io/challenges/rest-countries-api-with-color-theme-switcher-5cacc469fec04111f7b848ca">Frontend Mentor's free advanced API projects</a> as an example.</p>
<h2 id="heading-table-of-contents">Table Of Contents</h2>
<ol>
<li><p>Getting Started</p>
</li>
<li><p>How to Set Up React</p>
</li>
<li><p>How to Fetch the Data</p>
</li>
<li><p>How to Search for Items in the API</p>
</li>
<li><p>How to Filter Items Based on Region</p>
</li>
</ol>
<h1 id="heading-getting-started">Getting Started</h1>
<p>For this tutorial we will be using the free <a target="_blank" href="https://restcountries.eu/">REST COUNTRIES API</a> provided by <a target="_blank" href="https://apilayer.com/">Apilayer</a>.</p>
<p>Basically we will fetch the data from our API endpoint <code>https://restcountries.eu/rest/v2/all</code> and display the data in a user readable form.</p>
<p>Then we'll provide a way for users to easily search for specific countries by their names and capitals.‌‌ Here is an example of the response for a particular country:</p>
<pre><code class="lang-json">[
  {
    <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Colombia"</span>,
    <span class="hljs-attr">"topLevelDomain"</span>: [
      <span class="hljs-string">".co"</span>
    ],
    <span class="hljs-attr">"alpha2Code"</span>: <span class="hljs-string">"CO"</span>,
    <span class="hljs-attr">"alpha3Code"</span>: <span class="hljs-string">"COL"</span>,
    <span class="hljs-attr">"callingCodes"</span>: [
      <span class="hljs-string">"57"</span>
    ],
    <span class="hljs-attr">"capital"</span>: <span class="hljs-string">"Bogotá"</span>,
    <span class="hljs-attr">"altSpellings"</span>: [
      <span class="hljs-string">"CO"</span>,
      <span class="hljs-string">"Republic of Colombia"</span>,
      <span class="hljs-string">"República de Colombia"</span>
    ],
    <span class="hljs-attr">"region"</span>: <span class="hljs-string">"Americas"</span>,
    <span class="hljs-attr">"subregion"</span>: <span class="hljs-string">"South America"</span>,
    <span class="hljs-attr">"population"</span>: <span class="hljs-number">48759958</span>,
    <span class="hljs-attr">"latlng"</span>: [
      <span class="hljs-number">4</span>,
      <span class="hljs-number">-72</span>
    ],
    <span class="hljs-attr">"demonym"</span>: <span class="hljs-string">"Colombian"</span>,
    <span class="hljs-attr">"area"</span>: <span class="hljs-number">1141748</span>,
    <span class="hljs-attr">"gini"</span>: <span class="hljs-number">55.9</span>,
    <span class="hljs-attr">"timezones"</span>: [
      <span class="hljs-string">"UTC-05:00"</span>
    ],
    <span class="hljs-attr">"borders"</span>: [
      <span class="hljs-string">"BRA"</span>,
      <span class="hljs-string">"ECU"</span>,
      <span class="hljs-string">"PAN"</span>,
      <span class="hljs-string">"PER"</span>,
      <span class="hljs-string">"VEN"</span>
    ],
    <span class="hljs-attr">"nativeName"</span>: <span class="hljs-string">"Colombia"</span>,
    <span class="hljs-attr">"numericCode"</span>: <span class="hljs-string">"170"</span>,
    <span class="hljs-attr">"currencies"</span>: [
      {
        <span class="hljs-attr">"code"</span>: <span class="hljs-string">"COP"</span>,
        <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Colombian peso"</span>,
        <span class="hljs-attr">"symbol"</span>: <span class="hljs-string">"$"</span>
      }
    ],
    <span class="hljs-attr">"languages"</span>: [
      {
        <span class="hljs-attr">"iso639_1"</span>: <span class="hljs-string">"es"</span>,
        <span class="hljs-attr">"iso639_2"</span>: <span class="hljs-string">"spa"</span>,
        <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Spanish"</span>,
        <span class="hljs-attr">"nativeName"</span>: <span class="hljs-string">"Español"</span>
      }
    ],
    <span class="hljs-attr">"translations"</span>: {
      <span class="hljs-attr">"de"</span>: <span class="hljs-string">"Kolumbien"</span>,
      <span class="hljs-attr">"es"</span>: <span class="hljs-string">"Colombia"</span>,
      <span class="hljs-attr">"fr"</span>: <span class="hljs-string">"Colombie"</span>,
      <span class="hljs-attr">"ja"</span>: <span class="hljs-string">"コロンビア"</span>,
      <span class="hljs-attr">"it"</span>: <span class="hljs-string">"Colombia"</span>,
      <span class="hljs-attr">"br"</span>: <span class="hljs-string">"Colômbia"</span>,
      <span class="hljs-attr">"pt"</span>: <span class="hljs-string">"Colômbia"</span>
    },
    <span class="hljs-attr">"flag"</span>: <span class="hljs-string">"https://restcountries.eu/data/col.svg"</span>,
    <span class="hljs-attr">"regionalBlocs"</span>: [
      {
        <span class="hljs-attr">"acronym"</span>: <span class="hljs-string">"PA"</span>,
        <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Pacific Alliance"</span>,
        <span class="hljs-attr">"otherAcronyms"</span>: [],
        <span class="hljs-attr">"otherNames"</span>: [
          <span class="hljs-string">"Alianza del Pacífico"</span>
        ]
      },
      {
        <span class="hljs-attr">"acronym"</span>: <span class="hljs-string">"USAN"</span>,
        <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Union of South American Nations"</span>,
        <span class="hljs-attr">"otherAcronyms"</span>: [
          <span class="hljs-string">"UNASUR"</span>,
          <span class="hljs-string">"UNASUL"</span>,
          <span class="hljs-string">"UZAN"</span>
        ],
        <span class="hljs-attr">"otherNames"</span>: [
          <span class="hljs-string">"Unión de Naciones Suramericanas"</span>,
          <span class="hljs-string">"União de Nações Sul-Americanas"</span>,
          <span class="hljs-string">"Unie van Zuid-Amerikaanse Naties"</span>,
          <span class="hljs-string">"South American Union"</span>
        ]
      }
    ],
    <span class="hljs-attr">"cioc"</span>: <span class="hljs-string">"COL"</span>
  }
]
</code></pre>
<p>‌‌By the end of this tutorial hopefully you will learn how to search through an API and return only the queried results with React.</p>
<h1 id="heading-how-to-set-up-react">How to Set Up React</h1>
<p>We'll use <code>create-react-app</code> to set up our project because it offers a modern build setup with no configuration at all.‌‌</p>
<p>To set up React, launch your terminal (either the one provided by your operating system or you can use an editor like VS Code) and run the following commands:</p>
<pre><code class="lang-bash">npx create-react-app my-app 
<span class="hljs-built_in">cd</span> my-app 
npm start
</code></pre>
<p>If you are unsure how to properly setup a <code>create-react-app</code> project you can refer to the official guide here at <a target="_blank" href="https://create-react-app.dev/docs/getting-started/">create-react-app-dev</a>.‌‌</p>
<p>For our case and to display live results in this tutorial, we'll use <a target="_blank" href="https://codepen.io/">Codepen</a> to setup our project. You can do this by using a Codepen template by <a target="_blank" href="https://codepen.io/MrMaster">Lathryx</a>:</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/MrMaster/embed/oNYWNjr" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p> </p>
<p>‌‌and there you have it – we have React set up in Codepen.</p>
<h2 id="heading-how-to-fetch-the-data-from-our-api-endpoint">How to Fetch the Data from Our API Endpoint</h2>
<p>Now that we have successfully setup our React project, it is time to fetch the data from our API. There are many ways to fetch data in React, but the two most popular are <strong>Axios</strong> (a promise-based HTTP client) and the <strong>Fetch API</strong> (a browser in-built web API).‌‌</p>
<p>We’ll use the <code>Fetch API</code> provided by the browser and Ajax to fetch our data from our API Endpoint.‌‌ Here is an example using hooks from <a target="_blank" href="https://reactjs.org/docs/faq-ajax.html">Ajax and APIs by React</a>:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyComponent</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-literal">null</span>);
      <span class="hljs-keyword">const</span> [isLoaded, setIsLoaded] = useState(<span class="hljs-literal">false</span>);
      <span class="hljs-keyword">const</span> [items, setItems] = useState([]);

      <span class="hljs-comment">// Note: the empty deps array [] means</span>
      <span class="hljs-comment">// this useEffect will run once</span>
      <span class="hljs-comment">// similar to componentDidMount()</span>
      useEffect(<span class="hljs-function">() =&gt;</span> {
        fetch(<span class="hljs-string">"https://api.example.com/items"</span>)
          .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json())
          .then(
            <span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
              setIsLoaded(<span class="hljs-literal">true</span>);
              setItems(result);
            },
            <span class="hljs-comment">// Note: it's important to handle errors here</span>
            <span class="hljs-comment">// instead of a catch() block so that we don't swallow</span>
            <span class="hljs-comment">// exceptions from actual bugs in components.</span>
            <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
              setIsLoaded(<span class="hljs-literal">true</span>);
              setError(error);
            }
          )
      }, [])

      <span class="hljs-keyword">if</span> (error) {
        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Error: {error.message}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!isLoaded) {
        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">return</span> (
          <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
            {items.map(item =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>&gt;</span>
                {item.name} {item.price}
              <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
        );
      }
    }
</code></pre>
<p>This fetches data from our endpoint in <code>line 10</code> and then uses <code>setState</code> to update our component when it gets the data.</p>
<p>From <code>line 27</code> we display an error message if getting data from our API fails. If it doesn't fail we display the data as a list.</p>
<p>If you are unfamiliar with React lists I suggest you take a look at this guide to <a target="_blank" href="https://reactjs.org/docs/lists-and-keys.html">React Lists And Keys</a>.</p>
<p>Now let's use this code to fetch and display data from our REST COUNTRIES API.</p>
<p>From the example code above, we want to <code>import useState from React</code> and then change <code>line 10</code> to:</p>
<p><code>fetch("</code><a target="_blank" href="https://restcountries.eu/rest/v2/all&quot;\)‌"><code>https://restcountries.eu/rest/v2/all")</code>‌</a></p>
<p>When we put it all together we have:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://cdn.skypack.dev/react"</span>;

    <span class="hljs-comment">// Note: the empty deps array [] means</span>
    <span class="hljs-comment">// this useEffect will run once</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-literal">null</span>);
        <span class="hljs-keyword">const</span> [isLoaded, setIsLoaded] = useState(<span class="hljs-literal">false</span>);
        <span class="hljs-keyword">const</span> [items, setItems] = useState([]);

        useEffect(<span class="hljs-function">() =&gt;</span> {
            fetch(<span class="hljs-string">"https://restcountries.eu/rest/v2/all"</span>)
                .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> res.json())
                .then(
                    <span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
                        setIsLoaded(<span class="hljs-literal">true</span>);
                        setItems(result);
                    },
                    <span class="hljs-comment">// Note: it's important to handle errors here</span>
                    <span class="hljs-comment">// instead of a catch() block so that we don't swallow</span>
                    <span class="hljs-comment">// exceptions from actual bugs in components.</span>
                    <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
                        setIsLoaded(<span class="hljs-literal">true</span>);
                        setError(error);
                    }
                );
        }, []);
</code></pre>
<p><strong>Note:</strong> we are importing <code>useState</code> and <code>useEffect</code> from <code>"</code><a target="_blank" href="https://cdn.skypack.dev/react"><code>https://cdn.skypack.dev/react</code></a><code>";</code>. This is because we are using a CDN to import React in Codepen. If you set up React Locally then you should use <code>import { useState, useEffect } from "react";</code>.</p>
<p>Then we want to display our received data as a list of Countries. The final code to do this looks like this:</p>
<pre><code class="lang-js">
    <span class="hljs-comment">// Note: the empty deps array [] means</span>
    <span class="hljs-comment">// this useEffect will run once</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-literal">null</span>);
        <span class="hljs-keyword">const</span> [isLoaded, setIsLoaded] = useState(<span class="hljs-literal">false</span>);
        <span class="hljs-keyword">const</span> [items, setItems] = useState([]);

        useEffect(<span class="hljs-function">() =&gt;</span> {
            fetch(<span class="hljs-string">"https://restcountries.eu/rest/v2/all"</span>)
                .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> res.json())
                .then(
                    <span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
                        setIsLoaded(<span class="hljs-literal">true</span>);
                        setItems(result);
                    },
                    <span class="hljs-comment">// Note: it's important to handle errors here</span>
                    <span class="hljs-comment">// instead of a catch() block so that we don't swallow</span>
                    <span class="hljs-comment">// exceptions from actual bugs in components.</span>
                    <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
                        setIsLoaded(<span class="hljs-literal">true</span>);
                        setError(error);
                    }
                );
        }, []);

        <span class="hljs-keyword">if</span> (error) {
            <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;&gt;</span>{error.message}<span class="hljs-tag">&lt;/&gt;</span></span>;
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!isLoaded) {
            <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;&gt;</span>loading...<span class="hljs-tag">&lt;/&gt;</span></span>;
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> (
                <span class="hljs-comment">/* here we map over the element and display each item as a card  */</span>
                <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"wrapper"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-grid"</span>&gt;</span>
                        {items.map((item) =&gt; (
                            <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">article</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.callingCodes}</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-image"</span>&gt;</span>
                                        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{item.flag}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">{item.name}</span> /&gt;</span>
                                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-content"</span>&gt;</span>
                                        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-name"</span>&gt;</span>{item.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                                        <span class="hljs-tag">&lt;<span class="hljs-name">ol</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-list"</span>&gt;</span>
                                            <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                                                population:{" "}
                                                <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.population}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                                            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                                            <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                                                Region: <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.region}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                                            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                                            <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                                                Capital: <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.capital}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                                            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                                        <span class="hljs-tag">&lt;/<span class="hljs-name">ol</span>&gt;</span>
                                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">article</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                        ))}
                    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
            );
        }
    }

    ReactDOM.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>, <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
</code></pre>
<p>Here is the live preview of this in Codepen:</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/Spruce_khalifa/embed/ZELeWoN" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p> </p>
<p>Now that we have successfully fetched and displayed the data from our REST COUNTRIES API, we can now concentrate on searching through the countries that are being displayed.</p>
<p>But before we do that let's style the above example with CSS (because it looks ugly when displayed like this).</p>
<p>When we add CSS to the above example we have something that looks like the example below:</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/Spruce_khalifa/embed/zYNZBBB" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p> </p>
<p>Though the CSS we've added is not perfect, it displays the countries in a neater way than the former, I hope you agree?</p>
<h2 id="heading-how-to-build-the-search-component">How to Build the Search Component</h2>
<p>Inside our APP function we use the <code>useState()</code> hooks to set the query <code>q</code> to an empty string. We also have the <code>setQ</code> which we’ll use to bind the value from our search form.‌‌</p>
<p>On <code>line 13</code> we use the <code>useState</code> to define an array of defaults value we want to be able to search from the API. This means that we want to be able to search any Country by its <code>Capital</code> and its <code>name</code> only. You can always make this array longer depending on your preference.</p>
<pre><code class="lang-js">        <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-literal">null</span>);
        <span class="hljs-keyword">const</span> [isLoaded, setIsLoaded] = useState(<span class="hljs-literal">false</span>);
        <span class="hljs-keyword">const</span> [items, setItems] = useState([]);

        <span class="hljs-comment">//     set search query to empty string</span>
        <span class="hljs-keyword">const</span> [q, setQ] = useState(<span class="hljs-string">""</span>);
        <span class="hljs-comment">//     set search parameters</span>
        <span class="hljs-comment">//     we only what to search countries by capital and name</span>
        <span class="hljs-comment">//     this list can be longer if you want</span>
        <span class="hljs-comment">//     you can search countries even by their population</span>
        <span class="hljs-comment">// just add it to this array</span>
        <span class="hljs-keyword">const</span> [searchParam] = useState([<span class="hljs-string">"capital"</span>, <span class="hljs-string">"name"</span>]);

        useEffect(<span class="hljs-function">() =&gt;</span> {
            <span class="hljs-comment">// our fetch codes</span>
        }, []);

     }
</code></pre>
<p>Inside our return function we'll create the search form and our code now looks like this:</p>
<pre><code class="lang-js">            <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;&gt;</span>{error.message}<span class="hljs-tag">&lt;/&gt;</span></span>;
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!isLoaded) {
            <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;&gt;</span>loading...<span class="hljs-tag">&lt;/&gt;</span></span>;
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> (
                <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"wrapper"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"search-wrapper"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"search-form"</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                                <span class="hljs-attr">type</span>=<span class="hljs-string">"search"</span>
                                <span class="hljs-attr">name</span>=<span class="hljs-string">"search-form"</span>
                                <span class="hljs-attr">id</span>=<span class="hljs-string">"search-form"</span>
                                <span class="hljs-attr">className</span>=<span class="hljs-string">"search-input"</span>
                                <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Search for..."</span>
                                <span class="hljs-attr">value</span>=<span class="hljs-string">{q}</span>
                                /*
                                // <span class="hljs-attr">set</span> <span class="hljs-attr">the</span> <span class="hljs-attr">value</span> <span class="hljs-attr">of</span> <span class="hljs-attr">our</span> <span class="hljs-attr">useState</span> <span class="hljs-attr">q</span>
                                //  <span class="hljs-attr">anytime</span> <span class="hljs-attr">the</span> <span class="hljs-attr">user</span> <span class="hljs-attr">types</span> <span class="hljs-attr">in</span> <span class="hljs-attr">the</span> <span class="hljs-attr">search</span> <span class="hljs-attr">box</span>
                                */
                                <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setQ(e.target.value)}
                            /&gt;
                            <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"sr-only"</span>&gt;</span>Search countries here<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-grid"</span>&gt;</span>
                        {items.map((item) =&gt; (
                            <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">article</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.callingCodes}</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-image"</span>&gt;</span>
                                        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{item.flag}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">{item.name}</span> /&gt;</span>
                                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-content"</span>&gt;</span>
                                        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-name"</span>&gt;</span>{item.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                                        <span class="hljs-tag">&lt;<span class="hljs-name">ol</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-list"</span>&gt;</span>
                                            <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                                                population:{" "}
                                                <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.population}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                                            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                                            <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                                                Region: <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.region}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                                            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                                            <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
                                                Capital: <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{item.capital}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                                            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                                        <span class="hljs-tag">&lt;/<span class="hljs-name">ol</span>&gt;</span>
                                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">article</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                        ))}
                    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
            );
        }
    }

    ReactDOM.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>, <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
</code></pre>
<p>Now we’ll create a function to handle our Search and place it above our return (the code above).</p>
<pre><code class="lang-js">            <span class="hljs-keyword">return</span> items.filter(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
                <span class="hljs-keyword">return</span> searchParam.some(<span class="hljs-function">(<span class="hljs-params">newItem</span>) =&gt;</span> {
                    <span class="hljs-keyword">return</span> (
                        item[newItem]
                            .toString()
                            .toLowerCase()
                            .indexOf(q.toLowerCase()) &gt; <span class="hljs-number">-1</span>
                    );
                });
            });
        }
</code></pre>
<p>This function takes in our fetched items and returns all the items that match anything in our <code>searchParam</code> array if the <code>indexOF()</code> is <code>&gt; -1</code>.</p>
<p>Now that the function is set up, to use it we'll wrap the returned data with our search function.</p>
<p><code>{serach(items).map((item) =&gt; ( &lt;li&gt; // card goes here &lt;/li&gt; ))}</code>‌</p>
<p>Now the data stored in our <code>useState()</code> is going to be filtered in our search function before it gets passed to the list items, thereby only returning items that match our query.</p>
<p>Here is the code when put together and the live preview on Codepen. Try using the search form below to search for any country by it’s name or capital.</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/Spruce_khalifa/embed/wvgJWdO?editors=0010" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-how-to-filter-countries-by-region">How to Filter Countries by Region</h2>
<p>Now we can take this further by filtering the countries by their region. Say we don't want to display all the countries, we just want to display and be able to search for countries only in <code>Africa</code> or <code>Asia</code>. You can achieve this by using the <code>useState()</code> hook in React.</p>
<h3 id="heading-regions">Regions:</h3>
<ol>
<li><p>Africa</p>
</li>
<li><p>America</p>
</li>
<li><p>Asia</p>
</li>
<li><p>Europe</p>
</li>
<li><p>Oceania</p>
</li>
</ol>
<p>Now that we know our regions, let's create our filter component. First we set the <code>useState</code> of the filter like this:</p>
<p><code>const [filterParam, setFilterParam] = useState(["All"]);</code>‌</p>
<p>Notice that we set the useState default to <code>ALL</code> on purpose, as we want to be able to display and search all countries if no region is specified.</p>
<pre><code class="lang-js">       &lt;select
    <span class="hljs-comment">/*
    // here we create a basic select input
    // we set the value to the selected value
    // and update the setFilterParam() state every time onChange is called
    */</span>
      onChange={<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
      setFilterParam(e.target.value);
       }}
       className=<span class="hljs-string">"custom-select"</span>
       aria-label=<span class="hljs-string">"Filter Countries By Region"</span>&gt;
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"All"</span>&gt;</span>Filter By Region<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span></span>
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Africa"</span>&gt;</span>Africa<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span></span>
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Americas"</span>&gt;</span>America<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span></span>
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Asia"</span>&gt;</span>Asia<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span></span>
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Europe"</span>&gt;</span>Europe<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span></span>
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Oceania"</span>&gt;</span>Oceania<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span></span>
        &lt;/select&gt;
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"focus"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>
        &lt;/div&gt;
</code></pre>
<p>Now that we have created our filter, all that is left is to modify the <code>search function</code>. Basically we check the region entered and only return the countries that have that region:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">search</span>(<span class="hljs-params">items</span>) </span>{
       <span class="hljs-keyword">return</span> items.filter(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> {
    <span class="hljs-comment">/*
    // in here we check if our region is equal to our c state
    // if it's equal to then only return the items that match
    // if not return All the countries
    */</span>
       <span class="hljs-keyword">if</span> (item.region == filterParam) {
           <span class="hljs-keyword">return</span> searchParam.some(<span class="hljs-function">(<span class="hljs-params">newItem</span>) =&gt;</span> {
             <span class="hljs-keyword">return</span> (
               item[newItem]
                   .toString()
                   .toLowerCase()
                   .indexOf(q.toLowerCase()) &gt; <span class="hljs-number">-1</span>
                        );
                    });
                } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (filterParam == <span class="hljs-string">"All"</span>) {
                    <span class="hljs-keyword">return</span> searchParam.some(<span class="hljs-function">(<span class="hljs-params">newItem</span>) =&gt;</span> {
                        <span class="hljs-keyword">return</span> (
                            item[newItem]
                                .toString()
                                .toLowerCase()
                                .indexOf(q.toLowerCase()) &gt; <span class="hljs-number">-1</span>
                        );
                    });
                }
            });
        }
</code></pre>
<p>You can find the full code and live preview on Codepen. Try to filter the countries and watch the results.</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/Spruce_khalifa/embed/BapWzPe?editors=0010%E2%80%8C%E2%80%8C" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p> </p>
<p>Once we add some CSS we can now view the final preview of our React app.</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/Spruce_khalifa/embed/GRrWjmR?editors=0010" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p> </p>
<h1 id="heading-wrapping-up">Wrapping Up</h1>
<p>When you're dealing with large set of data that you need to display to a user, search and filter functions help that user navigate and find important info quickly.</p>
<p>If you have any questions, you can get in touch with me and I'll be happy to chat.</p>
<p>You can find the full preview of this project here at <a target="_blank" href="https://earthly.vercel.app">earthly vercel app</a>. You can follow me on <a target="_blank" href="https://twitter.com/sprucekhalifa">Twitter @sprucekhalifa</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add a Netlify Form to a React App Built with create-react-app ]]>
                </title>
                <description>
                    <![CDATA[ If you are a web developer, at some point you will need to capture information from people who use your website or app. One way of doing so is by using HTML forms. But there are also tons of frameworks out there that you can use to build web apps ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-a-netlify-form-to-a-react-app/</link>
                <guid isPermaLink="false">66d45f6536c45a88f96b7ce3</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ forms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Netlify ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joseph Mawa ]]>
                </dc:creator>
                <pubDate>Mon, 19 Apr 2021 21:20:05 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/04/questions-4304981_1280.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you are a web developer, at some point you will need to capture information from people who use your website or app.</p>
<p>One way of doing so is by using HTML forms. But there are also tons of frameworks out there that you can use to build web apps very quickly.</p>
<p>One such framework is React. You can bootstrap a single page application (SPA) very easily using <code>create-react-app</code> (CRA). Then you can deploy it to platforms such as Netlify, Vercel, Firebase and Digital Ocean in just a couple of steps.</p>
<p>The main focus of this article will be on how to add Netlify form functionality to a React app bootstrapped using <code>create-react-app</code>. At the end of this tutorial you will be able to:</p>
<ul>
<li><p>Quickly set up a single page app using <code>create-react-app</code></p>
</li>
<li><p>Add functionality to utilize Netlify's builtin form handling feature</p>
</li>
<li><p>Deploy the app to Netlify</p>
</li>
<li><p>Configure the builtin form handling feature on Netlify to send email notifications whenever a form has been submitted by a client</p>
</li>
</ul>
<p>Whether you are beginner trying to deploy your first React app or you are an experienced React developer, this article will help you learn to use Netlify's builtin form functionality without writing any server side code.</p>
<p>If you are an experienced React developer, you can skip the introduction and go to <code>step 6</code>. If you are a beginner in React, you can follow along right from the beginning.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along with this article, you should:</p>
<ul>
<li><p>Have an intermediate knowledge of JavaScript. If you are a beginner, you can still follow along and ask questions on the <a target="_blank" href="https://forum.freecodecamp.org">freeCodeCamp forum</a> if there is something you don't understand. You can also copy the code samples in each section and play with them in your text editor to make sense of what is going on.</p>
</li>
<li><p>Have at least basic knowledge of the React library</p>
</li>
<li><p>Have Node installed on your machine</p>
</li>
<li><p>Have a Netlify account. If you don't have one, you can signup for an account at no cost using your email address.</p>
</li>
<li><p>Have a text editor like <a target="_blank" href="https://code.visualstudio.com/">VS code</a> or <a target="_blank" href="https://atom.io/">Atom</a> installed on your machine. You can try out the code samples as you follow along. It will make it easier for you to understand.</p>
</li>
</ul>
<h2 id="heading-step-1-check-whether-you-have-node-and-npm-installed-on-your-machine">Step 1: Check whether you have <code>node</code> and <code>npm</code> installed on your machine</h2>
<p>Before we get started, you should check whether you have <a target="_blank" href="https://nodejs.org/en/">node</a> installed on your machine.</p>
<p>Node is a JavaScript runtime environment, and it's important to have it installed to be able to run the project. Open a terminal and type the following command in the command prompt.</p>
<pre><code class="lang-js">node - v
</code></pre>
<p>Instead of the above command, you can also type the command below. Both of them do the same thing.</p>
<pre><code class="lang-js">node --version
</code></pre>
<p>If Node is installed, you should be able to see the version printed on the terminal. Your version might be different from mine but you should see something like:</p>
<pre><code class="lang-js">v15<span class="hljs-number">.13</span><span class="hljs-number">.0</span>
</code></pre>
<p>If Node is installed, that means <code>npm</code> is also installed because recent versions of Node come with <code>npm</code>. If you are curious, type the command <code>npm --version</code> or <code>npm -v</code>. You should be able to see the version of <code>npm</code> which has been installed.</p>
<p>On the other hand, if you don't have Node installed on your machine, you can download and install for your platform from <a target="_blank" href="https://nodejs.org/en/download/">here</a>.</p>
<h2 id="heading-step-2-navigate-to-the-directory-where-you-want-to-create-your-project">Step 2: Navigate to the directory where you want to create your project</h2>
<p>Next, you need to navigate to a directory where you want to create your project. You can work from the Desktop or from any directory of your choice.</p>
<p>I like keeping my personal projects in a directory called <code>projects</code> on the desktop for easy access. This is just personal choice.</p>
<p>Open the terminal and navigate to the directory where you want to create your project. I am using <code>cd</code> (change directory) in the commands below.</p>
<p><strong>Take note</strong>: I already have a directory named <code>projects</code> on the Desktop. If you don't, you will have to first run the command <code>mkdir projects</code> before you <code>cd</code> into it. Like I said above, you can decide to work from another directory and then you won't have to run the commands below.</p>
<ol>
<li><p><code>cd Desktop</code></p>
</li>
<li><p><code>cd projects</code></p>
</li>
</ol>
<h2 id="heading-step-3-how-to-bootstrap-a-single-page-app-using-create-react-app">Step 3: How to bootstrap a single page app using <code>create-react-app</code></h2>
<p>How we are going to bootstrap a React project using <code>create-react-app</code>. In the directory where you want to create your project, run the command below.</p>
<pre><code class="lang-js">npx create-react-app netlify-form
</code></pre>
<p>I have named the project <code>netlify-form</code>. You can give it a different name if you wish.</p>
<p>If you don't have <code>create-react-app</code> installed, you will see a prompt on the terminal asking whether it should be installed. Type <code>Y</code> on the command prompt (for "Yes"). It will install <code>create-react-app</code> and then create a React project in the <code>netlify-form</code> directory.</p>
<p>If you already have <code>create-react-app</code> in your system, it will go straight to creating a React project in the <code>netlify-form</code> directory. This will take a couple of minutes, so just be patient.</p>
<p>In the next step, you will start the development server.</p>
<h2 id="heading-step-4-start-the-development-server">Step 4: Start the development server</h2>
<p>In this step, we are going to start the development server. This ensures hot reloading when we make changes to the project during development so that we are able to see how our project is taking shape.</p>
<p>You can open the <code>netlify-form</code> directory in your text editor of choice. When you are in <code>netlify-form</code>, open the terminal and run the command below.</p>
<pre><code class="lang-js">npm run start
</code></pre>
<p>The above command starts the development server on port 3000. If there is another project or service running on port 3000, you will be prompted to start the server on another port.</p>
<p>A new browser tab will be opened in your default browser where you can see the project. Any changes you make will automatically be reflected in the browser.</p>
<p>In the next step, you are going to create a component which will contain your form.</p>
<h2 id="heading-step-5-create-a-new-component-inside-the-src-directory">Step 5: Create a new component inside the <code>src</code> directory</h2>
<p>Now you are going to create a component named <code>Form</code> inside the <code>src</code> directory. In this component, you will have the form which will be rendered in your app.</p>
<p>Create a <code>Form.js</code> file in the <code>src</code> directory then copy and paste the code below in it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Form</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"contact"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"name"</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">required</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"email"</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">required</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"message"</span>&gt;</span>Message<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"message"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"message"</span> <span class="hljs-attr">required</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Submit message"</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}
</code></pre>
<p>The above component returns an ordinary form. I have enclosed each label-input pair and label-textarea pair in its own <code>p</code> tag.</p>
<p>There is nothing special about the <code>p</code> tag. You can use <code>div</code> if you wish. I just used it because I want to apply spacing between successive label-input pairs without using CSS.</p>
<p>You can import the <code>Form</code> component and render it inside <code>App</code>. To clean up <code>App.js</code>, you can also delete some items which come with <code>create-react-app</code>, so that it looks like:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;
<span class="hljs-keyword">import</span> Form <span class="hljs-keyword">from</span> <span class="hljs-string">"./Form"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> Get in touch <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Form</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>You can also clean up <code>App.css</code> so that it has only the following CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.App</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1em</span>;
}
</code></pre>
<p>When you check your form in the browser it should look like the image below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/Screenshot-from-2021-04-17-14-30-11.png" alt="Screenshot-from-2021-04-17-14-30-11" width="600" height="400" loading="lazy"></p>
<p>Right now deploying that app to Netlify won't enable us to capture a client's form submissions. To do that, we need to add necessary information to our app so that Netlify's bots will be able to detect our form.</p>
<p>In the next step, we are going to add all the necessary information to make the JSX <code>form</code> in React detectable by Netlify.</p>
<h2 id="heading-step-6-add-necessary-information-to-make-the-form-detectable-by-netlifys-bots">Step 6: Add necessary information to make the <code>form</code> detectable by Netlify's bots</h2>
<p>In this step, you are going to add some information to your app so that Netlify will be able to detect your app's form setup. If your form is deployed in plain HTML, the process of making it detectable is quite simple. You can read about it in the <a target="_blank" href="https://docs.netlify.com/forms/setup/?_ga=2.214149207.1369394306.1618461268-796209470.1617367540">documentation</a>.</p>
<p>But if you are dealing with a JSX form in React like in this simple app we are building, then you will have to do a bit more work. You can follow the steps outlined below.</p>
<h3 id="heading-add-the-html-version-of-the-form-to-the-indexhtml-file">Add the HTML version of the form to the <code>index.html</code> file</h3>
<p>Copy and paste your JSX form into the <code>index.html</code> file just after the opening <code>body</code> tag. This will ensure that Netlify detects our form because build bots parse the HTML files directly at deploy time. The JSX form cannot be parsed by the bots.</p>
<p>You can remove the <code>label</code> elements and the <code>submit</code> input element because we will add a <code>hidden</code> attribute to the <code>form</code> so that it is not visible to users and screen readers.</p>
<p>You can only leave the <code>type</code> and <code>name</code> attributes on the <code>input</code> elements and <code>name</code> attribute on <code>textarea</code> so that we keep the form minimal.</p>
<p>This is illustrated in the code below:</p>
<pre><code class="lang-HTML"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"contact"</span> <span class="hljs-attr">netlify</span> <span class="hljs-attr">netlify-honeypot</span>=<span class="hljs-string">"bot-field"</span> <span class="hljs-attr">hidden</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>  <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"message"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>As you can see in the above code snippet, there are additional attributes <code>netlify</code> and <code>netlify-honeypot</code> on the <code>form</code>. Netlify bots will use them while parsing your HTML so make sure to add them.</p>
<p>Do not forget to add the <code>hidden</code> attribute, because this form needs to be hidden from the users of your website. It is also worth pointing out that the name attributes in the HTML form must be exactly the same as those in the corresponding JSX form.</p>
<h3 id="heading-add-a-hidden-input-element-in-your-jsx-form">Add a hidden <code>input</code> element in your JSX form</h3>
<p>You also need to add a hidden <code>input</code> element in your JSX form with the attributes <code>name</code> and <code>value</code> as illustrated in the code below:</p>
<pre><code class="lang-HTML"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"form-name"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"contact"</span> /&gt;</span>
</code></pre>
<p>The value of the <code>name</code> attribute should always be <code>"form-name"</code> and the value of the <code>value</code> attribute should be the name of the HTML form, which in our case is <code>contact</code>.</p>
<p>Your <code>Form.js</code> file should now look like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Form</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"contact"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"form-name"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"contact"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"name"</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">required</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"email"</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">required</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"message"</span>&gt;</span>Message<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"message"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"message"</span> <span class="hljs-attr">required</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Submit message"</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}
</code></pre>
<p>If you check the app in the browser, you should be able to see the form – but you won't be able to submit it from your local setup. You can only submit forms after deploying your app to Netlify.</p>
<p>So let's do that now.</p>
<h2 id="heading-step-7-deploy-the-app-to-netlify">Step 7: Deploy the app to Netlify</h2>
<p>In this step, you are going to deploy our app to Netlify so that you are able to test whether clients can make form submissions.</p>
<p>There are a couple of ways you can deploy your app to Netlify. One method is by building the app locally and deploying it from the command line, or by dragging and dropping the production build to Netlify. The second method is by configuring automatic deployment via GitHub, BitBucket, or GitLab.</p>
<p>In this app, you will build the app locally and use the simplest method of dragging and dropping. This step requires you to login to your Netlify account. If you don't have an account, you can signup for one.</p>
<p>Run the command <code>npm run build</code> in the terminal. This will build the app for production to the <code>build</code> folder. This will take a bit of time. You should be able to see the <code>build</code> directory after running the command successfully.</p>
<p>Login to your Netlify account. On the Netlify dashboard, click the <code>Sites</code> menu item. At the bottom of the page, there is an area where you can drag and drop the production build of your app. After dragging and dropping the <code>build</code> folder, the build process begins.</p>
<p>After the site is built successfully, you can check the project dashboard to find out whether Netlify is detecting your form. If it is detecting the form, you will usually see a message stating so in the forms section at the bottom left.</p>
<p>What is left for you to do is to fill out the form and submit it. After submission, you should be able to see the information submitted.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/Screenshot-from-2021-04-17-14-03-26.png" alt="Screenshot-from-2021-04-17-14-03-26" width="600" height="400" loading="lazy"></p>
<p>Next, we'll learn how to configure email alerts so you get notified whenever a user submits a form.</p>
<h2 id="heading-step-8-configure-email-updates-whenever-a-user-submits-a-form">Step 8: Configure email updates whenever a user submits a form</h2>
<p>In this section, you will configure your app to send email notifications to an email address whenever a form is submitted.</p>
<p>To do this, navigate to the site settings. On the left, you will see a list of menu items. Click the <code>forms</code> option.</p>
<p>Under <code>outgoing notifications</code>, click <code>Add notification</code> and select the <code>Email notification</code> option. You will then configure your preferences accordingly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/Screenshot-from-2021-04-17-14-11-20.png" alt="Screenshot-from-2021-04-17-14-11-20" width="600" height="400" loading="lazy"></p>
<p>That is all you need to do to use Netlify's builtin form functionality with CRA. You don't need server side code to get feedback from your clients.</p>
<p>If you have managed to successfully follow the above steps, congratulations! You can now go ahead and explore other features.</p>
<p>If you encounter errors or issues relating to Netlify forms while following this tutorial, feel free to check out <a target="_blank" href="https://answers.netlify.com/t/support-guide-form-problems-form-debugging-404-when-submitting/92">this netlify form error debugging tip</a>.</p>
<p>You can also read the <a target="_blank" href="https://docs.netlify.com/forms/setup/">netlify forms documentation</a>.</p>
<p>If you fail to find a solution after using the above resources, you can ask a quesion in the <a target="_blank" href="https://answers.netlify.com/">netlify forum</a>. There are quite a number of friendly folks in that community who might help you out.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we look looked at:</p>
<ul>
<li><p>How to create a React app using <code>create-react-app</code></p>
</li>
<li><p>How to add a JSX form to your React app</p>
</li>
<li><p>How to add necessary information so that your form can be detected by Netlify's bots</p>
</li>
<li><p>How to deploy a production build to Netlify</p>
</li>
<li><p>How to set up email notifications whenever a client submits a form</p>
</li>
</ul>
<h3 id="heading-references">References</h3>
<ul>
<li><p><a target="_blank" href="https://docs.netlify.com/forms/setup/">Netlify forms documentation</a></p>
</li>
<li><p><a target="_blank" href="https://create-react-app.dev/">Create react app documentation</a></p>
</li>
<li><p><a target="_blank" href="https://reactjs.org/docs/getting-started.html">React documentation</a></p>
</li>
<li><p><a target="_blank" href="https://answers.netlify.com/t/support-guide-form-problems-form-debugging-404-when-submitting/92">Netlify form error debugging</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Solid To-Do App with React ]]>
                </title>
                <description>
                    <![CDATA[ By Virginia Balseiro In this tutorial you will learn how to create a basic Solid to-do app. But what is Solid – not to be confused with SOLID? Well, it's a set of conventions and tools used to build decentralized apps.   So what do I mean by decentra... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-a-solid-to-do-app-with-react/</link>
                <guid isPermaLink="false">66d461713a8352b6c5a2ab27</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 02 Mar 2021 16:37:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/603a6472a675540a229246bc.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Virginia Balseiro</p>
<p>In this tutorial you will learn how to create a basic <a target="_blank" href="https://solidproject.org/about">Solid</a> to-do app. But what is Solid – not to be confused with <a target="_blank" href="https://www.freecodecamp.org/news/solid-principles-explained-in-plain-english/">SOLID</a>? Well, it's a set of conventions and tools used to build decentralized apps.  </p>
<p>So what do I mean by decentralized? Currently, all our data is centralized in a few web platforms: Facebook, Google, and others. This has various consequences for privacy that we're all aware of, but it also endangers the principle of universality of the web: the web must be accessible to everyone.   </p>
<p>Let me illustrate this with an example: if my German teacher decides to create a Facebook group to share class materials, I need to have a Facebook account to access it. Likewise, if the teacher decides to quit Facebook, she needs to move the students to another app along with the data.   </p>
<p>With Solid, the data and the app are decoupled. The data lives in one place and the app reads and write to that place. The user controls where that data is, and with which people or apps they want to share it with. Users can decide which apps to use based on which ones suit their needs better, and they have full control of their data. </p>
<p>This has many advantages for developers as well, because competition is then based on the quality of an app, as opposed to how much user data you control.</p>
<p>And for frontend developers there's the added bonus of not having to worry about setting up a database if you want to save user data.</p>
<p>This tutorial will help you become familiar with some of the tools available to write Solid applications. We will use the following libraries:</p>
<ul>
<li><a target="_blank" href="https://docs.inrupt.com/developer-tools/javascript/client-libraries/tutorial/read-write-data/">solid-client</a>: Library to read and write data in Solid Pods</li>
<li><a target="_blank" href="https://docs.inrupt.com/developer-tools/javascript/react-sdk/">solid-ui-react</a>: Library of UI components that make it easier to interact with the data.</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>This tutorial assumes a basic knowledge of React.</p>
<p>You will also need to <a target="_blank" href="https://solidproject.org/users/get-a-pod">have your own Pod</a>. You can create it beforehand, or as part of the login process when we add authentication to the to-do app, by registering instead of logging in.</p>
<p>Here's a link to the repository where you can find the code: <a target="_blank" href="https://github.com/VirginiaBalseiro/solid-todo-tutorial">https://github.com/VirginiaBalseiro/solid-todo-tutorial</a></p>
<p>And here's a link to CodeSandbox: <a target="_blank" href="https://codesandbox.io/s/solid-todo-tutorial-7uz4j">https://codesandbox.io/s/solid-todo-tutorial-7uz4j</a>. If you want to test the app on CodeSandbox, just make sure to open it on a separate tab.</p>
<h1 id="heading-getting-started">Getting started</h1>
<p>We will start by creating a React app using <a target="_blank" href="https://create-react-app.dev/">create-react-app.</a> This will create a new directory with your app's name within the directory you run it from. So navigate to the directory where you keep you projects and run:</p>
<pre><code class="lang-jsx">npx create-react-app solid-todo-tutorial
</code></pre>
<p>This creates a new directory named <code>solid-todo-tutorial</code>. Go to that directory and install the two Solid libraries I mentioned before:</p>
<pre><code class="lang-jsx">cd solid-todo-tutorial
npm install @inrupt/solid-client @inrupt/solid-ui-react
</code></pre>
<p>Now we're ready to start coding.</p>
<h1 id="heading-how-to-authenticate-a-user">How to Authenticate a User</h1>
<p>I left the class names in these snippets in case you would like to use the stylesheets available in the repository.</p>
<h3 id="heading-how-to-use-the-loginbutton-component-to-log-users-in">How to Use the LoginButton Component to Log Users In</h3>
<p>The first thing we need to do in order to be able to write to our Pod is to authenticate as a user with write permissions (so that we have the permissions to do so). Luckily this is very straightforward using the <a target="_blank" href="https://solid-ui-react.docs.inrupt.com/?path=/story/authentication-login-button--with-children">login button</a> from <code>solid-ui-react</code>.</p>
<p>We need to import <code>LoginButton</code> from <code>solid-ui-react</code>. This component accepts two required props: <code>oidcIssuer</code>, the Pod provider, and a <code>redirectUrl</code> which is the URL we want to be redirected to after we login.</p>
<p>We will get the Pod provider as a string from the user through a text input box, and we will also provide some Pod provider options.</p>
<p>The <code>LoginButton</code> also takes an optional <code>authOptions</code> prop, which is an object with the <code>clientName</code> property. This is useful because we want to display our app's name to the user when they authenticate. </p>
<p>If we don't pass the <code>clientName</code>, a random string will be generated which is confusing for the user when they're granting our app permission to do things.</p>
<p>In <code>App.js</code> let's get rid of all the boilerplate that comes with our React app and use the <code>LoginButton</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// App.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { LoginButton } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;

<span class="hljs-keyword">const</span> authOptions = {
    <span class="hljs-attr">clientName</span>: <span class="hljs-string">"Solid Todo App"</span>,
  };

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">const</span> [oidcIssuer, setOidcIssuer] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    setOidcIssuer(event.target.value);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"app-container"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
            Log in with:
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"oidc-issuer-input "</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"oidcIssuer"</span>
              <span class="hljs-attr">list</span>=<span class="hljs-string">"providers"</span>
              <span class="hljs-attr">value</span>=<span class="hljs-string">{oidcIssuer}</span>
              <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span>
            /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">datalist</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"providers"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"https://broker.pod.inrupt.com/"</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"https://inrupt.net/"</span> /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">datalist</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">LoginButton</span>
             <span class="hljs-attr">oidcIssuer</span>=<span class="hljs-string">{oidcIssuer}</span>
             <span class="hljs-attr">redirectUrl</span>=<span class="hljs-string">{window.location.href}</span>
             <span class="hljs-attr">authOptions</span>=<span class="hljs-string">{authOptions}</span>
           /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>In the <code>index.js</code> file, let's wrap our App component with the <code>SessionProvider</code> component. Now, we can use the <code>useSession</code> hook throughout the entire app, which returns session info that allows us to make authenticated requests.</p>
<p>Replace the boilerplate in <code>index.js</code> with the following:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// index.js</span>

<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App"</span>;
<span class="hljs-keyword">import</span> { SessionProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;

ReactDOM.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">SessionProvider</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">SessionProvider</span>&gt;</span></span>,
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>)
);
</code></pre>
<p>Once that is done, you can test it! Run your app with <code>npm start</code> and click on the Login button. It should take you to a page where you can either log in or register. If you don't have an account, you can click on "Sign up" to create one. </p>
<p>Once you log in, you will be redirected to the main page. As you can see, our main page only has the login button. We are logged in, but we don't do anything with that information. Let's change that!</p>
<h3 id="heading-how-to-use-profile-data">How to Use Profile Data</h3>
<p>We're going to change our code so our app shows the login button if we're logged out, and our name if we're logged in.</p>
<p>For this we're going to use <code>CombinedDatasetProvider</code> and <code>Text</code> from <code>solid-ui-react</code>. <code>CombinedDatasetProvider</code> needs two props: <code>datasetUrl</code> and <code>thingUrl</code> which, in this case, can both be set to the user's WebID.</p>
<p>A <strong>WebID</strong> is an HTTP URI which refers to an agent (for example, a person), that, when looked up, resolves to a profile document.</p>
<p><code>CombinedDatasetProvider</code> fetches the dataset and Thing for us so we can pass it straight on to the children.</p>
<p>The child in our app will be the <code>Text</code> component</p>
<p>The <code>Text</code> component takes a prop, either <code>property</code> or <code>properties</code>, that specifies the value to retrieve and display from the fetched dataset/thing. </p>
<p>In our case, we want the Text component to retrieve and display the name of the user from the user's profile. <code>property</code> or <code>properties</code> is the URL or URLs we have chosen for the <strong>predicate</strong> for which we want to fetch the data.</p>
<p>In our case we want to get the name of the user.</p>
<p>A user's profile data is stored as <a target="_blank" href="https://www.w3.org/RDF/">Resource Description Framework (RDF)</a> data. RDF is a standard model for data interchange on the Web. RDF data is stored in <strong>triples</strong>, which are composed of a <strong>subject</strong>, a <strong>predicate</strong> and an <strong>object</strong>. </p>
<p>So, for instance, if I want to write a social networking app and I want to store Bob's acquaintances, I could add one like so: <code>&lt;http://example.org/bob#me&gt; &lt;http://xmlns.com/foaf/0.1/knows&gt; &lt;http://example.org/alice#me&gt; .</code></p>
<p>In this case, <code>&lt;http://example.org/bob#me&gt;</code> is the subject, <code>&lt;http://xmlns.com/foaf/0.1/knows&gt;</code>  is the predicate, and <code>&lt;http://example.org/alice#me&gt;</code> is the object.</p>
<p>To specify that we want to retrieve the name, we use a name identifier. In our example, we use a name identifier from an existing Vocabulary.</p>
<p>Vocabularies are collections of identifiers (URIs) with a clearly-defined meaning. An example of a popular vocabulary is <strong><a target="_blank" href="http://xmlns.com/foaf/spec/">FOAF (Friend Of A Friend)</a></strong>, which defines URIs to describe people and their relationships. </p>
<p>You can find more information about vocabularies in <a target="_blank" href="https://solidproject.org/developers/vocabularies">the Solid Project website</a>.</p>
<p>The name of the logged in user, in most cases, will be stored in the profile document under "<a target="_blank" href="http://www.w3.org/2006/vcard/ns#fn">http://www.w3.org/2006/vcard/ns#fn</a>" or "<a target="_blank" href="http://xmlns.com/foaf/0.1/name">http://xmlns.com/foaf/0.1/name</a>". <code>fn</code> stands for formatted name. In RDF, that looks like this:</p>
<pre><code class="lang-jsx">:me &lt;http:<span class="hljs-comment">//www.w3.org/2006/vcard/ns#fn&gt; "Virginia Balseiro" .</span>
</code></pre>
<p>or</p>
<pre><code class="lang-jsx">:me &lt;[<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">http:</span>//<span class="hljs-attr">xmlns.com</span>/<span class="hljs-attr">foaf</span>/<span class="hljs-attr">0.1</span>/<span class="hljs-attr">name</span>&gt;</span></span>](<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">http:</span>//<span class="hljs-attr">xmlns.com</span>/<span class="hljs-attr">foaf</span>/<span class="hljs-attr">0.1</span>/<span class="hljs-attr">name</span>&gt;</span></span>)&gt; <span class="hljs-string">"Virginia Balseiro"</span>
</code></pre>
<p>But in our case we want it to check under <a target="_blank" href="http://www.w3.org/2006/vcard/ns#fn"><code>http://www.w3.org/2006/vcard/ns#fn</code></a> and if it cannot find anything, check under <a target="_blank" href="http://xmlns.com/foaf/0.1/name"><code>http://xmlns.com/foaf/0.1/name</code></a>. We can use <code>properties</code>, which is an array of properties to attempt to read from, in our <code>Text</code> component.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// App.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> {
  LoginButton,
  Text,
  useSession,
  CombinedDataProvider,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;

<span class="hljs-keyword">const</span> authOptions = {
    <span class="hljs-attr">clientName</span>: <span class="hljs-string">"Solid Todo App"</span>,
  };

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { session } = useSession();
  <span class="hljs-keyword">const</span> [oidcIssuer, setOidcIssuer] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    setOidcIssuer(event.target.value);
  };
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"app-container"</span>&gt;</span>
      {session.info.isLoggedIn ? (
        <span class="hljs-tag">&lt;<span class="hljs-name">CombinedDataProvider</span>
          <span class="hljs-attr">datasetUrl</span>=<span class="hljs-string">{session.info.webId}</span>
          <span class="hljs-attr">thingUrl</span>=<span class="hljs-string">{session.info.webId}</span>
        &gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"message logged-in"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>You are logged in as: <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">properties</span>=<span class="hljs-string">{[</span>
                "<span class="hljs-attr">http:</span>//<span class="hljs-attr">www.w3.org</span>/<span class="hljs-attr">2006</span>/<span class="hljs-attr">vcard</span>/<span class="hljs-attr">ns</span>#<span class="hljs-attr">fn</span>",
                "<span class="hljs-attr">http:</span>//<span class="hljs-attr">xmlns.com</span>/<span class="hljs-attr">foaf</span>/<span class="hljs-attr">0.1</span>/<span class="hljs-attr">name</span>",
              ]} /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">CombinedDataProvider</span>&gt;</span>
      ) : (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"message"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>You are not logged in. <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
            Log in with:
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"oidc-issuer-input "</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"oidcIssuer"</span>
              <span class="hljs-attr">list</span>=<span class="hljs-string">"providers"</span>
              <span class="hljs-attr">value</span>=<span class="hljs-string">{oidcIssuer}</span>
              <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span>
            /&gt;</span>
           <span class="hljs-tag">&lt;<span class="hljs-name">datalist</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"providers"</span>&gt;</span>
             <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"https://broker.pod.inrupt.com/"</span> /&gt;</span>
             <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"https://inrupt.net/"</span> /&gt;</span>
           <span class="hljs-tag">&lt;/<span class="hljs-name">datalist</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">LoginButton</span>
            <span class="hljs-attr">oidcIssuer</span>=<span class="hljs-string">{oidcIssuer}</span>
            <span class="hljs-attr">redirectUrl</span>=<span class="hljs-string">{window.location.href}</span>
            <span class="hljs-attr">authOptions</span>=<span class="hljs-string">{authOptions}</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>We can now log in and display info from our Pod in our app.</p>
<h3 id="heading-how-to-log-users-out">How to Log Users Out</h3>
<p>Let's now add a <a target="_blank" href="https://solid-ui-react.vercel.app/?path=/story/authentication-logout-button--with-children">logout button</a> so we can log out whenever we want to. This is easy: we just need to import the <code>LogoutButton</code> from <code>solid-ui-react</code> and display it underneath the Text with the user name:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// App.js</span>

<span class="hljs-keyword">import</span> {
  LoginButton,
  LogoutButton,
  Text,
  useSession,
  CombinedDataProvider,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { session } = useSession();

    <span class="hljs-comment">// ...</span>

    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"message logged-in"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>You are logged in as: <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">properties</span>=<span class="hljs-string">{[</span>
         "<span class="hljs-attr">http:</span>//<span class="hljs-attr">xmlns.com</span>/<span class="hljs-attr">foaf</span>/<span class="hljs-attr">0.1</span>/<span class="hljs-attr">name</span>",
         "<span class="hljs-attr">http:</span>//<span class="hljs-attr">www.w3.org</span>/<span class="hljs-attr">2006</span>/<span class="hljs-attr">vcard</span>/<span class="hljs-attr">ns</span>#<span class="hljs-attr">fn</span>",
       ]} /&gt;</span>    
       <span class="hljs-tag">&lt;<span class="hljs-name">LogoutButton</span> /&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>

    <span class="hljs-comment">// ...</span>

}
</code></pre>
<h1 id="heading-how-to-create-a-to-do">How to Create a To-Do</h1>
<h3 id="heading-how-to-add-an-add-todo-button">How to Add an "Add Todo" button</h3>
<p>To create a to-do item we are going to need a button that triggers a function which adds a to-do item to our to-do list. Let's put all of the logic and UI to add a to-do into a separate component in <code>src/components/AddTodo/index.js</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/AddTodo/index.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AddTodo</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"add-button"</span>&gt;</span>Add Todo<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AddTodo;
</code></pre>
<p>In our App, we are going to display this <code>AddTodo</code> button to logged-in users only:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// App.js</span>

<span class="hljs-keyword">import</span> AddTodo <span class="hljs-keyword">from</span> <span class="hljs-string">"../src/components/AddTodo"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-comment">// ...</span>
      {session.info.isLoggedIn ? (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CombinedDataProvider</span>
          <span class="hljs-attr">datasetUrl</span>=<span class="hljs-string">{session.info.webId}</span>
          <span class="hljs-attr">thingUrl</span>=<span class="hljs-string">{session.info.webId}</span>
        &gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"message logged-in"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>You are logged in as: <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>
              <span class="hljs-attr">properties</span>=<span class="hljs-string">{[</span>
                "<span class="hljs-attr">http:</span>//<span class="hljs-attr">xmlns.com</span>/<span class="hljs-attr">foaf</span>/<span class="hljs-attr">0.1</span>/<span class="hljs-attr">name</span>",
                "<span class="hljs-attr">http:</span>//<span class="hljs-attr">www.w3.org</span>/<span class="hljs-attr">2006</span>/<span class="hljs-attr">vcard</span>/<span class="hljs-attr">ns</span>#<span class="hljs-attr">fn</span>",
              ]} /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">LogoutButton</span> /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">AddTodo</span> /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">CombinedDataProvider</span>&gt;</span></span>
      ) : 
<span class="hljs-comment">// ...</span>
}
</code></pre>
<p>For now this button doesn't do anything. Let's change that.</p>
<h3 id="heading-how-to-initialize-the-to-dos-dataset">How to Initialize the To-Dos Dataset</h3>
<p>In formal terms, each of our to-do items will be structured as <strong>things</strong> that are grouped inside a <strong>dataset.</strong> So first we need to check if the dataset already exists, and if not, we must create it. </p>
<p>Let's write a function that does this, assuming our structured data will be stored in a folder called "todos" in the root of our pod.</p>
<p>The proper way to do this would be to check the profile (that is, the data at the user's WebID), look for a URL for a known predicate (for example <code>myVocab:todolistContainer</code>), and then follow that link to get to this folder. </p>
<p>Only if no such link exists would the app initialize its own folder - and after initialization, it would link back to that from the user's WebID. </p>
<p>For that we would need to create a new vocab, and for simplicity's sake that is not included in this tutorial.</p>
<p>Let's put this function in <code>src/utils/index.js</code> because we might use it again in the future somewhere aside from our <code>AddTodo</code> component.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// utils/index.js</span>

<span class="hljs-keyword">import</span> {
  createSolidDataset,
  getSolidDataset,
  saveSolidDatasetAt,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-client"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getOrCreateTodoList</span>(<span class="hljs-params">containerUri, fetch</span>) </span>{
  <span class="hljs-keyword">const</span> indexUrl = <span class="hljs-string">`<span class="hljs-subst">${containerUri}</span>index.ttl`</span>;
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> todoList = <span class="hljs-keyword">await</span> getSolidDataset(indexUrl, { fetch });
    <span class="hljs-keyword">return</span> todoList;
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-keyword">if</span> (error.statusCode === <span class="hljs-number">404</span>) {
      <span class="hljs-keyword">const</span> todoList = <span class="hljs-keyword">await</span> saveSolidDatasetAt(
        indexUrl,
        createSolidDataset(),
        {
          fetch,
        }
      );
      <span class="hljs-keyword">return</span> todoList;
    }
  }
}
</code></pre>
<p>We are using three functions from <code>solid-client</code> here to read and write data in our Pods:</p>
<ul>
<li><code>getSolidDataset</code>: takes the URI of the dataset we want to get, plus an <code>options</code> object where we pass the <code>fetch</code> function. This is a function we get from the session, and it's used to make authenticated requests.</li>
<li><code>createSolidDataset</code>: initializes a new dataset in memory.</li>
<li><code>saveSolidDatasetAt</code>: takes a URI as first param (which is where our dataset will be saved), the dataset in question as second param (in this case a new, empty dataset), and the fetch function.</li>
</ul>
<p>If the to-do list <code>index</code> file is found, our getOrCreateTodoList function will return it. If not (if there is a 404 error), it will create the file at the location given.</p>
<p>Now we can use this function in our <code>AddTodo</code> component. We need to pass it a container URI, which we make by concatenating the Pod URI with the folder name we have chosen to store our to-do list. So first we need to:</p>
<ul>
<li>Fetch the profile dataset using the WebID for the current session (the current user's WebID).</li>
<li>Extract the profile <code>Thing</code> from the profile dataset with the same URL (the user's WebID).</li>
<li>Get the URLs for the user's Pods. For this we use <code>getUrlAll</code>, which returns an array with all the URLs stored under the predicate <code>http://www.w3.org/ns/pim/space#storage</code>. We will assume that the first item in the array is the Pod we want to use.</li>
</ul>
<p>Once we have the container URL, we can now check if the to-do list dataset exists. If it doesn't we can create it, and use it anywhere in the component:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/AddTodo/index.js</span>

<span class="hljs-keyword">import</span> { getSolidDataset, getThing, getUrlAll } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-client"</span>;
<span class="hljs-keyword">import</span> { useSession } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;
<span class="hljs-keyword">import</span> React, { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { getOrCreateTodoList } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../utils"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AddTodo</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { session } = useSession();
  <span class="hljs-keyword">const</span> [todoList, setTodoList] = useState();

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!session) <span class="hljs-keyword">return</span>;
    (<span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> profileDataset = <span class="hljs-keyword">await</span> getSolidDataset(session.info.webId, {
        <span class="hljs-attr">fetch</span>: session.fetch,
      });
      <span class="hljs-keyword">const</span> profileThing = getThing(profileDataset, session.info.webId);
      <span class="hljs-keyword">const</span> podsUrls = getUrlAll(
        profileThing,
        <span class="hljs-string">"http://www.w3.org/ns/pim/space#storage"</span>
      );
      <span class="hljs-keyword">const</span> pod = podsUrls[<span class="hljs-number">0</span>];
      <span class="hljs-keyword">const</span> containerUri = <span class="hljs-string">`<span class="hljs-subst">${pod}</span>todos/`</span>;
      <span class="hljs-keyword">const</span> list = <span class="hljs-keyword">await</span> getOrCreateTodoList(containerUri, session.fetch);
      setTodoList(list);
    })();
  }, [session]);

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"add-button"</span>&gt;</span>Add Todo<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AddTodo;
</code></pre>
<p>To check if it worked, go to <a target="_blank" href="https://podbrowser.inrupt.com/login">PodBrowser</a>, log in by selecting your Pod Provider from the dropdown, enter your username and password, and check that the "todos" folder was created in your Pod.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/image-171.png" alt="Files view in PodBrowser showing the newly created &quot;todos&quot; folder" width="600" height="400" loading="lazy"></p>
<p>If you go into the "todos" container, there should be an <code>index.ttl</code> file in it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/image-173.png" alt="Image" width="600" height="400" loading="lazy">
<em>Files view in PodBrowser showing the newly created "index.tll" file</em></p>
<p>If you click on the <code>index.ttl</code> a drawer will open up to the right with a "Download" link. Click on it to download the file, which you can open with any text editor, such as Notepad. The contents of the file should look like this:</p>
<pre><code class="lang-jsx">@prefix <span class="hljs-keyword">as</span>:    &lt;https://www.w3.org/ns/activitystreams#&gt; .
@prefix rdf:   &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt; .
@prefix xsd:   &lt;http://www.w3.org/2001/XMLSchema#&gt; .
@prefix ldp:   &lt;http://www.w3.org/ns/ldp#&gt; .
@prefix skos:  &lt;http://www.w3.org/2004/02/skos/core#&gt; .
@prefix rdfs:  &lt;http://www.w3.org/2000/01/rdf-schema#&gt; .
@prefix acl:   &lt;http://www.w3.org/ns/auth/acl#&gt; .
@prefix vcard: &lt;http://www.w3.org/2006/vcard/ns#&gt; .
@prefix foaf:  &lt;http://xmlns.com/foaf/0.1/&gt; .
@prefix dc:    &lt;http://purl.org/dc/terms/&gt; .
@prefix acp:   &lt;http://www.w3.org/ns/solid/acp#&gt; .

&lt;https://pod.inrupt.com/virginiabalseiro/todos/index.ttl&gt;
        rdf:type  ldp:RDFSource .
</code></pre>
<p>This is the file where we are going to be adding our to-dos.</p>
<p>If at any point you mess up your to-do list by testing out the app as you code along, you can delete this file and then the folder that contains it ("todos") on PodBrowser by clicking on the "Delete" button in the details drawer. </p>
<p>Then next time you refresh your app, the folder and file will be created again so you can start over.</p>
<h1 id="heading-how-to-add-an-item-to-the-dataset">How to Add an Item to the Dataset</h1>
<p>Ok, now we can finally add a to-do! Adding a to-do is essentially adding an item, or <code>[Thing](https://docs.inrupt.com/developer-tools/javascript/client-libraries/reference/glossary/)</code>, to the to-do list dataset we just created. Our to-dos will have three properties:</p>
<ul>
<li><code>text</code> - the content of the to-do. It will be stored under the predicate: <a target="_blank" href="http://schema.org/text">http://schema.org/text</a></li>
<li><code>created</code> - the date when this to-do was created, stored under <a target="_blank" href="http://www.w3.org/2002/12/cal/ical#created">http://www.w3.org/2002/12/cal/ical#created</a></li>
<li><code>type</code> - the type of the todo, which among other things will help us filter later on. This is stored under <a target="_blank" href="http://www.w3.org/2002/12/cal/ical#Vtodo">http://www.w3.org/2002/12/cal/ical#Vtodo</a></li>
</ul>
<p>We are hardcoding the predicate strings here, but there are libraries that make this easier, such as <a target="_blank" href="https://www.npmjs.com/package/rdf-namespaces">rdf-namespaces</a>.</p>
<p>The date will help us sort them later. So we need to create a thing and add these to it. We will use:</p>
<ul>
<li><code>addStringNoLocale</code> to add the text string</li>
<li><code>addDatetime</code> to add the created at date</li>
</ul>
<p>Let's write a function that does that so we can trigger it by clicking the button.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/AddTodo/index.js</span>
<span class="hljs-keyword">import</span> {
  addDatetime,
  addStringNoLocale,
  createThing,
  getSolidDataset,
  getSourceUrl,
  getThing,
  getUrlAll,
  saveSolidDatasetAt,
  setThing,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-client"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AddTodo</span>(<span class="hljs-params"></span>) </span>{ 
<span class="hljs-keyword">const</span> { session } = useSession();
<span class="hljs-comment">// ...</span>
  <span class="hljs-keyword">const</span> addTodo = <span class="hljs-keyword">async</span> (text) =&gt; {
    <span class="hljs-keyword">const</span> indexUrl = getSourceUrl(todoList);
    <span class="hljs-keyword">const</span> todoWithText = addStringNoLocale(
      createThing(),
      <span class="hljs-string">"http://schema.org/text"</span>,
      text
    );
    <span class="hljs-keyword">const</span> todoWithDate = addDatetime(
      todoWithText,
      <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#created"</span>,
      <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>()
    );
    <span class="hljs-keyword">const</span> todoWithType = addUrl(todoWithDate, <span class="hljs-string">"http://www.w3.org/1999/02/22-rdf-syntax-ns#type"</span>, <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#Vtodo"</span>);
    <span class="hljs-keyword">const</span> updatedTodoList = setThing(todoList, todoWithType);
    <span class="hljs-keyword">const</span> updatedDataset = <span class="hljs-keyword">await</span> saveSolidDatasetAt(indexUrl, updatedTodoList, {
      <span class="hljs-attr">fetch</span>: session.fetch,
    });
    setTodoList(updatedDataset);
  };
<span class="hljs-comment">// ...</span>
}
</code></pre>
<p>We create the <code>Thing</code> first, add a string and a date, then set the thing in the dataset (<code>todoList</code>). We need to overwrite the <code>todoList</code> by saving it in its URL, which we get by using <code>getSourceUrl</code>. </p>
<p>Now we need to modify our component so we can get the input text from the user. Let's put those predicates in constants to keep our code tidy and avoid bugs due to typos:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/AddTodo/index.js</span>

<span class="hljs-keyword">import</span> {
  addDatetime,
  addStringNoLocale,
  createThing,
  getSolidDataset,
  getSourceUrl,
  getUrlAll,
  saveSolidDatasetAt,
  setThing,
  getThing,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-client"</span>;
<span class="hljs-keyword">import</span> { useSession } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;
<span class="hljs-keyword">import</span> React, { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { getOrCreateTodoList } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../utils"</span>;

<span class="hljs-keyword">const</span> STORAGE_PREDICATE = <span class="hljs-string">"http://www.w3.org/ns/pim/space#storage"</span>;
<span class="hljs-keyword">const</span> TEXT_PREDICATE = <span class="hljs-string">"http://schema.org/text"</span>;
<span class="hljs-keyword">const</span> CREATED_PREDICATE = <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#created"</span>;
<span class="hljs-keyword">const</span> TODO_CLASS = <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#Vtodo"</span>;
<span class="hljs-keyword">const</span> TYPE_PREDICATE = <span class="hljs-string">"http://www.w3.org/1999/02/22-rdf-syntax-ns#type"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AddTodo</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { session } = useSession();
  <span class="hljs-keyword">const</span> [todoList, setTodoList] = useState();
  <span class="hljs-keyword">const</span> [todoText, setTodoText] = useState(<span class="hljs-string">""</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!session) <span class="hljs-keyword">return</span>;
    (<span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> profileDataset = <span class="hljs-keyword">await</span> getSolidDataset(session.info.webId, {
        <span class="hljs-attr">fetch</span>: session.fetch,
      });
      <span class="hljs-keyword">const</span> profileThing = getThing(profileDataset, session.info.webId);
      <span class="hljs-keyword">const</span> podsUrls = getUrlAll(profileThing, STORAGE_PREDICATE);
      <span class="hljs-keyword">const</span> pod = podsUrls[<span class="hljs-number">0</span>];
      <span class="hljs-keyword">const</span> containerUri = <span class="hljs-string">`<span class="hljs-subst">${pod}</span>todos/`</span>;
      <span class="hljs-keyword">const</span> list = <span class="hljs-keyword">await</span> getOrCreateTodoList(containerUri, session.fetch);
      setTodoList(list);
    })();
  }, [session]);

  <span class="hljs-keyword">const</span> addTodo = <span class="hljs-keyword">async</span> (text) =&gt; {
    <span class="hljs-keyword">const</span> indexUrl = getSourceUrl(todoList);
    <span class="hljs-keyword">const</span> todoWithText = addStringNoLocale(createThing(), TEXT_PREDICATE, text);
    <span class="hljs-keyword">const</span> todoWithDate = addDatetime(
      todoWithText,
      CREATED_PREDICATE,
      <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>()
    );
    <span class="hljs-keyword">const</span> todoWithType = addUrl(todoWithDate, TYPE_PREDICATE, TODO_CLASS);
    <span class="hljs-keyword">const</span> updatedTodoList = setThing(todoList, todoWithType);
    <span class="hljs-keyword">const</span> updatedDataset = <span class="hljs-keyword">await</span> saveSolidDatasetAt(indexUrl, updatedTodoList, {
      <span class="hljs-attr">fetch</span>: session.fetch,
    });
    setTodoList(updatedDataset);
  };

  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-keyword">async</span> (event) =&gt; {
    event.preventDefault();
    addTodo(todoText);
  };

  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    e.preventDefault();
    setTodoText(e.target.value);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"todo-form"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"todo-input"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
            <span class="hljs-attr">id</span>=<span class="hljs-string">"todo-input"</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{todoText}</span>
            <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"add-button"</span>&gt;</span>
          Add Todo
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AddTodo;
</code></pre>
<p>Now if we write some text and click <code>AddTodo</code>, our to-do will be added! But we cannot see our to-dos yet. </p>
<p>So in order to check if it worked, on <a target="_blank" href="https://podbrowser.inrupt.com/">PodBrowser</a> navigate to your "todos" folder, download the <code>index.ttl</code> file again, and see if there are changes. If everything went well, you should see something like this:</p>
<pre><code class="lang-jsx">&lt;https:<span class="hljs-comment">//pod.inrupt.com/virginiabalseiro/todos/index.ttl#16141957896165236259077375411&gt;</span>
        &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; &lt;http://www.w3.org/2002/12/cal/ical#Vtodo&gt; ;
        &lt;http://www.w3.org/2002/12/cal/ical#created&gt;  "2021-02-24T19:43:09.616Z"^^xsd:dateTime ;
        &lt;http://schema.org/text&gt;  "Finish the Solid Todo App tutorial" .
</code></pre>
<p>You can see that a random id has been generated for our to-do. This happens when we create a thing without passing a URL or a name string for the subject, which is fine for this case. Next we will see how we can fetch our to-dos so we can display them.</p>
<h1 id="heading-how-to-display-the-to-dos">How to Display the To-Dos</h1>
<p>To display the to-dos we are going to use two additional components from <code>solid-ui-react</code>: the <code>Table</code> and <code>TableColumn</code> components.</p>
<p>The Table component has a required prop <code>things</code>, which is an array of objects containing each thing in the dataset and the dataset they belong to. It should look like this:</p>
<pre><code class="lang-jsx">[{ <span class="hljs-attr">dataset</span>: myDataset, <span class="hljs-attr">thing</span>: thing1 }, { <span class="hljs-attr">dataset</span>: myDataset, <span class="hljs-attr">thing</span>: thing2 } ];
</code></pre>
<p>In our case, we already have the dataset (our to-do list), but now we need to extract the things from it and map them to obtain an array that looks like the above.</p>
<p>The place where we are fetching our to-dos is in the <code>AddTodo</code> component. But we are going to create a component called <code>TodoList</code> to display our table, so we are going to need to use the list there too. </p>
<p>Let's move the <code>useEffect</code> to the <code>App</code> component, so we can pass <code>todoList</code> and <code>setTodoList</code> to the components that need them. We are adding a check to see if the user is logged out, in which case we exit the <code>useEffect</code>.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// App.js</span>

<span class="hljs-keyword">import</span> React, { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> {
  LoginButton,
  LogoutButton,
  Text,
  useSession,
  CombinedDataProvider,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;
<span class="hljs-keyword">import</span> { getSolidDataset, getUrlAll, getThing } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-client"</span>;
<span class="hljs-keyword">import</span> AddTodo <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/AddTodo"</span>;
<span class="hljs-keyword">import</span> TodoList <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/TodoList"</span>;
<span class="hljs-keyword">import</span> { getOrCreateTodoList } <span class="hljs-keyword">from</span> <span class="hljs-string">"./utils"</span>;

<span class="hljs-keyword">const</span> STORAGE_PREDICATE = <span class="hljs-string">"http://www.w3.org/ns/pim/space#storage"</span>;

<span class="hljs-keyword">const</span> authOptions = {
  <span class="hljs-attr">clientName</span>: <span class="hljs-string">"Solid Todo App"</span>,
};

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { session } = useSession();
  <span class="hljs-keyword">const</span> [todoList, setTodoList] = useState();
  <span class="hljs-keyword">const</span> [oidcIssuer, setOidcIssuer] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    setOidcIssuer(event.target.value);
  };

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!session || !session.info.isLoggedIn) <span class="hljs-keyword">return</span>; 
    (<span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> profileDataset = <span class="hljs-keyword">await</span> getSolidDataset(session.info.webId, {
        <span class="hljs-attr">fetch</span>: session.fetch,
      });
      <span class="hljs-keyword">const</span> profileThing = getThing(profileDataset, session.info.webId);
      <span class="hljs-keyword">const</span> podsUrls = getUrlAll(profileThing, STORAGE_PREDICATE);
      <span class="hljs-keyword">const</span> pod = podsUrls[<span class="hljs-number">0</span>];
      <span class="hljs-keyword">const</span> containerUri = <span class="hljs-string">`<span class="hljs-subst">${pod}</span>todos/`</span>;
      <span class="hljs-keyword">const</span> list = <span class="hljs-keyword">await</span> getOrCreateTodoList(containerUri, session.fetch);
      setTodoList(list);
    })();
  }, [session, session.info.isLoggedIn]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"app-container"</span>&gt;</span>
      {session.info.isLoggedIn ? (
        <span class="hljs-tag">&lt;<span class="hljs-name">CombinedDataProvider</span>
          <span class="hljs-attr">datasetUrl</span>=<span class="hljs-string">{session.info.webId}</span>
          <span class="hljs-attr">thingUrl</span>=<span class="hljs-string">{session.info.webId}</span>
        &gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"message logged-in"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>You are logged in as: <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>
              <span class="hljs-attr">properties</span>=<span class="hljs-string">{[</span>
                "<span class="hljs-attr">http:</span>//<span class="hljs-attr">xmlns.com</span>/<span class="hljs-attr">foaf</span>/<span class="hljs-attr">0.1</span>/<span class="hljs-attr">name</span>",
                "<span class="hljs-attr">http:</span>//<span class="hljs-attr">www.w3.org</span>/<span class="hljs-attr">2006</span>/<span class="hljs-attr">vcard</span>/<span class="hljs-attr">ns</span>#<span class="hljs-attr">fn</span>",
              ]}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">LogoutButton</span> /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">AddTodo</span> <span class="hljs-attr">todoList</span>=<span class="hljs-string">{todoList}</span> <span class="hljs-attr">setTodoList</span>=<span class="hljs-string">{setTodoList}</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">TodoList</span> <span class="hljs-attr">todoList</span>=<span class="hljs-string">{todoList}</span> <span class="hljs-attr">setTodoList</span>=<span class="hljs-string">{setTodoList}</span> /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">CombinedDataProvider</span>&gt;</span>
      ) : (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"message"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>You are not logged in. <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
            Log in with:
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"oidc-issuer-input "</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"oidcIssuer"</span>
              <span class="hljs-attr">list</span>=<span class="hljs-string">"providers"</span>
              <span class="hljs-attr">value</span>=<span class="hljs-string">{oidcIssuer}</span>
              <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span>
            /&gt;</span>
           <span class="hljs-tag">&lt;<span class="hljs-name">datalist</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"providers"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"https://broker.pod.inrupt.com/"</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"https://inrupt.net/"</span> /&gt;</span>
           <span class="hljs-tag">&lt;/<span class="hljs-name">datalist</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">LoginButton</span>
            <span class="hljs-attr">oidcIssuer</span>=<span class="hljs-string">{oidcIssuer}</span>
            <span class="hljs-attr">redirectUrl</span>=<span class="hljs-string">{window.location.href}</span>
            <span class="hljs-attr">authOptions</span>=<span class="hljs-string">{authOptions}</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>And our AddTodo component will now look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/AddTodo/index.jsx</span>

<span class="hljs-keyword">import</span> {
  addDatetime,
  addStringNoLocale,
  createThing,
  getSourceUrl,
  saveSolidDatasetAt,
  setThing,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-client"</span>;
<span class="hljs-keyword">import</span> { useSession } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;
<span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> TEXT_PREDICATE = <span class="hljs-string">"http://schema.org/text"</span>;
<span class="hljs-keyword">const</span> CREATED_PREDICATE = <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#created"</span>;
<span class="hljs-keyword">const</span> TODO_CLASS = <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#Vtodo"</span>;
<span class="hljs-keyword">const</span> TYPE_PREDICATE = <span class="hljs-string">"http://www.w3.org/1999/02/22-rdf-syntax-ns#type"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AddTodo</span>(<span class="hljs-params">{ todoList, setTodoList }</span>) </span>{
  <span class="hljs-keyword">const</span> { session } = useSession();
  <span class="hljs-keyword">const</span> [todoText, setTodoText] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">const</span> addTodo = <span class="hljs-keyword">async</span> (text) =&gt; {
    <span class="hljs-keyword">const</span> indexUrl = getSourceUrl(todoList);
    <span class="hljs-keyword">const</span> todoWithText = addStringNoLocale(createThing(), TEXT_PREDICATE, text);
    <span class="hljs-keyword">const</span> todoWithDate = addDatetime(
      todoWithText,
      CREATED_PREDICATE,
      <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>()
    );
    <span class="hljs-keyword">const</span> todoWithType = addUrl(todoWithDate, TYPE_PREDICATE, TODO_CLASS);
    <span class="hljs-keyword">const</span> updatedTodoList = setThing(todoList, todoWithType);
    <span class="hljs-keyword">const</span> updatedDataset = <span class="hljs-keyword">await</span> saveSolidDatasetAt(indexUrl, updatedTodoList, {
      <span class="hljs-attr">fetch</span>: session.fetch,
    });
    setTodoList(updatedDataset);
  };

  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-keyword">async</span> (event) =&gt; {
    event.preventDefault();
    addTodo(todoText);
    setTodoText(<span class="hljs-string">""</span>);
  };

  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    e.preventDefault();
    setTodoText(e.target.value);
  };

  <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"todo-form"</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"todo-input"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
            <span class="hljs-attr">id</span>=<span class="hljs-string">"todo-input"</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{todoText}</span>
            <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"add-button"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Add Todo<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AddTodo;
</code></pre>
<p>Notice that we added a line in <code>handleSubmit</code> to set the text to an empty string after we have added the to-do, so that the input box content is cleared.</p>
<p>For our <code>TodoList</code> component, we are going to need the <code>Table</code> and <code>TableColumn</code> components from <code>solid-ui-react</code>. We're also going to use <code>getThingAll</code> from solid-client to extract the things from our dataset so we can create the array we need for the Table. </p>
<p>For now let's just display the number of things our dataset contains:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>

<span class="hljs-keyword">import</span> { getThingAll } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-client"</span>;
<span class="hljs-keyword">import</span> { Table, TableColumn } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;
<span class="hljs-keyword">import</span> React, { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TodoList</span>(<span class="hljs-params">{ todoList }</span>) </span>{
    <span class="hljs-keyword">const</span> todoThings = todoList ? getThingAll(todoList) : [];

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Your to-do list has {todoThings.length} items<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TodoList;
</code></pre>
<p>Once you add the <code>TodoList</code> component, you might need to stop and start your app again with <code>npm start</code> if you see any errors. </p>
<p>To see if it works, try adding to-dos and see if the number of items changes. You will notice the length of the array indicates one item more than the number of to-dos you have created. This is because there is another item in the to-dos dataset that is not a to-do. We will fix that later.</p>
<p>To use the <code>Table</code> component, we need to create the array with the objects we need and pass it to the table:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TodoList</span>(<span class="hljs-params">{ todoList }</span>) </span>{
<span class="hljs-comment">// ...</span>
<span class="hljs-keyword">const</span> thingsArray = todoThings.map(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">dataset</span>: todoList, <span class="hljs-attr">thing</span>: t };
  });
<span class="hljs-comment">// ...</span>
}
</code></pre>
<p>But to actually display anything we need to use the <code>TableColumn</code> component inside the <code>Table</code>. The <code>TableColumn</code> component needs a required prop <code>property</code>, which is the property we want to display. This means the predicate under which the data we want to show is stored. </p>
<p>In the case of our to-dos, we have two properties: the <code>text</code> and the <code>date</code> in which the to-do was created, stored under <a target="_blank" href="http://schema.org/text">http://schema.org/text</a> and <a target="_blank" href="http://www.w3.org/2002/12/cal/ical#created">http://www.w3.org/2002/12/cal/ical#created</a>, respectively:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// ./components/TodoList/index.jsx</span>

<span class="hljs-keyword">const</span> TEXT_PREDICATE = <span class="hljs-string">"http://schema.org/text"</span>;
<span class="hljs-keyword">const</span> CREATED_PREDICATE = <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#created"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TodoList</span>(<span class="hljs-params">{ todoList }</span>) </span>{
<span class="hljs-comment">// ...</span>
&lt;div&gt;
  Your to-<span class="hljs-keyword">do</span> list has {todoThings.length} items
  &lt;Table things={thingsArray}&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TableColumn</span> <span class="hljs-attr">property</span>=<span class="hljs-string">{TEXT_PREDICATE}</span> /&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TableColumn</span> <span class="hljs-attr">property</span>=<span class="hljs-string">{CREATED_PREDICATE}</span> /&gt;</span></span>
   &lt;/Table&gt;
 &lt;/div&gt;
<span class="hljs-comment">// ...</span>
}
</code></pre>
<p>You will notice two things: first, the headers. The <code>TableColumn</code> accepts an optional prop <code>header</code>, with which we can set the header of the column. If we don't pass this prop, the header will be the URL of the predicate for that property. You can also pass an empty string if you don't want headers. Let's do that for the text of our to-do, and pass "Created" for the date.</p>
<p>Second, there is nothing displayed for the created at column. This is because <code>TableColumn</code> also accepts an optional prop <code>dataType</code>, which defaults to 'string' if not set, but the data we have is not a string but a datetime, so we need to set it:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>

<span class="hljs-keyword">const</span> TEXT_PREDICATE = <span class="hljs-string">"http://schema.org/text"</span>;
<span class="hljs-keyword">const</span> CREATED_PREDICATE = <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#created"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TodoList</span>(<span class="hljs-params">{ todoList }</span>) </span>{
<span class="hljs-comment">// ...</span>
    &lt;div className=<span class="hljs-string">"table-container"</span>&gt;
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tasks-message"</span>&gt;</span>
          Your to-do list has {todoThings.length} items
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Table</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"table"</span> <span class="hljs-attr">things</span>=<span class="hljs-string">{thingsArray}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">TableColumn</span> <span class="hljs-attr">property</span>=<span class="hljs-string">{TEXT_PREDICATE}</span> <span class="hljs-attr">header</span>=<span class="hljs-string">""</span> /&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">TableColumn</span>
           <span class="hljs-attr">property</span>=<span class="hljs-string">{CREATED_PREDICATE}</span>
           <span class="hljs-attr">dataType</span>=<span class="hljs-string">"datetime"</span>
           <span class="hljs-attr">header</span>=<span class="hljs-string">"Created At"</span>
          /&gt;</span>
       <span class="hljs-tag">&lt;/<span class="hljs-name">Table</span>&gt;</span></span>
     &lt;/div&gt;
<span class="hljs-comment">// ...</span>
}
</code></pre>
<p>Finally, it would be nice if we could format the date so it could look like this: <code>Sat Dec 26 2020</code>, instead of a such a longer string. </p>
<p>The body prop allows us to pass a custom body to the column, where we can format the value we get for each cell. This prop is super useful when we want to pass a custom component the cell, for instance a link, instead of the value as it comes from the dataset.</p>
<p>Before we do this, though, we need to filter out the non-todo things we have in our dataset. If you look at the <code>index.ttl</code> file you will notice a line that looks like this:</p>
<pre><code class="lang-jsx">&lt;https:<span class="hljs-comment">//pod.inrupt.com/virginiabalseiro/todos/index.ttl&gt;</span>
        rdf:type  ldp:RDFSource .
</code></pre>
<p>That is automatically added by the server to identify what type of resource we're dealing with, but it will throw an error when we try to format the date, because it won't have a <code>created</code> property. This is also why we had an extra item in our to-dos count. </p>
<p>So we need to filter out all the things containing a property <code>type</code> with the value <code>RDFSource</code>.</p>
<p>We will also switch from <code>todoThing</code> to <code>thingsArray</code> in the message displaying the number of items, since otherwise we are counting the <code>type</code> as well.</p>
<p>Our <code>TodoList</code> component now looks like this:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// ./components/TodoList/index.jsx</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { getThingAll, getUrl } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-client"</span>;
<span class="hljs-keyword">import</span> { Table, TableColumn } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TodoList</span>(<span class="hljs-params">{ todoList }</span>) </span>{
  <span class="hljs-keyword">const</span> todoThings = todoList ? getThingAll(todoList) : [];

  <span class="hljs-keyword">const</span> TEXT_PREDICATE = <span class="hljs-string">"http://schema.org/text"</span>;
  <span class="hljs-keyword">const</span> CREATED_PREDICATE = <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#created"</span>;
  <span class="hljs-keyword">const</span> TODO_CLASS = <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#Vtodo"</span>;
  <span class="hljs-keyword">const</span> TYPE_PREDICATE = <span class="hljs-string">"http://www.w3.org/1999/02/22-rdf-syntax-ns#type"</span>;

  <span class="hljs-keyword">const</span> thingsArray = todoThings.filter(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> getUrl(t, TYPE_PREDICATE) === TODO_CLASS).map(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">dataset</span>: todoList, <span class="hljs-attr">thing</span>: t };
  });

  <span class="hljs-keyword">if</span> (!thingsArray.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"table-container"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tasks-message"</span>&gt;</span>
        Your to-do list has {thingsArray.length} items
      <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Table</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"table"</span> <span class="hljs-attr">things</span>=<span class="hljs-string">{thingsArray}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">TableColumn</span> <span class="hljs-attr">property</span>=<span class="hljs-string">{TEXT_PREDICATE}</span> <span class="hljs-attr">header</span>=<span class="hljs-string">""</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">TableColumn</span>
          <span class="hljs-attr">property</span>=<span class="hljs-string">{CREATED_PREDICATE}</span>
          <span class="hljs-attr">dataType</span>=<span class="hljs-string">"datetime"</span>
              <span class="hljs-attr">header</span>=<span class="hljs-string">"Created At"</span>
          <span class="hljs-attr">body</span>=<span class="hljs-string">{({</span> <span class="hljs-attr">value</span> }) =&gt;</span> value.toDateString()}
        /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">Table</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TodoList;
</code></pre>
<h1 id="heading-how-to-mark-a-to-do-as-done">How to Mark a To-Do as Done</h1>
<p>Now that we can display our to-dos, we need a way to mark them as done. We will store this "done" state under "[http://www.w3.org/2002/12/cal/ical#completed"](http://www.w3.org/2002/12/cal/ical#completed%22%5D(http://www.w3.org/2002/12/cal/ical#completed%22), with a date time as the object. </p>
<p>Let's add a new column to our table:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>

<span class="hljs-keyword">const</span> COMPLETED_PREDICATE = <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#completed"</span>;
<span class="hljs-comment">// ...</span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TableColumn</span>
  <span class="hljs-attr">property</span>=<span class="hljs-string">{COMPLETED_PREDICATE}</span>
  <span class="hljs-attr">dataType</span>=<span class="hljs-string">"datetime"</span>
  <span class="hljs-attr">header</span>=<span class="hljs-string">"Done"</span>
  <span class="hljs-attr">body</span>=<span class="hljs-string">{({</span> <span class="hljs-attr">value</span> }) =&gt;</span> (
     <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
     )}
 /&gt;</span>
<span class="hljs-comment">// ...</span>
</code></pre>
<p>For now this check box doesn't do anything. We need to add this property with a datetime value to our to-do thing when we click the checkbox. For that, we are going to need the URL for our to-do, so we can find it and add properties to it.</p>
<p>For this we are going to use the <code>useThing</code> hook from <code>solid-ui-react</code>.</p>
<p>We need to write a function that handles the adding of a <code>completed</code> property to our to-do thing. This function will take the to-do thing as an argument, add a <code>completed</code> property with a <code>datetime</code> value to it, set it in the dataset, and save the updated dataset.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>
<span class="hljs-keyword">import</span> {
  addDatetime,
  getSourceUrl,
  saveSolidDatasetAt,
  setThing,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-client"</span>;
<span class="hljs-keyword">import</span> {
  Table,
  TableColumn,
  useSession,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TodoList</span>(<span class="hljs-params">{ todoList, setTodoList }</span>) </span>{
  <span class="hljs-keyword">const</span> { fetch } = useSession();
  <span class="hljs-comment">// ...</span>
  <span class="hljs-keyword">const</span> handleCheck = <span class="hljs-keyword">async</span> (todo) =&gt; {
        <span class="hljs-keyword">const</span> todosUrl = getSourceUrl(todoList);
        <span class="hljs-keyword">const</span> date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
        <span class="hljs-keyword">const</span> doneTodo = addDatetime(
          todo,
          <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#completed"</span>,
          date
        );
        <span class="hljs-keyword">const</span> updatedTodos = setThing(todoList, doneTodo, { fetch });
        <span class="hljs-keyword">await</span> saveSolidDatasetAt(todosUrl, updatedTodos, {
          fetch,
        });
      };
  <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>To access the to-do thing, we first need to create a custom body component for our <code>TableColumn</code>. It needs to be a proper component so that we can use the <code>useThing</code> hook, so let's put it outside the <code>TodoList</code> component but in the same file. We will also pass it a <code>checked</code> prop that we will use to set the <code>checked</code> property in the checkbox, and our <code>handleCheck</code> function.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>
<span class="hljs-keyword">import</span> {
  Table,
  TableColumn,
  useThing,
  useSession,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CompletedBody</span>(<span class="hljs-params">{ checked, handleCheck }</span>) </span>{
    <span class="hljs-keyword">const</span> { thing } = useThing();
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
          <span class="hljs-attr">checked</span>=<span class="hljs-string">{checked}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{()</span> =&gt;</span> handleCheck(thing)}
        /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span></span>
    );
  }
</code></pre>
<p>Now we can use this component in the <code>body</code> of our column:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>

&lt;TableColumn
  property={COMPLETED_PREDICATE}
  dataType=<span class="hljs-string">"datetime"</span>
  header=<span class="hljs-string">"Done"</span>
  body={<span class="hljs-function">(<span class="hljs-params">{ value }</span>) =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CompletedBody</span> <span class="hljs-attr">checked</span>=<span class="hljs-string">{Boolean(value)}</span> <span class="hljs-attr">handleCheck</span>=<span class="hljs-string">{handleCheck}</span> /&gt;</span></span>}
 /&gt;
</code></pre>
<p>Now if you click on the checkbox, a property is added to the to-do. If you check the <code>index.ttl</code> file, you will see something like this:</p>
<pre><code class="lang-jsx">&lt;https:<span class="hljs-comment">//pod.inrupt.com/virginiabalseiro/todos/index.ttl#16089989748796144560745441174&gt;</span>
        &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; &lt;http://www.w3.org/2002/12/cal/ical#Vtodo&gt; ;        
        &lt;http://www.w3.org/2002/12/cal/ical#created&gt;  "2020-12-26T16:09:34.880Z"^^xsd:dateTime ;
        &lt;http://schema.org/text&gt;  "Walk the dog" ;
        &lt;http://www.w3.org/2002/12/cal/ical#completed&gt;  "2020-12-26T16:09:39.853Z"^^xsd:dateTime .
</code></pre>
<p>We will also want to mark to-dos as "undone", so essentially removing this property from the to-do. For that we will need to modify our <code>handleCheck</code> function so that it removes the to-do if it was marked as done at the moment of clicking the checkbox, or add it if it was undone:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>
<span class="hljs-keyword">import</span> {
  addDatetime,
  getDatetime,
  getSourceUrl,
  getThingAll,
  getUrl, 
  removeDatetime,
  saveSolidDatasetAt,
  setThing,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-client"</span>;

<span class="hljs-keyword">const</span> COMPLETED_PREDICATE = <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#completed"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TodoList</span>(<span class="hljs-params">{ todoList, setTodoList }</span>) </span>{
<span class="hljs-keyword">const</span> { fetch } = useSession();
<span class="hljs-comment">// ...</span>

<span class="hljs-keyword">const</span> handleCheck = <span class="hljs-keyword">async</span> (todo, checked) =&gt; {
    <span class="hljs-keyword">const</span> todosUrl = getSourceUrl(todoList);
    <span class="hljs-keyword">let</span> updatedTodos;
    <span class="hljs-keyword">let</span> date;
    <span class="hljs-keyword">if</span> (!checked) {
      date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
      <span class="hljs-keyword">const</span> doneTodo = addDatetime(todo, COMPLETED_PREDICATE, date);
      updatedTodos = setThing(todoList, doneTodo, { fetch });
    } <span class="hljs-keyword">else</span> {
      date = getDatetime(todo, COMPLETED_PREDICATE);
      <span class="hljs-keyword">const</span> undoneTodo = removeDatetime(todo, COMPLETED_PREDICATE, date);
      updatedTodos = setThing(todoList, undoneTodo, { fetch });
    }
    <span class="hljs-keyword">const</span> updatedList = <span class="hljs-keyword">await</span> saveSolidDatasetAt(todosUrl, updatedTodos, {
      fetch,
    });
    setTodoList(updatedList);
  };
<span class="hljs-comment">// ...</span>
}
</code></pre>
<p>And we need to update the <code>CompletedBody</code> component as well:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CompletedBody</span>(<span class="hljs-params">{ checked, handleCheck }</span>) </span>{
    <span class="hljs-keyword">const</span> { thing } = useThing();
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
          <span class="hljs-attr">checked</span>=<span class="hljs-string">{checked}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{()</span> =&gt;</span> handleCheck(thing, checked)}
        /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span></span>
    );
  }
</code></pre>
<p>Notice we need to use <code>setTodoList</code> here to update the to-do list, which we are getting from the <code>App</code> component.</p>
<p>There is one little bug though: each time we check a to-do, our list gets rearranged.</p>
<p>To fix this, we can sort the things array after we extract the things from the to-do list dataset. We want them sorted by the date they were created:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>

<span class="hljs-keyword">const</span> todoThings = todoList ? getThingAll(todoList) : [];
  todoThings.sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
      getDatetime(a, CREATED_PREDICATE) - getDatetime(b, CREATED_PREDICATE)
    );
  });
</code></pre>
<p>In addition, with the <code>TableColumn</code> component we can sort items by property. If we pass a <code>sortable</code> prop to one of our columns, we can arrange our to-dos based on that property, so let's use the "Created At" column and the to-do content column to see how it works. Let's also add a "To do" header to the content column so we can see what criteria we are sorting by. </p>
<p>Our (almost) finished <code>TodoList</code> component now looks like this:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>

<span class="hljs-keyword">import</span> {
  addDatetime,
  getDatetime,
  getSourceUrl,
  getThingAll,
  getUrl,
  removeDatetime,
  saveSolidDatasetAt,
  setThing,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-client"</span>;
<span class="hljs-keyword">import</span> {
  Table,
  TableColumn,
  useThing,
  useSession,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-ui-react"</span>;
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> TEXT_PREDICATE = <span class="hljs-string">"http://schema.org/text"</span>;
<span class="hljs-keyword">const</span> CREATED_PREDICATE = <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#created"</span>;
<span class="hljs-keyword">const</span> COMPLETED_PREDICATE = <span class="hljs-string">"http://www.w3.org/2002/12/cal/ical#completed"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CompletedBody</span>(<span class="hljs-params">{ checked, handleCheck }</span>) </span>{
    <span class="hljs-keyword">const</span> { thing } = useThing();
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
          <span class="hljs-attr">checked</span>=<span class="hljs-string">{checked}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{()</span> =&gt;</span> handleCheck(thing, checked)}
        /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span></span>
    );
  }

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TodoList</span>(<span class="hljs-params">{ todoList, setTodoList }</span>) </span>{
  <span class="hljs-keyword">const</span> todoThings = todoList ? getThingAll(todoList) : [];
  todoThings.sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
      getDatetime(a, CREATED_PREDICATE) - getDatetime(b, CREATED_PREDICATE)
    );
  });

  <span class="hljs-keyword">const</span> { fetch } = useSession();

  <span class="hljs-keyword">const</span> handleCheck = <span class="hljs-keyword">async</span> (todo, checked) =&gt; {
    <span class="hljs-keyword">const</span> todosUrl = getSourceUrl(todoList);
    <span class="hljs-keyword">let</span> updatedTodos;
    <span class="hljs-keyword">if</span> (!checked) {
      <span class="hljs-keyword">const</span> date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
      <span class="hljs-keyword">const</span> doneTodo = addDatetime(todo, COMPLETED_PREDICATE, date);
      updatedTodos = setThing(todoList, doneTodo, { fetch });
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">const</span> date = getDatetime(todo, COMPLETED_PREDICATE);
      <span class="hljs-keyword">const</span> undoneTodo = removeDatetime(todo, COMPLETED_PREDICATE, date);
      updatedTodos = setThing(todoList, undoneTodo, { fetch });
    }
    <span class="hljs-keyword">const</span> updatedList = <span class="hljs-keyword">await</span> saveSolidDatasetAt(todosUrl, updatedTodos, {
      fetch,
    });
    setTodoList(updatedList);
  };

  <span class="hljs-keyword">const</span> thingsArray = todoThings
    .filter(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> getUrl(t, TYPE_PREDICATE) === TODO_CLASS)
    .map(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
      <span class="hljs-keyword">return</span> { <span class="hljs-attr">dataset</span>: todoList, <span class="hljs-attr">thing</span>: t };
    });
  <span class="hljs-keyword">if</span> (!thingsArray.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"table-container"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tasks-message"</span>&gt;</span>
        Your to-do list has {thingsArray.length} items
      <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Table</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"table"</span> <span class="hljs-attr">things</span>=<span class="hljs-string">{thingsArray}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">TableColumn</span> <span class="hljs-attr">property</span>=<span class="hljs-string">{TEXT_PREDICATE}</span> <span class="hljs-attr">header</span>=<span class="hljs-string">"To Do"</span> <span class="hljs-attr">sortable</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">TableColumn</span>
          <span class="hljs-attr">property</span>=<span class="hljs-string">{CREATED_PREDICATE}</span>
          <span class="hljs-attr">dataType</span>=<span class="hljs-string">"datetime"</span>
          <span class="hljs-attr">header</span>=<span class="hljs-string">"Created At"</span>
          <span class="hljs-attr">body</span>=<span class="hljs-string">{({</span> <span class="hljs-attr">value</span> }) =&gt;</span> value.toDateString()}
          sortable
        /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">TableColumn</span>
          <span class="hljs-attr">property</span>=<span class="hljs-string">{COMPLETED_PREDICATE}</span>
          <span class="hljs-attr">dataType</span>=<span class="hljs-string">"datetime"</span>
          <span class="hljs-attr">header</span>=<span class="hljs-string">"Done"</span>
          <span class="hljs-attr">body</span>=<span class="hljs-string">{({</span> <span class="hljs-attr">value</span> }) =&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">CompletedBody</span> <span class="hljs-attr">checked</span>=<span class="hljs-string">{Boolean(value)}</span> <span class="hljs-attr">handleCheck</span>=<span class="hljs-string">{handleCheck}</span> /&gt;</span>}
        /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">Table</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TodoList;
</code></pre>
<h1 id="heading-how-to-delete-a-to-do">How to Delete a To-Do</h1>
<p>To delete a to-do, we will need a new column to add a delete button.</p>
<p>We will also need to write a function that takes the to-do <code>Thing</code> and deletes it on click:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>

<span class="hljs-keyword">import</span> {
  addDatetime,
  getDatetime,
  getSourceUrl,
  getThingAll,
  getUrl,
  removeDatetime,
    removeThing,
  saveSolidDatasetAt,
  setThing,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@inrupt/solid-client"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TodoList</span>(<span class="hljs-params">{ todoList, setTodoList }</span>) </span>{
<span class="hljs-comment">// ...</span>
    <span class="hljs-keyword">const</span> deleteTodo = <span class="hljs-keyword">async</span> (todo) =&gt; {
        <span class="hljs-keyword">const</span> todosUrl = getSourceUrl(todoList);
        <span class="hljs-keyword">const</span> updatedTodos = removeThing(todoList, todo);
        <span class="hljs-keyword">const</span> updatedDataset = <span class="hljs-keyword">await</span> saveSolidDatasetAt(todosUrl, updatedTodos, {
          fetch,
        });
        setTodoList(updatedDataset);
      };
<span class="hljs-comment">// ...</span>
}
</code></pre>
<p>We can get the to-do <code>Thing</code> using the <code>useThing</code> hook (like we did before with the <code>CompleteBody</code> component to mark to-dos as done), so it doesn't really matter which property we use. But because <code>property</code> is not optional in the <code>TableColumn</code> component, we'll use the to-do text.</p>
<p>Since we need to use a hook, we have to write a proper React component for the custom body outside the <code>TodoList</code> component:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DeleteButton</span>(<span class="hljs-params">{ deleteTodo }</span>) </span>{
    <span class="hljs-keyword">const</span> { thing } = useThing();
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"delete-button"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> deleteTodo(thing)}&gt;
        Delete
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
    );
  }
</code></pre>
<p>And add the column to the table, after the last column:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// components/TodoList/index.jsx</span>

&lt;TableColumn
          property={TEXT_PREDICATE}
          header=<span class="hljs-string">""</span>
          body={<span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DeleteButton</span> <span class="hljs-attr">deleteTodo</span>=<span class="hljs-string">{deleteTodo}</span> /&gt;</span></span>}
        /&gt;
</code></pre>
<p>That's it! Now if we click the delete button, we can delete the to-do.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<h3 id="heading-where-to-go-from-here">Where to go from here</h3>
<p>You have completed the tutorial! You now know the basics of how to create your own Solid app. Now you can go and build your own app from scratch, experiment, and learn more. Here are some resources to help you:</p>
<ul>
<li><a target="_blank" href="https://solid-ui-react.docs.inrupt.com/?path=/story/intro--page">Solid UI React Docs</a></li>
<li><a target="_blank" href="https://docs.inrupt.com/developer-tools/javascript/client-libraries/">Solid Client Libraries Docs</a></li>
<li><a target="_blank" href="https://inrupt.com/solidApps/solid-app-listing">Solid apps you can test and play around with</a></li>
<li><a target="_blank" href="https://forum.solidproject.org/">The Solid Community Forum, where you can ask questions and see what people are talking about</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a React Project with Create React App in 10 Steps ]]>
                </title>
                <description>
                    <![CDATA[ The package Create React App makes creating and developing React apps a breeze. It is one of the easiest ways to spin up a new React project and is an ideal choice to use for your own personal projects as well as for serious, large-scale applications... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-react-project-with-create-react-app-in-10-steps/</link>
                <guid isPermaLink="false">66d03774dcd3a41034854bba</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Reed ]]>
                </dc:creator>
                <pubDate>Fri, 05 Feb 2021 17:12:15 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/02/how-to-build-a-react-project-with-create-react-app-in-10-steps.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The package Create React App makes creating and developing React apps a breeze.</p>
<p>It is one of the easiest ways to spin up a new React project and is an ideal choice to use for your own personal projects as well as for serious, large-scale applications.</p>
<p>We're going to cover, step-by-step, how to use all of the major features of Create React App to quickly and easily build your own React projects.</p>
<p>Throughout this guide, I've also included a lot of helpful tips I've learned through building apps with Create React App to make your workflow even easier.</p>
<p>Let's get started.</p>
<h3 id="heading-tools-you-will-need">Tools You Will Need:</h3>
<ul>
<li>Node installed on your computer. You can download Node at <a target="_blank" href="https://nodejs.org">nodejs.org</a>. Create React App requires a Node version of at least 10.</li>
<li>A package manager called npm. It is automatically included in your installation of Node. You need to have an npm version of at least 5.2.</li>
<li>A good code editor to work with our project files. I highly recommend using the editor Visual Studio Code. You can grab it at <a target="_blank" href="https://code.visualstudio.com">code.visualstudio.com</a>.</li>
</ul>
<h2 id="heading-step-1-how-to-install-create-react-app">Step 1. How to Install Create React App</h2>
<p>To use Create React App, we first need to open our terminal or command line on our computer.</p>
<p>To create a new React project, we can use the tool <code>npx</code>, provided you have an npm version of at least 5.2.</p>
<blockquote>
<p>Note: You can check what npm version you have by running in your terminal <code>npm -v</code></p>
</blockquote>
<p>npx gives us the ability to use the <code>create-react-app</code> package without having to first install it on our computer, which is very convenient.</p>
<p>Using npx also ensures that we are using latest version of Create React App to create our project:</p>
<pre><code class="lang-bash">npx create-react-app my-react-app
</code></pre>
<p>Once we run this command, a folder named "my-react-app" will be created where we specified on our computer and all of the packages it requires will be automatically installed.</p>
<blockquote>
<p>Note: Creating a new React app with create-react-app will usually take 2-3 minutes, sometimes more.</p>
</blockquote>
<p>Create React App also gives us some templates to use for specific types of React projects.</p>
<p>For example, if we wanted to create a React project that used the tool TypeScript, we could use a template for that instead of having to install TypeScript manually.</p>
<p>To create a React app that uses TypeScript, we can use the Create React App TypeScript template:</p>
<pre><code class="lang-bash">npx create-react-app my-react-app --template typescript
</code></pre>
<h2 id="heading-step-2-reviewing-the-project-structure">Step 2. Reviewing the Project Structure</h2>
<p>Once our project files have been created and our dependencies have been installed, our project structure should look like this:</p>
<pre><code>my-react-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
└── src
</code></pre><p>What are each of these files and folders for?</p>
<ul>
<li><code>README.md</code> is a markdown file that includes a lot of helpful tips and links that can help you while learning to use Create React App. </li>
<li><code>node_modules</code> is a folder that includes all of the dependency-related code that Create React App has installed. You will never need to go into this folder.</li>
<li><code>package.json</code> that manages our app dependencies and what is included in our node_modules folder for our project, plus the scripts we need to run our app.</li>
<li><code>.gitignore</code> is a file that is used to exclude files and folders from being tracked by Git. We don't want to include large folders such as the node_modules folder </li>
<li><code>public</code> is a folder that we can use to store our static assets, such as images, svgs, and fonts for our React app.</li>
<li><code>src</code> is a folder that contains our source code. It is where all of our React-related code will live and is what we will primarily work in to build our app.</li>
</ul>
<blockquote>
<p>Note: A new Git repository is created whenever you make a new project with Create React App. You can start saving changes to your app right away using <code>git add .</code> and <code>git commit -m "your commit message"</code>.</p>
</blockquote>
<h2 id="heading-step-3-how-to-run-your-react-project">Step 3. How to Run your React Project</h2>
<p>Once you have dragged your project into your code editor, you can open up your terminal (in VSCode, go to View &gt; Terminal).</p>
<p>To start your React project, you can simply run:</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>When we run our project, a new browser tab will automatically open on our computer's default browser to view our app.</p>
<p>The development server will start up on localhost:3000 and, right away, we can see the starting home page for our app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screen-Shot-2021-02-03-at-8.56.40-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Where is our app content coming from? </p>
<p>It's coming from the App.js file within the src folder. If we head over to that file, we can start making changes to our app code.</p>
<pre><code class="lang-js"><span class="hljs-comment">// src/App.js</span>

<span class="hljs-keyword">import</span> logo <span class="hljs-keyword">from</span> <span class="hljs-string">"./logo.svg"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-header"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{logo}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-logo"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"logo"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
          Edit <span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>src/App.js<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span> and save to reload.
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"App-link"</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"https://reactjs.org"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
          <span class="hljs-attr">rel</span>=<span class="hljs-string">"noopener noreferrer"</span>
        &gt;</span>
          Learn React
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>In particular, let's remove the <code>p</code> and <code>a</code> tags, and add an <code>h1</code> element with the name of our app, "React Posts Sharer":</p>
<pre><code class="lang-js"><span class="hljs-comment">// src/App.js</span>

<span class="hljs-keyword">import</span> logo <span class="hljs-keyword">from</span> <span class="hljs-string">"./logo.svg"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-header"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{logo}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-logo"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"logo"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>React Posts Sharer<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>When you save by using Command/Ctrl + S, you will see our page immediately update to look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screen-Shot-2021-02-03-at-9.04.31-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>What is great about the development server is that it automatically refreshes to reflect our changes. There is no need to manually refresh the browser.</p>
<blockquote>
<p>Note: The only time you may need to refresh the browser when working with Create React App is when you have an error.</p>
</blockquote>
<h2 id="heading-step-4-how-to-run-tests-with-the-react-testing-library">Step 4. How to Run Tests with the React Testing Library</h2>
<p>Create React App makes it very simple to test your React app. </p>
<p>It includes all of the packages you need to run tests using the React Testing Library (<code>@testing-library/react</code>).</p>
<p>A basic test is included in the file App.test.js in src. It tests that our App component successfully displays a link with the text "learn react".</p>
<p>We can run our tests with the command:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>
</code></pre>
<blockquote>
<p>Note: Tests will be run in all files that end in .test.js when you run the command <code>npm run test</code></p>
</blockquote>
<p>If we run this, however, our test will fail. </p>
<p>This is because we no longer have a link element, but a title element. To make our test pass we want to get a title element with the text "React Posts Sharer". </p>
<pre><code class="lang-js"><span class="hljs-comment">// src/App.test.js</span>

<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">"@testing-library/react"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App"</span>;

test(<span class="hljs-string">"renders app title element"</span>, <span class="hljs-function">() =&gt;</span> {
  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span></span>);
  <span class="hljs-keyword">const</span> titleElement = screen.getByText(<span class="hljs-regexp">/React Posts Sharer/i</span>);
  expect(titleElement).toBeInTheDocument();
});
</code></pre>
<p>Once we run our test again, we see that it passes:</p>
<pre><code class="lang-bash">PASS  src/App.test.js

  ✓ renders app title element (54 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.776 s, estimated 3 s
Ran all <span class="hljs-built_in">test</span> suites related to changed files.
</code></pre>
<blockquote>
<p>Note: When run the test command, you do not need to start and stop it manually. If you have a failing test, you can jump into your app code, fix your error, and once you hit save, all tests will automatically re-run.</p>
</blockquote>
<h2 id="heading-step-5-how-to-change-the-apps-meta-data">Step 5. How to Change the App's Meta Data</h2>
<p>How does our project work? We can see how by going to the index.js file.</p>
<pre><code class="lang-js"><span class="hljs-comment">// src/index.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
<span class="hljs-keyword">import</span> reportWebVitals <span class="hljs-keyword">from</span> <span class="hljs-string">'./reportWebVitals'</span>;

ReactDOM.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>,
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)
);
</code></pre>
<p>The package ReactDOM renders our application (specifically the App component and every component within it), by attaching it to a HTML element with an id value of 'root'.</p>
<p>This element can be found within <code>public/index.html</code>.</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"%PUBLIC_URL%/favicon.ico"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"theme-color"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"#000000"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span>
      <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span>
      <span class="hljs-attr">content</span>=<span class="hljs-string">"Web site created using create-react-app"</span>
    /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"apple-touch-icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"%PUBLIC_URL%/logo192.png"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"manifest"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"%PUBLIC_URL%/manifest.json"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>React App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">noscript</span>&gt;</span>You need to enable JavaScript to run this app.<span class="hljs-tag">&lt;/<span class="hljs-name">noscript</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>The entire React app is attached to this HTML page using the div with the id of root you see above.</p>
<p>We don't need to change anything within the <code>body</code> tags. However, it is useful to change the metadata in the <code>head</code> tags, to tell users and search engines about our specific app.</p>
<p>We can see that it includes meta tags for a title, description, and favicon image (the little icon in the browser tab).</p>
<p>You'll also see several other tags like theme-color, apple-touch-icon and manifest. These are useful if users want to add your application to their device or computer's home screen.</p>
<p>In our case, we can change the title to our app name and the description to suit the app we're making:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"%PUBLIC_URL%/favicon.ico"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"theme-color"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"#000000"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span>
      <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span>
      <span class="hljs-attr">content</span>=<span class="hljs-string">"App for sharing peoples' posts from around the web"</span>
    /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"apple-touch-icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"%PUBLIC_URL%/logo192.png"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"manifest"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"%PUBLIC_URL%/manifest.json"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>React Posts Sharer<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">noscript</span>&gt;</span>You need to enable JavaScript to run this app.<span class="hljs-tag">&lt;/<span class="hljs-name">noscript</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h2 id="heading-step-6-how-to-work-with-images-and-other-assets">Step 6. How to Work with Images and Other Assets</h2>
<p>If we look at our App component, we see that we are using an <code>img</code> element. </p>
<p>What's interesting is that we are importing a file from our src folder, as if it was a variable being exported from that file.</p>
<pre><code class="lang-js"><span class="hljs-comment">// src/App.js</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;
<span class="hljs-keyword">import</span> logo <span class="hljs-keyword">from</span> <span class="hljs-string">"./logo.svg"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-header"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{logo}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-logo"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"logo"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>React Posts Sharer<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>We can import image files and other static assets directly into our React components. This feature comes from Create React App's webpack configuration.</p>
<p>Instead of including static assets directly within our src folder, we also have the option to include them in our public folder.</p>
<p>If we move our logo.svg file from src to public, instead of importing our file by using the import syntax, we can write the following:</p>
<pre><code class="lang-js"><span class="hljs-comment">// src/App.js</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-header"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/logo.svg"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-logo"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"logo"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>React Posts Sharer<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Any file that's placed in the public folder can be used in .js or .css files with the syntax: <code>/filename.extension</code>.</p>
<p>What is convenient about Create React App is that we do not need to use an <code>img</code> element at all to display this svg. </p>
<p>We can import this svg as a component using the following syntax:</p>
<pre><code class="lang-js"><span class="hljs-comment">// src/App.js</span>

<span class="hljs-keyword">import</span> { ReactComponent <span class="hljs-keyword">as</span> Logo } <span class="hljs-keyword">from</span> <span class="hljs-string">"./logo.svg"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-header"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Logo</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">height:</span> <span class="hljs-attr">200</span> }} /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>React Posts Sharer<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>What is happening here? We can import the svg file as a ReactComponent and then rename it to whatever name we like using the <code>as</code> keyword.</p>
<p><em>In other words, we can use our imported svg just like we would a regular component.</em></p>
<p>Svg files have traditionally been challenging to use in React. This component syntax makes it very easy and allows us to do things such as use inline styles (like you see above, where we set the logo's height to 200px).</p>
<h2 id="heading-step-7-how-to-install-dependencies">Step 7. How to Install Dependencies</h2>
<p>For our post sharing app that we're making, let's grab some post data to display in our app from the JSON Placeholder API.</p>
<p>We can use a dependency called <code>axios</code> to make a request to get our posts.</p>
<p>To install axios, run:</p>
<pre><code class="lang-bash">npm install axios
</code></pre>
<blockquote>
<p>Note: You can more easily install packages using the shorthand command <code>npm i axios</code> instead of <code>npm install</code></p>
</blockquote>
<p>When we install axios, it will be added to our <code>node_modules</code> folder. </p>
<p>We can review all dependencies we have installed directly within our package.json file and see that axios has been added to the "dependencies" section:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"my-react-app"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"0.1.0"</span>,
  <span class="hljs-attr">"private"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"@testing-library/jest-dom"</span>: <span class="hljs-string">"^5.11.4"</span>,
    <span class="hljs-attr">"@testing-library/react"</span>: <span class="hljs-string">"^11.1.0"</span>,
    <span class="hljs-attr">"@testing-library/user-event"</span>: <span class="hljs-string">"^12.1.10"</span>,
    <span class="hljs-attr">"axios"</span>: <span class="hljs-string">"^0.21.1"</span>,
    <span class="hljs-attr">"react"</span>: <span class="hljs-string">"^17.0.1"</span>,
    <span class="hljs-attr">"react-dom"</span>: <span class="hljs-string">"^17.0.1"</span>,
    <span class="hljs-attr">"react-scripts"</span>: <span class="hljs-string">"4.0.2"</span>,
    <span class="hljs-attr">"web-vitals"</span>: <span class="hljs-string">"^1.0.1"</span>
  }
}
</code></pre>
<p>We will not include it in this project, but if you are interested in using TypeScript with your existing Create React App project, the process is very simple.</p>
<p>You simply need to install the <code>typescript</code> dependency and the appropriate type definitions to use for React development and testing:</p>
<pre><code class="lang-bash">npm install typescript @types/node @types/react @types/react-dom @types/jest
</code></pre>
<p>After that, you can simply restart your development server and rename any React file that ends with .js to .tsx and you have a working React and TypeScript project.</p>
<h2 id="heading-step-8-how-to-import-components">Step 8. How to Import Components</h2>
<p>Instead of writing all of our code within the App component, let's create a separate component to fetch our data and display it.</p>
<p>We'll call this component Posts, so let's create a folder within src to hold all of our components and put a file within it: Posts.js.</p>
<p>The complete path for our component file is <code>src/components/Posts.js</code>.</p>
<p>To fetch our posts, we will request them from JSON Placeholder, put them in a state variable called posts, and then map over them to display their title and body:</p>
<pre><code class="lang-js"><span class="hljs-comment">// src/components/Posts.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Posts</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [posts, setPosts] = React.useState([]);

  React.useEffect(<span class="hljs-function">() =&gt;</span> {
    axios
      .get(<span class="hljs-string">"http://jsonplaceholder.typicode.com/posts"</span>)
      .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> setPosts(response.data));
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"posts"</span>&gt;</span>
      {posts.map((post) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"post"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{post.id}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h4</span>&gt;</span>{post.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{post.body}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Posts;
</code></pre>
<p>We are fetching and returning our post data from the Posts component, but to see it in our app, we need to import it into the App component.</p>
<p>Let's head back to App.js and import it by going into the components folder and getting the Posts component from Posts.js.</p>
<p>After that, we can place our Posts component under our <code>header</code>:</p>
<pre><code class="lang-js"><span class="hljs-comment">// src/App.js</span>

<span class="hljs-keyword">import</span> Posts <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Posts"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-header"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/logo.svg"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-logo"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"logo"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>React Posts Sharer<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Posts</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>And we can see all of our fetched posts on our home page below our header:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screen-Shot-2021-02-03-at-11.24.54-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-step-9-how-to-style-our-app-with-css">Step 9: How to Style our App with CSS</h2>
<p>Our app could benefit from some improved styles.</p>
<p>Create React App comes with CSS support out of the box. If you head to App.js, you can see at the top that we are importing an App.css file from src.</p>
<blockquote>
<p>Note: You can import .css files into any component you like, however these styles will be applied globally to our app. They are not scoped to the component into which the .css file is imported.</p>
</blockquote>
<p>Within App.css, we can add some styles to improve our app's appearance:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* src/App.css */</span>

<span class="hljs-selector-class">.App</span> {
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> auto;
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">1000px</span>;
}

<span class="hljs-selector-class">.App-logo</span> {
  <span class="hljs-attribute">height</span>: <span class="hljs-number">40vmin</span>;
  <span class="hljs-attribute">pointer-events</span>: none;
}

<span class="hljs-selector-class">.App-header</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> auto;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">10px</span> + <span class="hljs-number">2vmin</span>);
}

<span class="hljs-selector-tag">li</span> {
  <span class="hljs-attribute">list-style-type</span>: none;
}

<span class="hljs-selector-class">.post</span> {
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">4em</span>;
}

<span class="hljs-selector-class">.post</span> <span class="hljs-selector-tag">h4</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
}
</code></pre>
<p>There is also another global stylesheet called index.css that has more general style rules.</p>
<p>In it, we can add some additional properties for the body element to make our background dark and our text white:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* src/index.css */</span>

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#282c34</span>;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">font-family</span>: -apple-system, BlinkMacSystemFont, <span class="hljs-string">"Segoe UI"</span>, <span class="hljs-string">"Roboto"</span>, <span class="hljs-string">"Oxygen"</span>,
    <span class="hljs-string">"Ubuntu"</span>, <span class="hljs-string">"Cantarell"</span>, <span class="hljs-string">"Fira Sans"</span>, <span class="hljs-string">"Droid Sans"</span>, <span class="hljs-string">"Helvetica Neue"</span>,
    sans-serif;
  <span class="hljs-attribute">-webkit-font-smoothing</span>: antialiased;
  <span class="hljs-attribute">-moz-osx-font-smoothing</span>: grayscale;
}
</code></pre>
<p>After adding these styles, we have a much better looking app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screen-Shot-2021-02-03-at-11.20.29-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Be aware that it is also very easy to add a more advanced CSS configurations, such as if you want to add CSS modules or SASS to your React app. </p>
<p>More helpful resources for CSS styling are included in your README.md file.</p>
<h2 id="heading-step-10-how-to-build-the-app-and-publish-it">Step 10. How to Build the App and Publish It</h2>
<p>Once we are happy with our app and are ready to publish it, we can build it with the following command:</p>
<pre><code class="lang-bash">npm run build
</code></pre>
<p>This command will create an optimized production build for our project and will output what files it has generated and how large each file is:</p>
<pre><code class="lang-bash">Compiled successfully.

File sizes after gzip:

  46.62 KB  build/static/js/2.1500c654.chunk.js
  1.59 KB   build/static/js/3.8022f77f.chunk.js
  1.17 KB   build/static/js/runtime-main.86c7b7c2.js
  649 B     build/static/js/main.ef6580eb.chunk.js
  430 B     build/static/css/main.5ae9c609.chunk.css
</code></pre>
<p>The output is coming from the build tool Webpack. </p>
<p>It helps to give us an idea of the size of our app files because the size of our .js files in particular can make a large impact on our app's performance.</p>
<p>Each chunk includes a unique string or hash, which will change on every build to make sure any new deployment is not saved (cached) by the browser. </p>
<p>If we did not have this cache-busting hash for each of our files, we likely couldn't see any changes we made to our app.</p>
<p>Finally, we can run our built React project locally with the help of the npm package <code>serve</code>. </p>
<p>This is helpful to detect any errors we might have with the final version of our project before pushing live to the web.</p>
<p>Like create-react-app, we can use npx to run <code>serve</code> without installing it globally on our computer.</p>
<pre><code class="lang-bash">npx serve
</code></pre>
<p>Using <code>serve</code>, our app will start up on a different development port instead of 3000. In this case, localhost:5000.</p>
<p>And with that, we have a completed React application ready to publish live to the web on any deployment service, such as Netlify, Github Pages, or Heroku!</p>
<h2 id="heading-become-a-professional-react-developer">Become a Professional React Developer</h2>
<p>React is hard. You shouldn't have to figure it out yourself.</p>
<p>I've put everything I know about React into a single course, to help you reach your goals in record time:</p>
<p><a target="_blank" href="https://www.thereactbootcamp.com"><strong>Introducing: The React Bootcamp</strong></a></p>
<p><strong>It’s the one course I wish I had when I started learning React.</strong></p>
<p>Click below to try the React Bootcamp for yourself:</p>
<p><a target="_blank" href="https://www.thereactbootcamp.com"><img src="https://reedbarger.nyc3.digitaloceanspaces.com/reactbootcamp/react-bootcamp-cta-alt.png" alt="Click to join the React Bootcamp" width="600" height="400" loading="lazy"></a>
<em>Click to get started</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The React Scripts Start Command – Create-React-App NPM scripts explained ]]>
                </title>
                <description>
                    <![CDATA[ Creating a React application requires you to set up build tools such as Babel and Webpack. These build tools are required because React's JSX syntax is a language that the browser doesn't understand.  To run your React application, you need to turn y... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-react-app-npm-scripts-explained/</link>
                <guid isPermaLink="false">66bd914dabf0ccf74f1ce9b0</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ npm ]]>
                    </category>
                
                    <category>
                        <![CDATA[ npm scripts ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Nathan Sebhastian ]]>
                </dc:creator>
                <pubDate>Mon, 04 Jan 2021 16:15:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/12/cra-npm-scripts-explained.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Creating a React application requires you to set up build tools such as Babel and Webpack. These build tools are required because React's JSX syntax is a language that the browser doesn't understand. </p>
<p>To run your React application, you need to turn your JSX into plain JavaScript, which browsers understand.</p>
<p><a target="_blank" href="https://github.com/facebook/create-react-app">Create React App (CRA)</a> is a tool to create single-page React applications that is officially supported by the React team. </p>
<p>The script generates the required files and folders to start the React application and run it on the browser. This allows you to focus on coding your application without having to bother with build configurations.</p>
<h2 id="heading-the-dependencies-that-create-react-app-uses">The dependencies that create-react-app uses</h2>
<p>Although you can't see Babel or Webpack listed as dependencies in the generated <code>package.json</code> file, CRA still uses Babel and Webpack under the hood. It's just that the configurations are hidden from you inside the <a target="_blank" href="https://github.com/facebook/create-react-app/tree/master/packages/react-scripts"><code>react-scripts</code> package</a>.</p>
<p>When you look into the <code>package.json</code> file of react-scripts, you'll see all the packages needed to make React works in the browser. It has 58 packages, from line 31 to 88:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/package.json#L30">https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/package.json#L30</a></div>
<p>That's a lot of packages! Let's break it down a little to understand what these packages are used for.</p>
<p><em>Please note that this article was written using Create React App version 4.0.1 as the reference. This article will help you understand what happens under the hood when you use Create React App NPM scripts.</em></p>
<h3 id="heading-babel">Babel</h3>
<p>The main purpose of Babel is to make your code readable by older browsers. Since the release of ES 2015, browsers have seen slow but steady progress to implement new JavaScript APIs and features. </p>
<p>The most advanced browsers like Chrome and Safari may support new JavaScript versions, but JSX is a React-only feature that's not a part of ES versions.</p>
<p>Babel transforms your modern JavaScript code into the older version, and then adds <em>polyfills</em>, a piece of code that implements features missing in the browser but needed by your app.</p>
<h3 id="heading-eslint">ESLint</h3>
<p>ESLint is a JavaScript linter that will scan your code and flag any code errors. The library will warn you from the console if you have any errors. It also plays well with a modern code editor like VSCode.</p>
<h3 id="heading-jest">Jest</h3>
<p>Jest is a testing library by Facebook that plays very well with React. The dependencies for Jest allow you to write test scripts for your application without having to install another testing library.</p>
<h3 id="heading-postcss">PostCSS</h3>
<p>PostCSS is a JavaScript plugin to transform your CSS. PostCSS plugins can lint your CSS, support variables and mixins syntax, transpile future CSS syntax, and many more things depending on its configs.</p>
<h3 id="heading-webpack">Webpack</h3>
<p>Webpack is a module bundler for JavaScript that puts everything needed by your application together. This library can also run tasks like running Babel, Jest, ESLint, and PostCSS on top of your code.</p>
<p>Now that you have an idea what the dependencies are used for, let's continue with understanding what <code>react-scripts</code> really do behind the scene.</p>
<h2 id="heading-what-react-scripts-do">What react-scripts do</h2>
<p>react-scripts are simply scripts to run the build tools required to transform React JSX syntax into plain JavaScript programmatically. </p>
<p>There are four scripts provided by this package:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts: {
  "</span>start<span class="hljs-string">": "</span>react-scripts start<span class="hljs-string">",
  "</span>build<span class="hljs-string">": "</span>react-scripts build<span class="hljs-string">",
  "</span>test<span class="hljs-string">": "</span>react-scripts test<span class="hljs-string">",
  "</span>eject<span class="hljs-string">": "</span>react-scripts eject<span class="hljs-string">"
},</span>
</code></pre>
<p>When you run one of the scripts, the <a target="_blank" href="https://github.com/facebook/create-react-app/tree/master/packages/react-scripts/bin">/bin/react-scripts.js</a> will be executed to start the process. This script will look into the arguments that you passed into the call. It only accepts start, build, test, and eject arguments.</p>
<p>Any other argument you passed will cause the script to return an unknown script to the log:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/cra-unknown-script-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>CRA unknown script console output</em></p>
<p>When you pass a valid argument, it will run the scripts located inside the <a target="_blank" href="https://github.com/facebook/create-react-app/tree/master/packages/react-scripts/scripts"><code>/scripts</code> folder</a>. Let's start by looking at the <code>start.js</code> script.</p>
<h2 id="heading-how-the-react-scripts-start-process-works">How the react-scripts start process works</h2>
<p>With the <code>start</code> argument, NPM will begin the process to make a development server available for your React application. Here's a list of tasks for this script:</p>
<ul>
<li>Set the build environment into <code>development</code> for Node and Babel</li>
<li>Ensure environment variables are read for the build process </li>
<li>Verify the packages installed in your project are not outdated</li>
<li>Check whether the code is in TypeScript or not</li>
<li>Import required packages for the process, mostly Webpack-related modules</li>
<li>Check for available port and host IP, defaults to 0.0.0.0:3000</li>
<li>Run the compiler and listen for any messages from Webpack. Webpack will take care of using Babel, ESLint, and any other tools to prepare your code</li>
<li>While Webpack is running, the script will open your browser and start the development server</li>
</ul>
<p>The development server created by <a target="_blank" href="https://github.com/facebook/create-react-app/blob/8bf050aa7c16078fed5e51ac8388d6100c29e105/packages/react-scripts/scripts/start.js#L37">WebpackDevServer</a> will also create a listener for changes in your JavaScript file. When you make changes and save your JavaScript file, the development server will recompile your code and quickly refresh the browser.</p>
<h2 id="heading-how-to-use-the-react-scripts-build-command">How to use the react-scripts build command</h2>
<p>The <code>build</code> command will start the process of creating a production-ready React app for you. Mostly, it does the same step as a <code>start</code> command, except that it sets the build environment to <code>production</code>.</p>
<p>Instead of checking for available ports and running a development server, the script will run the <a target="_blank" href="https://github.com/facebook/create-react-app/blob/8bf050aa7c16078fed5e51ac8388d6100c29e105/packages/react-scripts/scripts/build.js#L152"><code>build</code></a> <a target="_blank" href="https://github.com/facebook/create-react-app/blob/8bf050aa7c16078fed5e51ac8388d6100c29e105/packages/react-scripts/scripts/build.js#L152">function</a>, which will bundle all your separate files into one <code>bundle.js</code> file. The production build will also ensure that your code is optimized and minified to make sure it has the best performance.</p>
<p>If you've already run the <code>build</code> command before, the script will take your current file size and compare it with the next build. It will show you how much the file size has changed:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/cra-build-result.png" alt="Image" width="600" height="400" loading="lazy">
<em>React shows comparison after gzip in the console</em></p>
<p>The final output of this command can be found in the <code>build/</code> folder, which is generated at your project's root.</p>
<h2 id="heading-how-to-use-the-react-scripts-test-command">How to use the react-scripts test command</h2>
<p>The <code>test</code> command will run any test scripts that you've written using <a target="_blank" href="https://jestjs.io/">Jest</a>. Your tests will be run under a Node environment. Jest will run under the interactive watch mode, which means every time you save a file, it will re-run the tests, like how the <code>start</code> command recompiles the code.</p>
<p>You can save your test files anywhere inside the <code>src/</code> folder, and the script will find and execute any file with <code>.test.js</code> or <code>.spec.js</code> extensions. It will also run any <code>.js</code> file under the <code>__tests__/</code> folder.</p>
<p>You can see the test result from the terminal:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/cra-test-result-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Console log of react-scripts test command result</em></p>
<p>Keep in mind that CRA's test command only covers testing your component and business logic under a stable environment. To run an end-to-end test in the browser, you need to use another testing library.</p>
<h2 id="heading-how-to-use-the-react-scripts-eject-command">How to use the react-scripts eject command</h2>
<p>The last command, <code>eject</code>, is used to remove the dependency on <code>react-scripts</code> and expose the build tools and configurations for you to modify. </p>
<p>All the configuration files from <code>react-scripts</code> will be copied into your project root's <code>config/</code> folder, and the scripts to run the build will be copied into the <code>scripts/</code> folder. The dependencies will also be moved into your root's <code>package.json</code> file.</p>
<p>This command is a one-way operation. Once you have ejected from CRA set up, you can't undo it. If you have committed your code into a source code management system like Git, you can undo the changes with <code>git checkout</code> or <code>git reset</code>.</p>
<p>Generally, you don't need to run this command because CRA has already provided sensible configurations suitable for small and mid-sized projects. If you're interested to learn more, I have written a post about ejecting your React App here:</p>
<p><a target="_blank" href="https://sebhastian.com/create-react-app-eject/">Should you eject your Create React App?</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>As more people use CRA, the development team will receive more feedback about how the tool is used in real projects. The insights gained by the development team will ensure that CRA will stay updated with the latest tools and has best practices for building React apps.</p>
<p>If you enjoyed this article and want to take your JavaScript skills to the next level, I recommend you check out my new book <em>Beginning Modern JavaScript</em> <a target="_blank" href="https://www.amazon.com/dp/B0CQXHMF8G">here</a>.</p>
<p><a target="_blank" href="https://www.amazon.com/dp/B0CQXHMF8G"><img src="https://www.freecodecamp.org/news/content/images/2024/01/beginning-js-cover.png" alt="beginning-js-cover" width="600" height="400" loading="lazy"></a></p>
<p>The book is designed to be easy to understand and accessible to anyone looking to learn JavaScript. It provides a step-by-step gentle guide that will help you understand how to use JavaScript to create a dynamic application.</p>
<p>Here's my promise: <em>You will actually feel like you understand what you're doing with JavaScript.</em></p>
<p>Until next time!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Install React.js with create-react-app ]]>
                </title>
                <description>
                    <![CDATA[ By Cem Eygi React is one of the most popular JavaScript libraries in the web development field today. As a Frontend Developer, I have personally worked with React in my projects and probably will continue to work with it in the future. One of the ste... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/install-react-with-create-react-app/</link>
                <guid isPermaLink="false">66d45decbc9760a197a10363</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ npm ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 28 Oct 2020 00:12:06 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c980e740569d1a4ca17e8.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Cem Eygi</p>
<p>React is one of the most popular JavaScript libraries in the web development field today.</p>
<p>As a Frontend Developer, I have personally worked with React in my projects and probably will continue to work with it in the future. One of the steps that many people struggle with is the installation/configuration process of React.</p>
<p>So let's start with the basics. In this post, you are going to learn how to install and run a React application the easy way.</p>
<p>Since interest in learning React is also increasing rapidly day by day, I have also decided to create video tutorials about React on <a target="_blank" href="https://www.youtube.com/channel/UC1EgYPCvKCXFn8HlpoJwY3Q/">my YouTube channel</a>. Here's a video version of this tutorial:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/QJZ-xgt4SJo" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-how-to-download-amp-install-nodejs">How to Download &amp; Install Node.js</h2>
<p>First of all, you are going to need NPM (or Yarn, alternatively). Let's use NPM for this example.</p>
<p>If you don't have it installed on your system, then you need to head to the <a target="_blank" href="https://nodejs.org/en/">official Node.js website</a> to download and install Node, which also includes NPM (Node Package Manager).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/nodejs.png" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://nodejs.org/en/">Node.js' official website</a></em></p>
<p>Select the "Recommended For Most Users" button and download the current version for your operating system.</p>
<p>After you download and install Node, start your terminal/command prompt and run <code>node -v</code> and <code>npm -v</code> to see which versions you have.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/t1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Your version of NPM should be at least 5.2.0 or newer because create-react-app requires that we have <a target="_blank" href="https://github.com/npm/npm/releases/tag/v5.2.0">NPX</a> installed. If you have an older version of NPM, run this command to update it:</p>
<pre><code>npm install -g npm
</code></pre><h2 id="heading-what-is-create-react-app">What is create-react-app?</h2>
<p>Since it is complicated and takes a lot of time, we don't want to configure React manually. create-react-app is a much easier way which does all the configuration and necessary package installations for us automatically and starts a new React app locally, ready for development.</p>
<p>Another advantage of using create-react-app is that you don't have to deal with Babel or Webpack configurations. All of the necessary configurations will be made by create-react-app for you.</p>
<p><a target="_blank" href="https://reactjs.org/docs/create-a-new-react-app.html">According to the React document</a>ation, create-react-app is one of the officially supported ways to create single-page applications in React. You can find other ways <a target="_blank" href="https://reactjs.org/docs/create-a-new-react-app.html">here</a>.</p>
<h3 id="heading-how-to-install-create-react-app">How to Install Create-React-App</h3>
<p>In order to install your app, first go to your workspace (desktop or a folder) and run the following command:</p>
<pre><code class="lang-js">npx create-react-app my-app
</code></pre>
<p>The installation process may take a few minutes. After it is done, you should see a folder that appears in your workspace with the name you gave to your app.</p>
<blockquote>
<p>Note: If you're on Mac and receiving permission errors, don't forget to be a super user first with the sudo command.</p>
</blockquote>
<h3 id="heading-how-to-run-the-app-you-created-with-create-react-app">How to Run the App You Created with Create-React-App</h3>
<p>After the installation is completed, change to the directory where your app was installed:</p>
<pre><code>cd my-app
</code></pre><p>and finally run <code>npm start</code> to see your app live on localhost:</p>
<pre><code>npm start
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2020/10/rw.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you see something like this in your browser, you are ready to work with React. Congratulations! :)</p>
<p>Thank you for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up a React App with Parcel ]]>
                </title>
                <description>
                    <![CDATA[ By Bob Ziroll For a long time Webpack was one of the biggest barriers-to-entry for someone wanting to learn React. There's a lot of boilerplate configuration that can be confusing, especially if you're new to React.  Even in a talk trying to show how... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-up-a-react-app-with-parcel/</link>
                <guid isPermaLink="false">66d45dd78812486a37369c6b</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 29 Jul 2020 20:16:24 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c997b740569d1a4ca1ff3.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Bob Ziroll</p>
<p>For a long time <a target="_blank" href="https://webpack.js.org/">Webpack</a> was one of the biggest barriers-to-entry for someone wanting to learn React. There's a lot of boilerplate configuration that can be confusing, especially if you're new to React. </p>
<p>Even in <a target="_blank" href="https://youtu.be/BXTU4NmMu8A?t=307">a talk trying to show how easy React is to set up</a>, it can be very difficult to try and learn each and every step in the setup process.</p>
<p>Not too long after React was first out of beta, the team at Facebook made <a target="_blank" href="https://github.com/facebook/create-react-app">create-react-app</a>. It was an attempt to make spinning up a (very fully-loaded version of a) React app as simple as typing a single command:</p>
<pre><code class="lang-js">npx create-react-app my-app
</code></pre>
<p>Nice! And honestly, this ? method of creating a new React app is awesome if you want something that has lots of bells and whistles right from the get-go, <strong>and</strong> you're okay with having your app start as a fairly heavy/large app. </p>
<p>That heaviness comes from the many dependencies, loaders, plugins, and so on automatically installed as <code>node_modules</code> that take up a lot of space for each app. The Finder summary image below is from one of my create-react-app apps. ?</p>
<p><img src="https://coursework.vschool.io/content/images/2020/07/node_modules.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://coursework.vschool.io/content/images/2020/07/tfugj4n3l6ez.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-introducing-parcel">Introducing Parcel</h2>
<p><a target="_blank" href="https://parceljs.org/">Parcel</a> is a "Blazing fast, zero configuration web application bundler." This means it handles a lot of the hard bundling stuff for you under the hood <strong>and</strong> allows you to create a relatively lean setup of React (or any other web project that requires <a target="_blank" href="https://medium.com/madhash/understanding-the-concept-of-bundling-for-beginners-f2db1adad724">bundling</a>).</p>
<p>So, let's see what it takes to set up the bare bones "Hello World" React app that displays an <code>h1</code> element.</p>
<h3 id="heading-step-1-create-a-new-folder-for-your-project">Step 1: Create a new folder for your project</h3>
<p>Easy enough. ?</p>
<h3 id="heading-step-2-create-your-packagejson-file">Step 2: Create your <code>package.json</code> file</h3>
<p>In terminal, <code>cd</code> into the new folder and run:</p>
<pre><code class="lang-bash">npm init -y
</code></pre>
<p>This automatically creates the <code>package.json</code> file.</p>
<h3 id="heading-step-3-install-parcel-react-and-reactdom">Step 3: Install Parcel, React, and ReactDOM</h3>
<pre><code class="lang-bash">npm install --save-dev parcel-bundler
<span class="hljs-comment"># Shorthand version: npm i -D parcel-bundler</span>

npm install react react-dom
<span class="hljs-comment"># Shorthand version: npm i react react-dom</span>
<span class="hljs-comment"># Note that npm will automatically save dependencies to package.json now, so there's no longer a need to do npm install --save ...</span>
</code></pre>
<h3 id="heading-step-4-add-a-start-script-to-packagejson">Step 4: Add a "start" script to <code>package.json</code></h3>
<p>In the <code>package.json</code> file, in the "scripts" section, add the following "start" script:</p>
<pre><code class="lang-json"><span class="hljs-string">"start"</span>: <span class="hljs-string">"parcel index.html --open"</span>
</code></pre>
<h3 id="heading-step-5-create-the-indexhtml-file-and-add-a-couple-lines">Step 5: Create the <code>index.html</code> file and add a couple lines</h3>
<p>In VS Code, you can create a new file called <code>index.html</code> and use the built-in <a target="_blank" href="https://code.visualstudio.com/docs/editor/emmet">emmet</a> shortcut to create a standard boilerplate HTML file by typing an exclamation point and hitting the Tab key on your keyboard.</p>
<p><img src="https://coursework.vschool.io/content/images/2020/07/Screen-Shot-2020-07-29-at-10.17.34-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Type ! and hit the Tab key</em></p>
<p><img src="https://coursework.vschool.io/content/images/2020/07/Screen-Shot-2020-07-29-at-10.18.10-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>? Poof!</em></p>
<p>Before we move on, we need to add 2 things:</p>
<ol>
<li>A <code>div</code> placeholder where our React app will be inserted</li>
<li>A <code>script</code> to read in the JavaScript entry file (which we will create next)</li>
</ol>
<p>In the <code>body</code> of <code>index.html</code>, add:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./index.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<h3 id="heading-step-6-create-the-indexjs-file">Step 6: Create the <code>index.js</code> file</h3>
<p>Create a new file called <code>index.js</code> and enter your bare bones React code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// index.js</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom"</span>

ReactDOM.render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello world!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>, <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>))
</code></pre>
<h3 id="heading-step-7-start-it-up">Step 7: Start it up!</h3>
<p>That's it! Now from the terminal, run:</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>Parcel will handle the rest, and you'll have a fully-functional React app.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>If you're interested, take some time to <a target="_blank" href="https://parceljs.org/getting_started.html">peruse the Parcel documentation</a> to better understand all the awesomeness that comes with using Parcel, without requiring any configuration on your end. </p>
<p>Out of the box, Parcel comes with support for all kinds of common web development extensions, transpilers, syntaxes, and so on.</p>
<p>Although it's not <em>tiny</em>, the node_modules from a Parcel app take up 50% less space on your computer:</p>
<p><img src="https://coursework.vschool.io/content/images/2020/07/Screen-Shot-2020-07-29-at-10.31.58-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Thanks, Parcel!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Setup HTTPS Locally with create-react-app ]]>
                </title>
                <description>
                    <![CDATA[ By Braedon Gough Running HTTPS in development is helpful when you need to consume an API that is also serving requests via HTTPS.  In this article, we will be setting up HTTPS in development for our create-react-app with our own SSL certificate.  Thi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-set-up-https-locally-with-create-react-app/</link>
                <guid isPermaLink="false">66d45dd7182810487e0ce0f9</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ how-to ]]>
                    </category>
                
                    <category>
                        <![CDATA[ http ]]>
                    </category>
                
                    <category>
                        <![CDATA[ https ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 21 Jul 2020 16:12:05 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/07/react-https.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Braedon Gough</p>
<p>Running HTTPS in development is helpful when you need to consume an API that is also serving requests via HTTPS. </p>
<p>In this article, we will be setting up HTTPS in development for our create-react-app with our own SSL certificate. </p>
<p>This guide is for macOS users and requires that you have <code>[brew](https://brew.sh/)</code> installed. </p>
<h2 id="heading-adding-https">Adding HTTPS</h2>
<p>In your <code>package.json</code>, update the <strong>start</strong> script to include https: </p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"HTTPS=true react-scripts start"</span>,
    <span class="hljs-attr">"build"</span>: <span class="hljs-string">"react-scripts build"</span>,
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"react-scripts test"</span>,
    <span class="hljs-attr">"eject"</span>: <span class="hljs-string">"react-scripts eject"</span>
  },
</code></pre>
<p>Running <code>yarn start</code> after this step will show you this screen in your browser:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/privacy-error.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>At this stage, you're already set to go with <code>https</code>. But you don't have a valid certificate, so your connection is assumed to be insecure. </p>
<h2 id="heading-creating-a-ssl-certificate">Creating a SSL Certificate</h2>
<p>The easiest way to obtain a certificate is via <code>[mkcert](https://github.com/FiloSottile/mkcert)</code>.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Install mkcert tool</span>
brew install mkcert

<span class="hljs-comment"># Install nss (only needed if you use Firefox)</span>
brew install nss

<span class="hljs-comment"># Setup mkcert on your machine (creates a CA)</span>
mkcert -install
</code></pre>
<p>After running the above commands, you'll have created a <strong><a target="_blank" href="https://en.wikipedia.org/wiki/Certificate_authority">certificate authority</a></strong> on your machine which enables you to generate certificates for all of your future projects. </p>
<p>From the root of your <code>create-react-app</code> project, you should now run:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create .cert directory if it doesn't exist</span>
mkdir -p .cert

<span class="hljs-comment"># Generate the certificate (ran from the root of this project)</span>
mkcert -key-file ./.cert/key.pem -cert-file ./.cert/cert.pem <span class="hljs-string">"localhost"</span>
</code></pre>
<p>We'll be storing our generated certificates in the <code>.cert</code> directory. These should not be committed to version control, so you should update your <code>.gitignore</code> to include the <code>.cert</code> directory. </p>
<p>Next, we need to update the <code>start</code> script again to include our newly created certificate:</p>
<pre><code class="lang-json">  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"HTTPS=true SSL_CRT_FILE=./.cert/cert.pem SSL_KEY_FILE=./.cert/key.pem react-scripts start"</span>,
    <span class="hljs-attr">"build"</span>: <span class="hljs-string">"react-scripts build"</span>,
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"react-scripts test"</span>,
    <span class="hljs-attr">"eject"</span>: <span class="hljs-string">"react-scripts eject"</span>
  },
</code></pre>
<p>When you run <code>yarn start</code> again, you should now see that your connection is secure. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/secure.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Don't be a stranger! Feel free to write if you have any questions - <a target="_blank" href="https://www.linkedin.com/in/braedon-gough-ba92a048/">connect with me on Linkedin</a> or <a target="_blank" href="https://twitter.com/bbbraedddon">follow me on Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Storybook and How Can I Use It to Create a Component Library in React? ]]>
                </title>
                <description>
                    <![CDATA[ Frameworks like React, Vue, and Angular all help developers create modular systems using components, but that doesn't usually include a good way to see them all from a higher point of view.  So how can we use Storybook to build libraries and design s... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-storybook-and-how-can-i-use-it-to-create-a-component-libary-in-react/</link>
                <guid isPermaLink="false">66b8e39c68c5b9f37d1d1af1</guid>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design Tools ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer Tools ]]>
                    </category>
                
                    <category>
                        <![CDATA[ framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Libraries ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Storybook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tools ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Tue, 09 Jun 2020 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/06/storybook.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Frameworks like React, Vue, and Angular all help developers create modular systems using components, but that doesn't usually include a good way to see them all from a higher point of view. </p>
<p>So how can we use Storybook to build libraries and design systems that self-document as we build them?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-storybook">What is Storybook?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-step-0-bootstrapping-an-app">Step 0: Bootstrapping an app</a></li>
<li><a class="post-section-overview" href="#heading-step-1-installing-storybook">Step 1: Installing Storybook</a></li>
<li><a class="post-section-overview" href="#heading-step-2-creating-a-new-button">Step 2: Creating a new button</a></li>
<li><a class="post-section-overview" href="#heading-step-3-using-our-new-button-component">Step 3: Using our new Button component</a></li>
<li><a class="post-section-overview" href="#heading-repeat-creating-a-new-header-component">Repeat: Creating a new Header component</a></li>
<li><a class="post-section-overview" href="#heading-more-storybook-features">More Storybook features</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/VApXDsYO5Gg" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-is-storybook">What is Storybook?</h2>
<p><a target="_blank" href="https://storybook.js.org/">Storybook</a> is a JavaScript tool that allows developers to create organized UI systems making both the building process and documentation more efficient and easier to use.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/loneley-planet-storybook-example.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://lonelyplanet.github.io/backpack-ui/?path=/story/cards--card-basic">Lonely Planet's Backpack UI</a></em></p>
<p>Once you build out a component, Storybook lets you create a "story" file where you can then import your component and create various use case examples in an iFramed sandbox using that component.</p>
<p>This provides an organized and focused environment to build new components and work on existing ones.</p>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We're going to bootstrap a new <a target="_blank" href="https://reactjs.org/">React JS</a> app using <a target="_blank" href="https://reactjs.org/docs/create-a-new-react-app.html">Create React App</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/storybook-component-example.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Inside that app, we're going to install Storybook and create a few new components that will help us learn how to create new components that we can work on in a story and then use it in a React app.</p>
<h2 id="heading-step-0-bootstrapping-an-app">Step 0: Bootstrapping an app</h2>
<p>To get started, we're going to start from scratch with <a target="_blank" href="https://reactjs.org/docs/create-a-new-react-app.html">Create React App</a>. This will help us focus on getting productive in Storybook rather than walking through integrating it into a current app.</p>
<p>That said, if you're already working with an app created using Create React App that's not ejected, you should be able to still follow on with Part 1 and beyond just the same!</p>
<p>So let's get started by navigating to where we want to create our new app and run the Create React App command:</p>
<pre><code class="lang-shell">npx create-react-app my-storybook
</code></pre>
<p><em>Note: feel free to replace <code>my-storybook</code> with the directory name of your choice.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/create-new-react-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Bootstrapping with Create React App</em></p>
<p>Once that's finished running, you can navigate to the directory:</p>
<pre><code class="lang-shell">cd my-storybook
</code></pre>
<p>And we're ready to go!</p>
<h2 id="heading-step-1-installing-storybook">Step 1: Installing Storybook</h2>
<p>Storybook luckily makes it really easy to get started with a standard installation of React. Particularly with Create React App, Storybook automatically detects that we're using an app created using CRA and installs the dependencies and scaffolds everything for us.</p>
<h3 id="heading-initializing-storybook">Initializing Storybook</h3>
<p>To get started installing Storybook, run:</p>
<pre><code class="lang-shell">npx -p @storybook/cli sb init
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/initializing-storybook.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Initializing Storybook in a React app</em></p>
<p>If you aren't using Create React App or it didn't work, you can check out their <a target="_blank" href="https://storybook.js.org/docs/guides/guide-react/">available guides in their docs</a>.</p>
<p>After that's finished, all of our Storybook dependencies should be installed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/storybook-finished-installing.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Finished installing Storybook</em></p>
<h3 id="heading-starting-up-storybook">Starting up Storybook</h3>
<p>So now we're ready to get moving! Finally, run:</p>
<pre><code class="lang-shell">yarn storybook
# or
npm run storybook
</code></pre>
<p>And once everything finishes loading, Storybook will open a new tab in your browser and you should now see a welcome message inside of your new Storybook dashboard!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/storybook-welcome-page.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Storybook welcome page</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-storybook/commit/3e994096384e31cb540150c9f14f41758ef3a746">Follow along with the commit!</a></p>
<h2 id="heading-step-2-creating-a-new-button">Step 2: Creating a new button</h2>
<p>If you took a second to poke around the dashboard, you might have noticed that it comes pre-loaded with a Button that's available as a demo.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/storybook-demo-button.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Storybook demo button</em></p>
<p>You should also notice if you click the button, you actually see an action print out inside of the Actions tab at the bottom. This shows the event that's captured from the button click.</p>
<p>It's simple, but this is great to get a nice feel about what to expect in storybook. The only issue is, this is meant purely for demonstration purposes, so let's build our own button to replace it.</p>
<h3 id="heading-creating-a-new-button-component">Creating a new Button component</h3>
<p>To get started, let's first create a few directories:</p>
<ul>
<li>Under <code>src</code>, create a new folder called <code>components</code></li>
<li>Under <code>components</code>, create a new folder called <code>Button</code></li>
</ul>
<p>Once you create those folders, create a new file called <code>index.js</code> inside of your <code>src/components/Button</code> folder and inside add:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Inside src/components/Button/index.js</span>

<span class="hljs-keyword">export</span> { <span class="hljs-keyword">default</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'./Button'</span>;
</code></pre>
<p>This will import the next file we created called <code>Button.js</code> which will allow us to more easily import our files with <code>src/components/Button</code> instead of <code>/src/components/Button/Button</code>.</p>
<p>Next, let's create <code>Button.js</code> right next to our <code>index.js</code> file with the following content:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Inside src/components/Button/Button.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> Button = <span class="hljs-function">(<span class="hljs-params">{ children, ...rest }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"button"</span> {<span class="hljs-attr">...rest</span>}&gt;</span>
      { children }
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Button;
</code></pre>
<p>Here, we're creating a new component called Button that adds a class of <code>button</code> to the element and passes through the <code>children</code>. We're a additionally <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">destructuring</a> the rest of the props into the <code>rest</code> variable and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">spreading</a> that value into the <code>&lt;button&gt;</code> element.</p>
<p>If you've followed along, your files should now look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/button-reaect-component.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Button component in React</em></p>
<h3 id="heading-using-our-new-button-component">Using our new Button component</h3>
<p>So now that we have our Button component, let's use it!</p>
<p>Open up the file <code>src/stories/1-Button.stories.js</code> and replace the line that's importing <code>Button</code> with:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/updating-button-storybook-story.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Updating the Button Storybook story</em></p>
<p>And once you hit save, you can open back up your browser tab with your Storybook dashboard, and you can now see a button that looks mostly similar, but it uses the browser's default styles for the <code>&lt;button&gt;</code> element. You'll even notice that if you click it, the event will still be logged under the Actions tab.</p>
<h3 id="heading-styling-our-button-component">Styling our Button component</h3>
<p>Finally, we probably don't want to use the browser default styles, so let's make it look nice.</p>
<p>In our <code>src/components/Button</code> directory, add a new file <code>Button.css</code> and add the following content:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Inside src/components/Button/Button.css */</span>

<span class="hljs-selector-class">.button</span> {
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">font-weight</span>: bold;
  <span class="hljs-attribute">background-color</span>: blueviolet;
  <span class="hljs-attribute">border</span>: none;
  <span class="hljs-attribute">padding</span>: .<span class="hljs-number">8em</span> <span class="hljs-number">1em</span>;
  <span class="hljs-attribute">border-radius</span>: .<span class="hljs-number">2rem</span>;
}
</code></pre>
<p>This applies a few styles to our <code>.button</code> class like adding a background color and changing the font color to white.</p>
<p>But if you open Storybook, you'll notice it didn't do anything. To use it, we need to import it into our component.</p>
<p>Inside <code>src/components/Button/Button.js</code> add the following at the top under the React import:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> <span class="hljs-string">'./Button.css'</span>;
</code></pre>
<p>And once you save that and open up your browser, you should now see our new button with our updated styles!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/new-button-storybook.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Button in Storybook</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-storybook/commit/e71e0e9e666adee0455b0b69118053c2f551ab68">Follow along with the commit!</a></p>
<h2 id="heading-step-3-using-our-new-button-component">Step 3: Using our new Button component</h2>
<p>The ultimate goal of our component is to use it right? So let's add it to our app.</p>
<h3 id="heading-switching-over-to-the-react-app">Switching over to the React app</h3>
<p>First we'll need to either start our React app in a new terminal tab or kill the Storybook process and start the React process there. To start the React app using Create React App, run:</p>
<pre><code class="lang-shell">yarn start
# or
npm run start
</code></pre>
<p>Once that loads, we should have our standard Create React App if you're following along with me:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/new-create-react-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Create React App</em></p>
<h3 id="heading-importing-and-using-the-new-button">Importing and using the new button</h3>
<p>Next, inside of <code>src/App.js</code>, let's import our new Button at the top of the page:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Button'</span>;
</code></pre>
<p>With Button imported, we can use it. Here, we can simply add it anywhere we want in the page. I'm going to replace the Learn React link with:</p>
<pre><code class="lang-jsx">&lt;p&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Button</span>&gt;</span>Hello, Storybook!<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span>
&lt;/p&gt;
</code></pre>
<p>And if we save and reload the page, we should now see our Button on the page!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/create-react-app-with-new-button.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Button in Create React App</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-storybook/commit/e6071aae5be281101d486c4cc7664bf6cacb4028">Follow along with the commit</a></p>
<h2 id="heading-repeat-creating-a-new-header-component">Repeat: Creating a new Header component</h2>
<p>The great thing about Storybook and React (or any of the supported frameworks) is that this process scales to as many components as you want.</p>
<p>So let's build another component!</p>
<h3 id="heading-creating-our-header-component">Creating our Header component</h3>
<p>Similar to our Button, let's start off by creating the set of directories and files that give us our component.</p>
<p>Since we already did this once, I'm going to provide the code without walking through what's going on.</p>
<p>Let's start off by spinning back up our Storybook server with:</p>
<pre><code>yarn storybook
# or 
npm run storybook
</code></pre><p>Create a <code>Header</code> directory inside the <code>src/components</code> directory.</p>
<p>Create an <code>index.js</code> file inside of <code>src/components/Header</code> with the following content:</p>
<pre><code class="lang-js"><span class="hljs-comment">// In src/components/Header/index.js</span>

<span class="hljs-keyword">export</span> { <span class="hljs-keyword">default</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'./Header'</span>;
</code></pre>
<p>Create a <code>Header.js</code> file inside of <code>src/components/Header</code> with the following content:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// In src/components/Header/Header.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./Header.css'</span>;

<span class="hljs-keyword">const</span> Header = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"header"</span>&gt;</span>
      { children }
    <span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Header;
</code></pre>
<p>Create a <code>Header.css</code> file inside of <code>src/components/Header</code> with the following content:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* In src/components/Header/Header.css */</span>

<span class="hljs-selector-class">.header</span> {
  <span class="hljs-attribute">font-family</span>: sans-serif;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2.5em</span>;
  <span class="hljs-attribute">color</span>: blueviolet;
  <span class="hljs-attribute">border-bottom</span>: solid <span class="hljs-number">5px</span> aqua;
  <span class="hljs-attribute">padding-bottom</span>: .<span class="hljs-number">2em</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">5px</span> <span class="hljs-number">0</span> blueviolet;
}
</code></pre>
<p>Now if you notice, if you try to open up Storybook, again, nothing will happen. This time we need to create a new story file.</p>
<h3 id="heading-creating-a-new-story-file">Creating a new Story file</h3>
<p>Inside <code>src/stories</code>, add a new file called <code>2-Header.stories.js</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Inside src/stories/2-Header.stories.js</span>

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">import</span> Header <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/Header'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">title</span>: <span class="hljs-string">'Header'</span>,
  <span class="hljs-attr">component</span>: Header,
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Text = <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Header</span>&gt;</span>Hello Header<span class="hljs-tag">&lt;/<span class="hljs-name">Header</span>&gt;</span></span>;
</code></pre>
<p>Here's a breakdown of our story file:</p>
<ul>
<li>First, we import our component – this is pretty standard any time we want to use it</li>
<li>The first thing we export is a <code>default</code> object. With Storybook, it expects the default export to be the configuration of our story, so here we provide it with a title and we pass in the component that we're using for this story</li>
<li>The second and last thing we export is the <code>Text</code> constant. With Storybook, any non-default export will be considered a variation that will get nested under the title that you provide in the default export</li>
</ul>
<p>And if you save this file and open up your Storybook dashboard in the browser, you should now see the new header!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/new-header-storybook-story.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Header component in Storybook</em></p>
<h3 id="heading-using-the-header-component">Using the Header component</h3>
<p>Using our component is just the same as our Button component, so inside of <code>src/App.js</code>, let's add our Header.</p>
<p>After starting your React server, first import our new Header:</p>
<pre><code class="lang-js"><span class="hljs-comment">// In src/App.js</span>

<span class="hljs-keyword">import</span> Header <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Header'</span>;
</code></pre>
<p>Then add it to the top of the page:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// In src/App.js</span>

&lt;Header&gt;My App&lt;/Header&gt;
</code></pre>
<p>And if you open the page, we'll see our new Header!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/create-react-app-with-header-and-button.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Create React App with new Header and Button components</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-storybook/commit/e1c59eccaf5f4146a2fe039dca8874609d615194">Follow along with the commit!</a></p>
<h2 id="heading-adding-more-components">Adding more components</h2>
<p>As you've noticed with our second Repeat step – adding a new component is pretty much the same process for any type of component we want to add. Once we have it in our library, we can develop it in a focused environment and then import it to our app to use.</p>
<p>You can now use this to manage your library of components and better maintain an entire system for your project!</p>
<h2 id="heading-more-storybook-features">More Storybook features</h2>
<p>Storybook doesn't stop with just adding components, it provides the ability to configure <a target="_blank" href="https://storybook.js.org/addons/">Addons</a> that enhance the core capabilities opening up a lot of possibilities.</p>
<p>Here are some of my favorites...</p>
<h3 id="heading-story-source">Story Source</h3>
<p>When building a component system, the hope is that people can easily use these components. But if you don't have documentation, someone would have to open up the file or try to find another use example.</p>
<p>Instead, <a target="_blank" href="https://github.com/storybookjs/storybook/tree/master/addons/storysource">Story Source</a> shows the code source of the story file you created allowing someone browsing your Storybook dashboard to get an example right along with the component output!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/storybook-source-demo.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Storybook Story Source demo</em></p>
<h3 id="heading-storyshots">Storyshots</h3>
<p>If you're a fan of automated testing, you might have heard of using <a target="_blank" href="https://jestjs.io/">Jest</a> or another tool for adding snapshot testing to your app.</p>
<p><a target="_blank" href="https://github.com/storybookjs/storybook/tree/master/addons/storyshots/storyshots-core">StoryShots</a> is a way to easily add Jest snapshot testing to your component system. It creates snapshots based off of the stories you create so you can make sure that your components aren't fundamentally changing (or breaking) during development.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/storybook-snapshot-example.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Snapshot example with StoryShots</em></p>
<h2 id="heading-whats-your-favorite-part-of-storybook">What's your favorite part of Storybook?</h2>
<p><a target="_blank" href="https://twitter.com/colbyfayock">Share with me on Twitter!</a></p>
<h2 id="heading-continue-the-conversation">Continue the conversation!</h2>
<div class="embed-wrapper">
        <blockquote class="twitter-tweet">
          <a href="https://twitter.com/colbyfayock/status/1270392710260719616"></a>
        </blockquote>
        <script defer="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="600" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to set up a custom Mapbox basemap style with React Leaflet and Leaflet Gatsby Starter ]]>
                </title>
                <description>
                    <![CDATA[ Building maps can be pretty powerful, but often you’re stuck with open source options for the map imagery that might not help the readability of your data. How can we leverage Mapbox’s tile APIs to add a custom basemap to our React Leaflet app? What... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-set-up-a-custom-mapbox-basemap-with-gatsby-and-react-leaflet/</link>
                <guid isPermaLink="false">66b8e36647c23b7ae1ad0bdb</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mapbox ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 08 Apr 2020 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-basemap-react-leaflet-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Building maps can be pretty powerful, but often you’re stuck with open source options for the map imagery that might not help the readability of your data. How can we leverage Mapbox’s tile APIs to add a custom basemap to our React Leaflet app?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-mapbox">What is Mapbox?</a></li>
<li><a class="post-section-overview" href="#heading-part-1-creating-a-custom-mapbox-style">Part 1: Creating a custom Mapbox style</a></li>
<li><a class="post-section-overview" href="#heading-part-2-adding-a-custom-tilelayer-to-react-leaflet">Part 2: Adding a custom TileLayer to React Leaflet</a></li>
<li><a class="post-section-overview" href="#heading-part-3-adding-a-custom-basemap-to-gatsby-starter-leaflet">Part 3: Adding a custom basemap to Gatsby Starter Leaflet</a></li>
<li><a class="post-section-overview" href="#heading-securing-your-mapbox-key">Securing your Mapbox key</a></li>
<li><a class="post-section-overview" href="#heading-want-to-learn-more-about-maps">Want to learn more about maps?</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/KcPJr1b_rv0" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We’re going to walk through creating a new basic <a target="_blank" href="https://www.mapbox.com/mapbox-studio/">Mapbox style</a> in our <a target="_blank" href="https://www.mapbox.com/">Mapbox</a> account. Once created, we’re going to use their <a target="_blank" href="https://docs.mapbox.com/api/maps/">Map API</a> to add a custom basemap to our <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet</a> app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/gatsby-starter-leaflet-with-mapbox-tilelayer.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Gatsby Starter Leaflet with Mapbox basemap</em></p>
<p>For our map, we’re going to use this <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Leaflet Gatsby Starter</a> I created that will allow you to easily spin up a new mapping app. Before we spin that up though, I’ll walk you through how to add it using only React Leaflet components.</p>
<h2 id="heading-a-mapping-app">A mapping app?</h2>
<p>Yup! Maps are used all around the world to study datasets for geographic locations. They're important tools for scientists and others that are trying to help the world.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-map-dashboard-demo.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Coronavirus (COVID-19) custom map</em></p>
<p>If you want to learn more about building a map and adding data to it, you can check out some of <a target="_blank" href="https://www.freecodecamp.org/news/author/colbyfayock/">my other articles</a> first such as creating a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-a-coronavirus-covid-19-dashboard-map-app-in-react-with-gatsby-and-leaflet/">Coronavirus (COVID-19) map</a> or a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet/">Summer Road Trip map</a> as well as a little bit of inspiration about why <a target="_blank" href="https://www.freecodecamp.org/news/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping/">Anyone Can Map</a>.</p>
<h2 id="heading-what-is-mapbox">What is Mapbox?</h2>
<p>Mapbox is a mapping platform that allows its customers to create custom mapping solutions. They also leverage a variety of APIs that provide powerful capabilities for building map features.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-homepage.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.mapbox.com/">mapbox.com</a></em></p>
<p>For our purposes, we’re going to utilize their Map API, specifically their Static Tiles API, to serve a custom map style that we create.</p>
<h2 id="heading-part-1-creating-a-custom-mapbox-style">Part 1: Creating a custom Mapbox style</h2>
<p>To get the look and feel that we want for our map, it’s important to have a basemap that helps make our data present itself without distractions. Plus, sometimes it’s fun to have a custom map.</p>
<h3 id="heading-mapbox-account">Mapbox account</h3>
<p>The first thing we’ll need to set up our custom Mapbox style is to have an account. I'm not going to walk you through that process, but you can head over to <a target="_blank" href="https://www.mapbox.com/">Mapbox’s website</a> where you can sign up for free: <a target="_blank" href="https://www.mapbox.com/">mapbox.com</a></p>
<h3 id="heading-creating-a-new-custom-style">Creating a new custom style</h3>
<p>Creating a new style in Mapbox isn’t as hard as it sounds. While it can get really complex if you want something unique, we can copy one of Mapbox’s default styles to get started.</p>
<p>First, head over to Mapbox’s <a target="_blank" href="https://studio.mapbox.com/">Studio dashboard</a> by clicking your account link in the top right corner when logged in.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-studio.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Mapbox Studio</em></p>
<p>Once we’re on our Studio dashboard, we want to select the New Style button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-studio-new-style.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Create a new style in Mapbox Studio</em></p>
<p>After clicking the button, a modal will pop up allowing you to choose a template. You can choose whatever you want here, but I’m going to choose Monochrome with a variation of Dark. And after you’ve selected your template, click the Customize button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-studio-new-style-choose-template.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Select and customize a template for a new style in Mapbox Studio</em></p>
<p>And now we’re dropped into our customization UI.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-customize-style.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Mapbox customize style UI</em></p>
<p>From here, you can really do what you’d like. There are a ton of options to customize your map. It’s a little complex to try to dig in here, but <a target="_blank" href="https://docs.mapbox.com/studio-manual/overview/">Mapbox provides some resources</a> to try to help you get productive.</p>
<h3 id="heading-generating-a-mapbox-token">Generating a Mapbox token</h3>
<p>Once you’re happy with your new style and everything’s published, we want to generate a token that we’ll use for providing access to our Map.</p>
<p>Head on over to the Account section of the Mapbox dashboard.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-account.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new token in Mapbox</em></p>
<p>Mapbox provides you with a “default” token that you can use in your applications. You're free to use this, but I recommend creating a new token that you can provide a unique name, that way if you ever blow past the <a target="_blank" href="https://www.mapbox.com/pricing/">free tier</a> of Mapbox, you’ll be able to track your usage.</p>
<p>Additionally, it’s best to keep a separate token for each application, that way you can easily rotate an individual key, without having to update every application using it.</p>
<p>Once you click Create a token, you can set up the key how you’d like, with the scopes and permissions you choose, but for our purposes, you can leave all of the Public scopes checked for our map, which they do by default.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-create-token.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Create a new access token in Mapbox</em></p>
<h3 id="heading-configuring-our-custom-endpoint">Configuring our custom endpoint</h3>
<p>For this tutorial, we’re going to use <a target="_blank" href="https://docs.mapbox.com/api/maps/#static-tiles">Mapbox’s Static Tiles service</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-static-tiles-map-api.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Mapbox Static Tiles Maps API</em></p>
<p>Our endpoint will look like the following:</p>
<pre><code>https:<span class="hljs-comment">//api.mapbox.com/styles/v1/{username}/{style_id}/tiles/256/{z}/{x}/{y}@2x?access_token={access_token}</span>
</code></pre><p>There are a few parameters here we need to understand:</p>
<ul>
<li>username: this will be your Mapbox account’s username</li>
<li>style_id: this will be the ID of the style you created before</li>
<li>z, x, y: these are parameters that Leaflet programmatically swaps out, so we want to leave them as is</li>
<li>access_token: this is the Mapbox key you created above</li>
</ul>
<p>To find your username and style ID, we can use the Style URL for our new Mapbox style to get those values.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-studio-style-url.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Finding the Style URL in Mapbox Studio</em></p>
<p>In my example, my Style URL looks like:</p>
<pre><code>mapbox:<span class="hljs-comment">//styles/colbyfayock/ck8lryjfq0jdo1ip9ctmuhc6p</span>
</code></pre><p><code>colbyfayock</code> is my username and <code>ck8lryjfq0jdo1ip9ctmuhc6p</code> is my style ID.</p>
<p>And once I update my endpoint parameters, the final tilepoint URL will look like:</p>
<pre><code>https:<span class="hljs-comment">//api.mapbox.com/styles/v1/colbyfayock/ck8lryjfq0jdo1ip9ctmuhc6p/tiles/256/{z}/{x}/{y}@2x?access_token=MYACCESSTOKEN</span>
</code></pre><h2 id="heading-part-2-adding-a-custom-tilelayer-to-react-leaflet">Part 2: Adding a custom TileLayer to React Leaflet</h2>
<p>When building a map with React Leaflet, your main component will be a <code>&lt;Map&gt;</code> that wraps the entirety of the app. This is what sets up your <a target="_blank" href="https://leafletjs.com/reference-1.6.0.html#map-example">Map instance</a> for <a target="_blank" href="https://leafletjs.com/">Leaflet</a>.</p>
<p>For our purposes here, we’re going to use the example on the <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet homepage</a> as our starting point.</p>
<h3 id="heading-react-leaflet-tilelayer-component">React Leaflet TileLayer Component</h3>
<p>Inside of your <code>&lt;Map&gt;</code> component you include a <code>&lt;TileLayer&gt;</code> component, which defines the imagery of the world that you base your map upon.</p>
<p>The example on the React Leaflet homepage uses a public version of <a target="_blank" href="https://www.openstreetmap.org/">OpenStreetMap</a> as their TileLayer, which is an open source map project created and updated by people all around the world.</p>
<pre><code class="lang-react">&lt;Map center={position} zoom={13}&gt;
  &lt;TileLayer
    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
    attribution="&amp;copy; &lt;a href=&amp;quot;http://osm.org/copyright&amp;quot;&gt;OpenStreetMap&lt;/a&gt; contributors"
  /&gt;
&lt;/Map&gt;
</code></pre>
<p>This gives you a basic map, but we want to swap in Mapbox so we can set up a custom look and feel for our map.</p>
<h3 id="heading-custom-mapbox-tilelayer">Custom Mapbox TileLayer</h3>
<p>To add our custom style, we’ll want to update the <code>url</code> and <code>attribution</code> props of the <code>TileLayer</code> component.</p>
<p>For URL, it will simply be the custom style endpoint we created earlier, so in my example, it looks like:</p>
<pre><code>https:<span class="hljs-comment">//api.mapbox.com/styles/v1/colbyfayock/ck8lryjfq0jdo1ip9ctmuhc6p/tiles/256/{z}/{x}/{y}@2x?access_token=MYACCESSTOKEN</span>
</code></pre><p>For attribution, we want to credit Mapbox as the service, so we want to set our attribution as:</p>
<pre><code><span class="hljs-built_in">Map</span> data &amp;copy; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&amp;quot;https://www.openstreetmap.org/&amp;quot;</span>&gt;</span>OpenStreetMap<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span> contributors, <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&amp;quot;https://creativecommons.org/licenses/by-sa/2.0/&amp;quot;</span>&gt;</span>CC-BY-SA<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>, Imagery &amp;copy; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&amp;quot;https://www.mapbox.com/&amp;quot;</span>&gt;</span>Mapbox<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>
</code></pre><p>When plugged in to our <code>TileLayer</code>, our code should now look like this:</p>
<pre><code class="lang-react">&lt;Map center={position} zoom={13}&gt;
  &lt;TileLayer
    url="https://api.mapbox.com/styles/v1/colbyfayock/ck8lryjfq0jdo1ip9ctmuhc6p/tiles/256/{z}/{x}/{y}@2x?access_token=MYACCESSTOKEN"
    attribution="Map data &amp;copy; &lt;a href=&amp;quot;https://www.openstreetmap.org/&amp;quot;&gt;OpenStreetMap&lt;/a&gt; contributors, &lt;a href=&amp;quot;https://creativecommons.org/licenses/by-sa/2.0/&amp;quot;&gt;CC-BY-SA&lt;/a&gt;, Imagery &amp;copy; &lt;a href=&amp;quot;https://www.mapbox.com/&amp;quot;&gt;Mapbox&lt;/a&gt;"
  /&gt;
&lt;/Map&gt;
</code></pre>
<p>And once we open up our map, we should see our new basemap!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/react-leaflet-mapbox-basemap.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>React Leaflet with a Mapbox basemap</em></p>
<h3 id="heading-see-the-code">See the code!</h3>
<p>If you want to see how I did it, <a target="_blank" href="https://github.com/colbyfayock/my-mapbox-react-leaflet/commits/master">check out the diff commit by commit</a>.</p>
<p>The only caveat there is I created an <code>.env.development.local</code> file in the root of my project in which I stored a new environment variable called <code>REACT_APP_MAPBOX_KEY</code>  to store my Mapbox key.</p>
<h2 id="heading-part-3-adding-a-custom-basemap-to-gatsby-starter-leaflet">Part 3: Adding a custom basemap to Gatsby Starter Leaflet</h2>
<p>I’ve written <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">a few</a> <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">other</a> <a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping/">articles</a> on <a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">how to get started</a> with my <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Leaflet Gatsby Starter</a>, but for this part, we’ll want to have a basic app spun up that we can use to change our <code>TileLayer</code> endpoint.</p>
<h3 id="heading-setting-up-our-react-leaflet-gatsby-app">Setting up our React Leaflet Gatsby app</h3>
<p>To get started, check out the instructions on the Starter github:</p>
<p><a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">https://github.com/colbyfayock/gatsby-starter-leaflet</a></p>
<p>Once you’re ready, you should have a basic mapping app ready to go!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/gatsby-starter-leaflet-in-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Leaflet Gatsby app in the browser</em></p>
<h3 id="heading-configuring-our-mapbox-service">Configuring our Mapbox service</h3>
<p>The first thing we’ll want to do is add Mapbox as a service in our <code>src/data/map-services.js</code> file.</p>
<p>Taking our custom endpoint URL that we created in Part 1, let’s set up a new object with a name of Mapbox, and with a url and attribution similar to what we did in Part 2.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> mapServices = [
  {
    <span class="hljs-attr">name</span>: ‘OpenStreetMap’,
    <span class="hljs-attr">attribution</span>: <span class="hljs-string">'&amp;copy; &lt;a href="http://osm.org/copyright”&gt;OpenStreetMap&lt;/a&gt; contributors’,
    url: ‘https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png’
  },
  {
    name: ‘Mapbox’,
    attribution: ‘Map data &amp;copy; &lt;a href=&amp;quot;https://www.openstreetmap.org/&amp;quot;&gt;OpenStreetMap&lt;/a&gt; contributors, &lt;a href=&amp;quot;https://creativecommons.org/licenses/by-sa/2.0/&amp;quot;&gt;CC-BY-SA&lt;/a&gt;, Imagery &amp;copy; &lt;a href=&amp;quot;https://www.mapbox.com/&amp;quot;&gt;Mapbox&lt;/a&gt;’,
    url: `https://api.mapbox.com/styles/v1/colbyfayock/ck8c2foj72lqk1jnug0g2haw0/tiles/256/{z}/{x}/{y}@2x?access_token=MY_ACCESS_TOKEN`
  }
];</span>
</code></pre>
<h3 id="heading-using-our-mapbox-map-service">Using our Mapbox map service</h3>
<p>Once you have your Mapbox service set up, all that’s left is to open up the <code>src/pages/index.js</code> file, find the <code>mapSettings</code> object definition, and update the <code>defaultBaseMap</code> property to <code>Mapbox</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mapSettings = {
  <span class="hljs-attr">center</span>: CENTER,
  <span class="hljs-attr">defaultBaseMap</span>: ‘Mapbox’,
  <span class="hljs-attr">zoom</span>: DEFAULT_ZOOM,
  mapEffect
};
</code></pre>
<p>Save that change, refresh the map in your browser, and you should now see your custom basemap style!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/gatsby-starter-leaflet-with-mapbox-tilelayer-in-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Gatsby Starter Leaflet with custom Mapbox basemap in browser</em></p>
<h3 id="heading-see-the-code-1">See the code!</h3>
<p>If you want to see how I did it, <a target="_blank" href="https://github.com/colbyfayock/my-mapbox-gatsby-starter-leaflet/commit/9baa1b7003504dec5c938328ea9b54477f65ec58">check out the diff with the commit</a>.</p>
<p>The only caveat there is I created an <code>.env.development</code> file in the root of my project in which I stored a new environment variable called <code>GATSBY_MAPBOX_KEY</code>  to store my Mapbox key.</p>
<h2 id="heading-securing-your-mapbox-key">Securing your Mapbox key</h2>
<h3 id="heading-environment-variables">Environment variables</h3>
<p>Part of most development processes that use individual keys will generally set the keys up as environment variables. Environment variables are configured settings that don’t live in the code itself.</p>
<p>This is important because it prevents your key from being checked in to your code, which is bad from a security perspective, but it also allows you to provide a different key for different environments.</p>
<p>When generating your keys, try to keep this in mind, as it can save you in the long run.</p>
<h3 id="heading-locking-down-your-mapbox-key">Locking down your Mapbox key</h3>
<p>In your settings when creating a token or when editing a token, Mapbox allows you to specify only the URLs you want your key to be accessible from.</p>
<p>Though Mapbox has a generous free tier, you probably want to keep it locked down only to the URLs that you’re using it on. You can create multiple keys, where one could be for public use on your website and one would be for your local development.</p>
<p>This is helpful for instance, where you have a key that will never be used publicly for development purposes, but then you have a key that you deploy with, which can be locked down only to that URL.</p>
<p>If someone grabs your key, they could plug it into their own website and use up all of your free tier, potentially running up your bill!</p>
<h2 id="heading-want-to-learn-more-about-maps">Want to learn more about maps?</h2>
<p>You can check out a few of my other resources to get started:</p>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App in React with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping">Anyone Can Map! Inspiration and an introduction to the world of mapping</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">How to Create your own Santa Tracker with Gatsby and React Leaflet</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a></li>
</ul>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="600" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Tips to Enhance the Performance of Your React App ]]>
                </title>
                <description>
                    <![CDATA[ By Shifa Martin ReactJS is an open-source framework that facilitates the development of UI interfaces for web and mobile applications. Developers globally use the framework to build state-of-the-art applications which subsequently generate revenues a... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/tips-to-enhance-the-performance-of-your-react-app/</link>
                <guid isPermaLink="false">66d460fa4a0edd9b48e83589</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React context ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react testing library ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Reactive Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 27 Aug 2019 13:46:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/08/react.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Shifa Martin</p>
<p>ReactJS is an open-source framework that facilitates the development of UI interfaces for web and mobile applications. Developers globally use the framework to build state-of-the-art applications which subsequently generate revenues as well as expand the audience for businesses.  </p>
<p>However, building a great UI with React isn’t enough, You’ve got to add that extra glitter to make the app more polished, functional and remarkably better than the competition. </p>
<p>This is exactly what I’m going to help you with as I describe some key methods to increase performance in React apps.</p>
<h3 id="heading-1-making-good-use-of-identities">1. Making good use of Identities</h3>
<p>When building mobile apps with React,  it is possible to wrap functions and variables with React.useMemo. Doing so provides the ability to memoize them so they remain identical for renders in the future.  </p>
<p>When functions and variables are not memoized, any references to them might vanish from future renders. Memoizing helps in negating wasteful processes and operations in every situation where you’d leverage functions and variables.</p>
<p><em><strong>Example:</strong></em> </p>
<p>Say, we’re preparing a custom hook for a list of urls as arguments. Using the hook, we can collect them into an array of promise objects and resolve them with Promise.all. The results of this accumulation will enter the state and be passed the app component once done. The list of promises now map over the urls array from where it fetches the urls.</p>
<pre><code class="lang-react">import React from 'react'
import axios from 'axios'

export const useApp = ({ urls }) =&gt; {
  const [results, setResults] = React.useState(null)

  const promises = urls.map(axios.get)

  React.useEffect(() =&gt; {
    Promise.all(promises).then(setResults)
  }, [])

  return { results }
}

const App = () =&gt; {
  const urls = [
    'https://clinicaltables.nlm.nih.gov/api/icd10cm/v3/search?terms=a',
    'https://clinicaltables.nlm.nih.gov/api/icd10cm/v3/search?terms=b',
    'https://clinicaltables.nlm.nih.gov/api/icd10cm/v3/search?terms=c',
  ]

  useApp({ urls })

  return null
}

export default App
</code></pre>
<p>Since we want to obtain data from 3 urls here, only 3 requests are supposed to be sent out, one for each url. However,  when looking at it through the inspect element feature on Google Chrome, we find that 6 requests are sent instead of the supposed 3.<br>This happens because the urls argument did not retain its previous identity. When the app is re-rendered, it’s instantiating a new array each time, as React treats it as a different value.  </p>
<p><img src="https://lh5.googleusercontent.com/XE6rCdOL110eYARSgVTgcwiecF2qNAT96yBYn_-FbQ2_ffjdRAplLqRxu4eQh-NniyF0doEPRtsT3X0lYxeHcSu35UN0giiteCsIJTrVP9tw1mITk5-P5hH3PmdWd2ss5R0E2pb3" alt="Image" width="600" height="400" loading="lazy"></p>
<p>To fix this problem, we can use React.useMemo as previously mentioned. When using React.useMemo, the array of promise objects won’t recompute in each new render unless the array with the list of urls changes. As long as it stays the same, the identities remain.</p>
<p><strong>Here’s what happens when applying React.useMemo to this example:</strong></p>
<pre><code class="lang-react">const useApp = ({ urls }) =&gt; {
  const [results, setResults] = React.useState(null)

  const promises = urls.map((url) =&gt; axios.get(url))

  React.useEffect(() =&gt; {
    Promise.all(promises).then(setResults)
  }, [])

  return { results }
}

const App = () =&gt; {
  const urls = React.useMemo(() =&gt; {
    return [
      'https://clinicaltables.nlm.nih.gov/api/icd10cm/v3/search?terms=a',
      'https://clinicaltables.nlm.nih.gov/api/icd10cm/v3/search?terms=b',
    ]
  }, [])

  const { results } = useApp({ urls })

  return null
}
</code></pre>
<p>It will send 6 requests even now since we’ve only memoized the urls array. The promises variables are also instantiating when running the hook. So in order to send only 3  requests, we also have to memorize the promises variables as well.</p>
<pre><code class="lang-react">const promises = React.useMemo(() =&gt; {
  return urls.map((url) =&gt; axios.get(url))
}, [urls])
</code></pre>
<blockquote>
<p>After memoizing both the urls array and the promises variables, this is what we get: </p>
</blockquote>
<p><img src="https://lh4.googleusercontent.com/P-8qvsq_Nu229Eod2_FIlqLtY1_lAxkPXZfw3a9D7P25VIyGrw--kTnOuTF4rmXPsA3vxGRifwprsI_VGGDU9pFIafOAsfPKiQE3L3Zv1MHXzPH25e2g39MaCikn2AActzgJlftr" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-2-merging-props-to-children">2. Merging Props to Children</h3>
<p>At times, developers get into situations where they prefer merging a prop with children before rendering. To facilitate the same, React allows viewing the props to all react elements including others, and also allows exposing their key.</p>
<p>So developers can choose to wrap the children element with a newer one, and insert new props there or they can simply merge the props with React.</p>
<p>Say, we have an app component that uses a useModal and offers the ability to manage modals by using controls such as open, close, opened and activated. Before merging props to children, we can pass them to a VisbilityControl component which provides some additional functionality.</p>
<pre><code class="lang-react">import React from 'react'

const UserContext = React.createContext({
  user: {
    firstName: 'Kelly',
    email: 'frogLover123@gmail.com',
  },
  activated: true,
})

const VisibilityControl = ({ children, opened, close }) =&gt; {
  const ctx = React.useContext(UserContext)
  return React.cloneElement(children, {
    opened: ctx.activated ? opened : false,
    onClick: close,
  })
}

export const useModal = ({ urls } = {}) =&gt; {
  const [opened, setOpened] = React.useState(false)
  const open = () =&gt; setOpened(true)
  const close = () =&gt; setOpened(false)

  return {
    opened,
    open,
    close,
  }
}

const App = ({ children }) =&gt; {
  const modal = useModal()

  return (
    &lt;div&gt;
      &lt;button type="button" onClick={modal.opened ? modal.close : modal.open}&gt;
        {modal.opened ? 'Close' : 'Open'} the Modal
      &lt;/button&gt;
      &lt;VisibilityControl {...modal}&gt;{children}&lt;/VisibilityControl&gt;
    &lt;/div&gt;
  )
}

const Window = ({ opened }) =&gt; {
  if (!opened) return null
  return (
    &lt;div style={{ border: '1px solid teal', padding: 12 }}&gt;
      &lt;h2&gt;I am a window&lt;/h2&gt;
    &lt;/div&gt;
  )
}

export default () =&gt; (
  &lt;App&gt;
    &lt;Window /&gt;
  &lt;/App&gt;
)
</code></pre>
<p>Using Visibility control allows developers to ascertain whether the control activated is true before allowing the control opened to be used by children. In case the Visibility Control feature is used via a secret route, there’s an option to prevent unactivated users from accessing the content.  </p>
<h3 id="heading-3-making-a-larger-reducer">3. Making a larger reducer</h3>
<p>It is possible to combine to or more reducer to make a single, much larger reducer that can help boost a react app.</p>
<p>Say, you think of building a large app that provides access to a wide variety of small services. How would you go about the development of such an app? </p>
<p><strong>There are two options:</strong></p>
<ol>
<li>We can give each microservice within the app a separate part of its own from where its state and context can be managed directly.  </li>
</ol>
<ol start="2">
<li>Or we can combine all states into a single large state and manage all of them within the same environment.  </li>
</ol>
<blockquote>
<p>The first approach seems to highly tedious, so obviously, the second one is the way to go.  </p>
</blockquote>
<p><strong>Now we have three reducers to combine -</strong> </p>
<p>frogsreducer.js, authreducer.js and finally, ownersreducer.js.  </p>
<p><strong>Let's start with authReducer.js</strong></p>
<pre><code class="lang-react">const authReducer = (state, action) =&gt; {
  switch (action.type) {
    case 'set-authenticated':
      return { ...state, authenticated: action.authenticated }
    default:
      return state
  }
}

export default authReducer

ownersReducer.js
</code></pre>
<p><strong>ownersReducer.js</strong></p>
<pre><code class="lang-react">const ownersReducer = (state, action) =&gt; {
  switch (action.type) {
    case 'add-owner':
      return {
        ...state,
        profiles: [...state.profiles, action.owner],
      }
    case 'add-owner-id':
      return { ...state, ids: [...state.ids, action.id] }
    default:
      return state
  }
}

export default ownersReducer
</code></pre>
<p><strong>frogsReducer.js</strong></p>
<pre><code class="lang-react">const frogsReducer = (state, action) =&gt; {
  switch (action.type) {
    case 'add-frog':
      return {
        ...state,
        profiles: [...state.profiles, action.frog],
      }
    case 'add-frog-id':
      return { ...state, ids: [...state.ids, action.id] }
    default:
      return state
  }
}

export default frogsReducer
</code></pre>
<blockquote>
<p>Now we can put all three into the main app file and define their state:  </p>
</blockquote>
<p><strong>App.js</strong></p>
<pre><code class="lang-react">import React from 'react'
import authReducer from './authReducer'
import ownersReducer from './ownersReducer'
import frogsReducer from './frogsReducer'

const initialState = {
  auth: {
    authenticated: false,
  },
  owners: {
    profiles: [],
    ids: [],
  },
  frogs: {
    profiles: [],
    ids: [],
  },
}

function rootReducer(state, action) {
  return {
    auth: authReducer(state.auth, action),
    owners: ownersReducer(state.owners, action),
    frogs: frogsReducer(state.frogs, action),
  }
}

const useApp = () =&gt; {
  const [state, dispatch] = React.useReducer(rootReducer, initialState)

  const addFrog = (frog) =&gt; {
    dispatch({ type: 'add-frog', frog })
    dispatch({ type: 'add-frog-id', id: frog.id })
  }

  const addOwner = (owner) =&gt; {
    dispatch({ type: 'add-owner', owner })
    dispatch({ type: 'add-owner-id', id: owner.id })
  }

  React.useEffect(() =&gt; {
    console.log(state)
  }, [state])

  return {
    ...state,
    addFrog,
    addOwner,
  }
}

const App = () =&gt; {
  const { addFrog, addOwner } = useApp()

  const onAddFrog = () =&gt; {
    addFrog({
      name: 'giant_frog123',
      id: 'jakn39eaz01',
    })
  }

  const onAddOwner = () =&gt; {
    addOwner({
      name: 'bob_the_frog_lover',
      id: 'oaopskd2103z',
    })
  }

  return (
    &lt;&gt;
      &lt;div&gt;
        &lt;button type="button" onClick={onAddFrog}&gt;
          add frog
        &lt;/button&gt;
        &lt;button type="button" onClick={onAddOwner}&gt;
          add owner
        &lt;/button&gt;
      &lt;/div&gt;
    &lt;/&gt;
  )
}
export default () =&gt; &lt;App /&gt;

This is what it looks like combining all three reducers into one large reducer, along with rootReducer

function rootReducer(state, action) {
  return {
    auth: authReducer(state.auth, action),
    owners: ownersReducer(state.owners, action),
    frogs: frogsReducer(state.frogs, action),
  }
</code></pre>
<p>This is what it looks like combining all three reducers into one large reducer, along with rootReducer.</p>
<h3 id="heading-using-sentry-for-analyzing-errors">Using Sentry for Analyzing Errors</h3>
<p><img src="https://lh5.googleusercontent.com/ySh7MjcCdU2XUVc1GASq8HBz0ym9Yn3mQt8xP0fygcYWqf-UoSkOAV1gOxUSgOQ3o79FJb7R3P9iwIYngWY8MtNB6uAqHBh-UXY5gf_G-C9kN_Nuxx73iYllkPSqKKOSjDTXWvmb" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Any mobile app development project can benefit greatly from <a target="_blank" href="https://sentry.io/welcome/">Sentry.</a> It provides everything a developer needs to handle errors and exceptions when building apps with React. Sentry identifies all errors and displays them at one central location so they can be accessed and analyzed all at once.</p>
<p>Getting started with Sentry on React is easy. Just use npm install @sentry/browser and set it up. Once done, developers can log in at sentry.io and analyze all error reports of a project on a single dashboard.</p>
<p>The error reports from sentry are incredibly detailed. They provide all sorts of important information which include the user’s device information, browser, URL, stack trace, how the error was handled, source code, IP address, breadcrumbs to trace the source of error, the error function name and much more.  </p>
<h3 id="heading-5-using-axios-for-http-requests">5. Using Axios for HTTP requests</h3>
<p>Though <a target="_blank" href="https://github.com/axios/axios">Axios</a> is commonly used for HTTP requests. I felt it is important to mention this point because it's actually not common for developers to use other request libraries such as fetch for React apps.  </p>
<p>Windows.fetch provides no support for Internet Explorer 11 (most don’t really care though). But for what it's worth, Axios does work there as well and offers the ability to cancel requests in mid-flight.  </p>
<h3 id="heading-final-words">Final Words</h3>
<p>The 5 mentioned methods can greatly help speed up your React app. It helps developers, the business you’re in and of course, those who’d be using it eventually. But honestly, the success of your React App mostly depends on those who work on them. </p>
<p>As a consumer, you’d want better performance from your app, so it is what denotes success. As a developer, these methods could make your app easier to develop, and efficiency is key to being more productive. </p>
<p><strong>ValueCoders is an expert <a target="_blank" href="https://www.valuecoders.com/">IT outsourcing company</a> for software development. If you are looking for offshore React programmers or <a target="_blank" href="https://www.valuecoders.com/hire-developers/hire-android-developers">hire Android developers</a>, feel free to get in touch.</strong> </p>
<p>Also, I hope this post helps you learn new things and get a deeper insight into what goes into making the perfect react application. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Create React App Crash Course ]]>
                </title>
                <description>
                    <![CDATA[ Create React App is a tool that saves you a bunch of time when building React apps. It makes creating React apps easier for beginners and experienced developers by automating time-consuming setup and configuration. You simply run one command and Crea... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-react-app-crash-course/</link>
                <guid isPermaLink="false">66b201dda2135cc2539a2164</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Mon, 28 Jan 2019 20:35:38 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/ghost/2019/01/create-react-app.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Create React App is a tool that saves you a bunch of time when building React apps. It makes creating React apps easier for beginners and experienced developers by automating time-consuming setup and configuration. You simply run one command and Create React App sets up the tools you need to start your React project.</p>
<p>In this crash course from Ipenywis, you will learn everything you need to know to begin using Create React App for your own React projects.</p>
<p>You can watch the tutorial on the <a target="_blank" href="https://www.youtube.com/watch?v=999E9t4v9So">freeCodeCamp.org YouTube channel</a> (22 minute watch).‌</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How To Make create-react-app work with a Node Back-end API ]]>
                </title>
                <description>
                    <![CDATA[ By Esau Silva This is a very common question among newer React developers, and one question I had when I was starting out with React and Node.js. In this short example I will show you how to make create-react-app work with Node.js and Express Back-en... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-make-create-react-app-work-with-a-node-backend-api-7c5c48acb1b0/</link>
                <guid isPermaLink="false">66d45e3e3a8352b6c5a2aa30</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Express.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 21 Dec 2017 00:17:25 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*eo3-wlU7ny1XYqPk4i2Blw.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Esau Silva</p>
<p>This is a very common question among newer React developers, and one question I had when I was starting out with React and Node.js. In this short example I will show you how to make <code>create-react-app</code> work with Node.js and Express Back-end.</p>
<h4 id="heading-create-react-app">create-react-app</h4>
<p>Create a project using <code>create-react-app</code>.</p>
<pre><code class="lang-bash">npx create-react-app example-create-react-app-express
</code></pre>
<p>Create a <code>/client</code> directory under <code>example-create-react-app-express</code> directory and move all the React boilerplate code created by <code>create-react-app</code> to this new client directory.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> example-create-react-app-expressmkdir client
</code></pre>
<h4 id="heading-the-node-express-server">The Node Express Server</h4>
<p>Create a <code>package.json</code> file inside the root directory (<code>example-create-react-app-express</code>) and copy the following contents:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"example-create-react-app-express"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"client"</span>: <span class="hljs-string">"cd client &amp;&amp; yarn start"</span>,
    <span class="hljs-attr">"server"</span>: <span class="hljs-string">"nodemon server.js"</span>,
    <span class="hljs-attr">"dev"</span>: <span class="hljs-string">"concurrently --kill-others-on-fail \"yarn server\" \"yarn client\""</span>
  },
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"body-parser"</span>: <span class="hljs-string">"^1.18.3"</span>,
    <span class="hljs-attr">"express"</span>: <span class="hljs-string">"^4.16.4"</span>
  },
  <span class="hljs-attr">"devDependencies"</span>: {
    <span class="hljs-attr">"concurrently"</span>: <span class="hljs-string">"^4.0.1"</span>
  }
}
</code></pre>
<p>Notice I am using <code>concurrently</code> to run the React app and Server at the same time. The <code>–kill-others-on-fail</code> flag will kill other processes if one exits with a non zero status code.</p>
<p>Install <code>nodemon</code> globally and the server dependencies:</p>
<pre><code class="lang-bash">npm i nodemon -g
yarn
</code></pre>
<p>Create a <code>server.js</code> file and copy the following contents:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> bodyParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">'body-parser'</span>);

<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">const</span> port = process.env.PORT || <span class="hljs-number">5000</span>;

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ <span class="hljs-attr">extended</span>: <span class="hljs-literal">true</span> }));

app.get(<span class="hljs-string">'/api/hello'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  res.send({ <span class="hljs-attr">express</span>: <span class="hljs-string">'Hello From Express'</span> });
});

app.post(<span class="hljs-string">'/api/world'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(req.body);
  res.send(
    <span class="hljs-string">`I received your POST request. This is what you sent me: <span class="hljs-subst">${req.body.post}</span>`</span>,
  );
});

app.listen(port, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening on port <span class="hljs-subst">${port}</span>`</span>));
</code></pre>
<p>This is a simple Express server that will run on port 5000 and have two API routes: <code>GET</code> - <code>/api/hello</code>, and <code>POST</code> -<code>/api/world</code>.</p>
<p>At this point you can run the Express server with the following command (still inside the root directory):</p>
<pre><code class="lang-bash">node server.js
</code></pre>
<p>Now navigate to <code>[http://localhost:5000/api/hello](http://localhost:5000/api/hello)</code>, and you will get the following:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/TPcEMDY475EhrLyGruM9uWQvM33ZKlDAl-cb" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We will test the <code>POST</code> route once we build the React app.</p>
<h4 id="heading-the-react-app">The React App</h4>
<p>Now switch over to the <code>client</code> directory where our React app lives.</p>
<p>Add the following line to the <code>package.json</code> file created by <code>create-react-app</code>.</p>
<pre><code class="lang-json"><span class="hljs-string">"proxy"</span>: <span class="hljs-string">"http://localhost:5000/"</span>
</code></pre>
<p>The key to using an Express back-end server with a project created with <code>create-react-app</code> is to use a proxy. This tells the Web-pack development server to proxy our API requests to our API server, given that our Express server is running on <code>localhost:5000</code>.</p>
<p>Now modify <code>./client/src/App.js</code> to call our Express API Back-end, changes are in bold.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">import</span> logo <span class="hljs-keyword">from</span> <span class="hljs-string">'./logo.svg'</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">App</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
  state = {
    <span class="hljs-attr">response</span>: <span class="hljs-string">''</span>,
    <span class="hljs-attr">post</span>: <span class="hljs-string">''</span>,
    <span class="hljs-attr">responseToPost</span>: <span class="hljs-string">''</span>,
  };

  componentDidMount() {
    <span class="hljs-built_in">this</span>.callApi()
      .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">response</span>: res.express }))
      .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(err));
  }

  callApi = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'/api/hello'</span>);
    <span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> response.json();
    <span class="hljs-keyword">if</span> (response.status !== <span class="hljs-number">200</span>) <span class="hljs-keyword">throw</span> <span class="hljs-built_in">Error</span>(body.message);

    <span class="hljs-keyword">return</span> body;
  };

  handleSubmit = <span class="hljs-keyword">async</span> e =&gt; {
    e.preventDefault();
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'/api/world'</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
      },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">post</span>: <span class="hljs-built_in">this</span>.state.post }),
    });
    <span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> response.text();

    <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">responseToPost</span>: body });
  };

render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-header"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{logo}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App-logo"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"logo"</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
            Edit <span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>src/App.js<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span> and save to reload.
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"App-link"</span>
            <span class="hljs-attr">href</span>=<span class="hljs-string">"https://reactjs.org"</span>
            <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
            <span class="hljs-attr">rel</span>=<span class="hljs-string">"noopener noreferrer"</span>
          &gt;</span>
            Learn React
          <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{this.state.response}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{this.handleSubmit}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Post to Server:<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{this.state.post}</span>
            <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> this.setState({ post: e.target.value })}
          /&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{this.state.responseToPost}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
  }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>We create <code>callApi</code> method to interact with our <code>GET</code> Express API route, then we call this method in <code>componentDidMount</code> and finally set the state to the API response, which will be <em>Hello From Express</em>.</p>
<p>Notice we didn’t use a fully qualified URL <code>[http://localhost:5000/api/hello](http://localhost:5000/api/hello)</code> to call our API, even though our React app runs on a different port (3000). This is because of the <code>**proxy**</code> line we added to the <code>package.json</code> file earlier.</p>
<p>We have a form with a single input. When submitted calls <code>handleSubmit</code>, which in turn calls our <code>POST</code> Express API route then saves the response to state and displays a message to the user: <em>I received your POST request. This is what you sent me: [message from input]</em>.</p>
<p>Now open <code>./client/src/App.css</code> and modify <code>.App-header</code> class as follows (changes in bold)</p>
<pre><code class="lang-js">.App-header {
...
  min-height: <span class="hljs-number">50</span>%;
...
  padding-bottom: <span class="hljs-number">10</span>px;
}
</code></pre>
<h3 id="heading-running-the-app">Running the App</h3>
<p><em>If you still have the server running, go ahead and stop it by pressing Ctrl+C in your terminal.</em></p>
<p>From the project root directory run the following:</p>
<pre><code class="lang-bash">yarn dev
</code></pre>
<p>This will launch the React app and run the server at the same time.</p>
<p>Now navigate to <code>[http://localhost:3000](http://localhost:3000)</code> and you will hit the React app displaying the message coming from our <code>GET</code> Express route. Nice ?!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/v3LAoDh50Yq4c60yOY69WpRwnZL2fRCIXfTs" alt="Image" width="600" height="400" loading="lazy">
<em>Displaying GET route</em></p>
<p>Now, type something in the input field and submit the form, you will see the response from the <code>POST</code> Express route displayed right below the input field.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/NcLZDJaVE0g833Xrn8jM2G8e5f4LVVygt10O" alt="Image" width="600" height="400" loading="lazy">
<em>Calling POST route</em></p>
<p>Finally take a look at at your terminal, you will see the message we sent from the client, that is because we call <code>console.log</code> on the request body in the <code>POST</code> Express route.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/r43BMtm-aiA84Nxrin1eTHXi4YnnEX3SYzMM" alt="Image" width="600" height="400" loading="lazy">
<em>Node</em></p>
<h3 id="heading-production-deployment-to-heroku">Production Deployment to Heroku</h3>
<p>Open <code>server.js</code> and replace with the following contents:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> bodyParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">'body-parser'</span>);
<span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>);

<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">const</span> port = process.env.PORT || <span class="hljs-number">5000</span>;

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ <span class="hljs-attr">extended</span>: <span class="hljs-literal">true</span> }));

<span class="hljs-comment">// API calls</span>
app.get(<span class="hljs-string">'/api/hello'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  res.send({ <span class="hljs-attr">express</span>: <span class="hljs-string">'Hello From Express'</span> });
});

app.post(<span class="hljs-string">'/api/world'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(req.body);
  res.send(
    <span class="hljs-string">`I received your POST request. This is what you sent me: <span class="hljs-subst">${req.body.post}</span>`</span>,
  );
});

<span class="hljs-keyword">if</span> (process.env.NODE_ENV === <span class="hljs-string">'production'</span>) {
  <span class="hljs-comment">// Serve any static files</span>
  app.use(express.static(path.join(__dirname, <span class="hljs-string">'client/build'</span>)));

  <span class="hljs-comment">// Handle React routing, return all requests to React app</span>
  app.get(<span class="hljs-string">'*'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>) </span>{
    res.sendFile(path.join(__dirname, <span class="hljs-string">'client/build'</span>, <span class="hljs-string">'index.html'</span>));
  });
}

app.listen(port, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening on port <span class="hljs-subst">${port}</span>`</span>));
</code></pre>
<p>Open <code>./package.json</code> and add the following to the <code>scripts</code> entry</p>
<pre><code class="lang-json"><span class="hljs-string">"start"</span>: <span class="hljs-string">"node server.js"</span>,
<span class="hljs-string">"heroku-postbuild"</span>: <span class="hljs-string">"cd client &amp;&amp; npm install &amp;&amp; npm install --only=dev --no-shrinkwrap &amp;&amp; npm run build"</span>
</code></pre>
<p>Heroku will run the <code>start</code> script by default and this will serve our app. Then we want to instruct Heroku to build our client app, we do so with <code>heroku-postbuild</code> script.</p>
<p>Now, head over to <a target="_blank" href="https://www.heroku.com/">Heroku</a> and log in (or open an account if you don’t have one).</p>
<p>Create a new app and give it a name</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/YSsjVCvWV0-uieTxyQG1TDLrDT4ZxjOTb4pP" alt="Image" width="600" height="400" loading="lazy">
<em>Create new app on Heroku</em></p>
<p>Click on the <strong><em>Deploy</em></strong> tab and follow the deploy instructions (which I think they are pretty self-explanatory, no point on replicating them here ?)</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/vFyFAdbumn-k-39zK9DFZLJ6oWS9vfflmH1N" alt="Image" width="600" height="400" loading="lazy">
<em>Deploy an app to Heroku</em></p>
<p>And that is it, you can open your app by clicking on the <strong><em>Open app</em></strong> button at the top right corner within the Heroku dashboard for your app.</p>
<p>Visit the deployed app for this tutorial: <a target="_blank" href="https://cra-express.herokuapp.com/">https://cra-express.herokuapp.com/</a></p>
<h4 id="heading-other-deployment-options">Other Deployment Options</h4>
<p>I write about other deployments options here:</p>
<ul>
<li><a target="_blank" href="https://blog.bitsrc.io/react-production-deployment-part-1-netlify-703686631dd1">Netlify</a></li>
<li><a target="_blank" href="https://blog.bitsrc.io/react-production-deployment-part-2-now-c81657c700b7">Now</a></li>
<li><a target="_blank" href="https://blog.bitsrc.io/react-production-deployment-part-3-heroku-316319744885">Heoku</a> (more in-depth explanation)</li>
</ul>
<h3 id="heading-project-structure">Project Structure</h3>
<p>This will be the final project structure.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/YSFfgasf0j6pDjUX5TgcGCW6b8m74M6DTnY9" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Get the full code on the <a target="_blank" href="https://github.com/esausilva/example-create-react-app-express">GitHub repository</a>.</p>
<p>Thank you for reading and I hope you enjoyed it. Any question, suggestions let me know in the comments below!</p>
<p>You can follow me on <a target="_blank" href="https://twitter.com/_esausilva">Twitter</a>, <a target="_blank" href="https://github.com/esausilva">GitHub</a>, <a target="_blank" href="https://medium.com/@_esausilva/latest">Medium</a>, <a target="_blank" href="https://www.linkedin.com/in/esausilva/">LinkedIn</a> or all of them.</p>
<p>This post was originally posted on my personal <a target="_blank" href="https://esausilva.com/2017/11/14/how-to-use-create-react-app-with-a-node-express-backend-api/">blog website</a>.</p>
<hr>
<p><strong>Update 8/25/19:</strong> I have been building a prayer web app called "<strong>My Quiet Time - A Prayer Journal</strong>". If you would like to stay in the loop please sign up through the following link: <a target="_blank" href="http://b.link/mqt">http://b.link/mqt</a>  </p>
<p>The app will be released before the end of the year, I have big plans for this app. To see some mockup screenshots follow the following link: <a target="_blank" href="http://pc.cd/Lpy7">http://pc.cd/Lpy7</a></p>
<p>My DMs on <a target="_blank" href="https://twitter.com/_esausilva">Twitter</a> are open if you have any questions regarding the app ?</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
