<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nabeel Valley</title>
    <description>The latest articles on DEV Community by Nabeel Valley (@nabeelvalley).</description>
    <link>https://dev.to/nabeelvalley</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F147973%2Fe16e78c5-f82a-4f64-8043-d3fe92575b9b.jpeg</url>
      <title>DEV Community: Nabeel Valley</title>
      <link>https://dev.to/nabeelvalley</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nabeelvalley"/>
    <language>en</language>
    <item>
      <title>Using React.memo for Controlling Component Rendering</title>
      <dc:creator>Nabeel Valley</dc:creator>
      <pubDate>Tue, 16 Aug 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/nabeelvalley/using-reactmemo-for-controlling-component-rendering-5h7m</link>
      <guid>https://dev.to/nabeelvalley/using-reactmemo-for-controlling-component-rendering-5h7m</guid>
      <description>

&lt;h1&gt;
  
  
  Contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;React Top Level API&lt;/li&gt;
&lt;li&gt;Component Rendering&lt;/li&gt;
&lt;li&gt;API Definition&lt;/li&gt;
&lt;li&gt;Rendering On a Specific Type of Change&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;li&gt;REPL&lt;/li&gt;
&lt;li&gt;References&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  React Top Level API
&lt;/h1&gt;

&lt;p&gt;The React library contains some functions at it's top level scope. Amongst these are the built-in hooks (like &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useCallback&lt;/code&gt;, etc.) as well as some other functions for manipulating React Elements directly - which I've covered in a previous post on &lt;a href="//../01-03/react-top-level-api.md"&gt;The React Top Level API&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Component Rendering
&lt;/h1&gt;

&lt;p&gt;By default, React will trigger a component render whenever there is a change to its &lt;code&gt;state&lt;/code&gt; or &lt;code&gt;props&lt;/code&gt;. &lt;code&gt;React.memo&lt;/code&gt; allows us to take control of the &lt;code&gt;props&lt;/code&gt; triggered render by giving us a way to look into the prop-change process&lt;/p&gt;

&lt;p&gt;&lt;code&gt;React.memo&lt;/code&gt; is a higher order component (HOC) that allows us to wrap a component and control whether or not it is updated/re-rendered by defining a function that tells react whether or not it's props are different - and effectively whether this should trigger a new render&lt;/p&gt;

&lt;p&gt;Doing the above is useful for complex components that don't necessarily need to be rendered every time their props are changed&lt;/p&gt;

&lt;h1&gt;
  
  
  API Definition
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://reactjs.org/docs/react-api.html#reactmemo"&gt;The React Docs&lt;/a&gt; give us the following example for the &lt;code&gt;React.memo&lt;/code&gt; HOC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const MyComponent = (props) =&amp;gt; {
  /* render using props */
}

const areEqual = (prevProps, nextProps) =&amp;gt; {
  /*
  return true if passing nextProps to render would return
  the same result as passing prevProps to render,
  otherwise return false
  */
}

const MyComponentMemo = React.memo(MyComponent, areEqual);

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

&lt;/div&gt;



&lt;p&gt;The component &lt;code&gt;MyComponent&lt;/code&gt; will be rendered whenever props are changed, however, using &lt;code&gt;React.memo&lt;/code&gt; lets us define a function called &lt;code&gt;areEqual&lt;/code&gt; that we can can use to tell &lt;code&gt;React.memo&lt;/code&gt; whether or not the new props would render a different result to the old props&lt;/p&gt;

&lt;p&gt;We can then use &lt;code&gt;MyComponentMemo&lt;/code&gt; in place of &lt;code&gt;MyComponent&lt;/code&gt; to take control of when the component is rendered&lt;/p&gt;

&lt;h1&gt;
  
  
  Rendering On a Specific Type of Change
&lt;/h1&gt;

&lt;p&gt;Say we have the specific component &lt;code&gt;TimeDisplay&lt;/code&gt; which shows the time that's being passed into it from &lt;code&gt;App&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

interface TimeDisplayProps {
  time: number
}

const TimeDisplay: React.FC&amp;lt;TimeDisplayProps&amp;gt; = ({ time }) =&amp;gt; {
  const display = new Date(time).toString()

  return &amp;lt;h1&amp;gt;{display}&amp;lt;/h1&amp;gt;
}

export default function App() {
  const [time, setTime] = useState(Date.now())

  useEffect(() =&amp;gt; {
    const handle = setInterval(() =&amp;gt; {
      setTime(Date.now())
    }, 100)

    return () =&amp;gt; {
      clearInterval(handle)
    }
  }, [])

  return (
    &amp;lt;main&amp;gt;
      &amp;lt;TimeDisplay time={time} /&amp;gt;
    &amp;lt;/main&amp;gt;
  )
}

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;TimeDisplay&lt;/code&gt; component in our case only displays time to the second, so any millisecond-level changes don't matter to the component and so we can save on those renders by checking if the difference in &lt;code&gt;time&lt;/code&gt; is similar to the previous render's &lt;code&gt;time&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let's assume for our purpose that it's acceptable for the time to be delayed by about 5 seconds, we then can define a function called &lt;code&gt;areTimesWithinOneSecond&lt;/code&gt; which compares the next render's props with the previous and returns if they are within 5 seconds of each other:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const areTimesWithinFiveSeconds = (prev: TimeDisplayProps, next: TimeDisplayProps): boolean =&amp;gt; {
  const diff = next.time - prev.time

  return diff &amp;lt; 5000
}

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

&lt;/div&gt;



&lt;p&gt;We can use the above function in a &lt;code&gt;React.memo&lt;/code&gt; to define a version of the &lt;code&gt;TimeDisplay&lt;/code&gt; component which will prevent unnecessary renders:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const TimeDisplayMemo = React.memo(TimeDisplay, areTimesWithinFiveSeconds)

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

&lt;/div&gt;



&lt;p&gt;And it can then be used as a drop-in replacement for the &lt;code&gt;TimeDisplay&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
export default function App() {
  const [time, setTime] = useState(Date.now())

  useEffect(() =&amp;gt; {
    const handle = setInterval(() =&amp;gt; {
      setTime(Date.now())
    }, 100)

    return () =&amp;gt; {
      clearInterval(handle)
    }
  }, [])

  return (
    &amp;lt;main&amp;gt;
      &amp;lt;TimeDisplayMemo time={time} /&amp;gt;
    &amp;lt;/main&amp;gt;
  )
}

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;From the above implementation we can see that it's possible to delay rendering of a component using &lt;code&gt;React.memo&lt;/code&gt; if the component doesn't need to be re-rendered, hence improving performance by decreasing the number of renders react needs to carry out&lt;/p&gt;

&lt;h1&gt;
  
  
  REPL
&lt;/h1&gt;

&lt;p&gt;The REPL with the example above can seen below:&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/react-api.html#reactmemo"&gt;The React Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>stdout: Type Guards and Narrowing in Typescript</title>
      <dc:creator>Nabeel Valley</dc:creator>
      <pubDate>Tue, 31 May 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/nabeelvalley/stdout-type-guards-and-narrowing-in-typescript-3dcf</link>
      <guid>https://dev.to/nabeelvalley/stdout-type-guards-and-narrowing-in-typescript-3dcf</guid>
      <description>&lt;p&gt;Type guards (also known as Narrowing) allow us create conditions under which an object of one type can be used as if it is of another type. We usually use this in conjunction with union types to allow us to specify different handling of the types based on the resulting value&lt;/p&gt;

&lt;h1&gt;
  
  
  Contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Using typeof&lt;/li&gt;
&lt;li&gt;Using in&lt;/li&gt;
&lt;li&gt;Using is&lt;/li&gt;
&lt;li&gt;References&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;typeof&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;We can use the &lt;code&gt;typeof&lt;/code&gt; keyword in javascript to find out what type an object is. This is useful if we have an object that can take on different structures, for example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GetData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In the above example, we have a type called &lt;code&gt;GetData&lt;/code&gt; which can be either some data or a function to get data. Using this, we can can create a function which fetches data like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetData&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;getData&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;getData&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using &lt;code&gt;in&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Javascript also has the &lt;code&gt;in&lt;/code&gt; operator which can be used to infer types by us checking a property of an object&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SimpleData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ComplexData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nl"&gt;isComplex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AnyData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SimpleData&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;ComplexData&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then use the &lt;code&gt;in&lt;/code&gt; operator to check the existence of a property of an object by using it along with a key that we expect to be in one object but not another&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getComplexName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnyData&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// isComplex is the name of the key that we expect in `ComplexData` but not `SimpleData`&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isComplex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using &lt;code&gt;is&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;We can use the typescript &lt;code&gt;is&lt;/code&gt; keyword to specify that the return of a boolean means that a variable satisfies a specific condition&lt;/p&gt;

&lt;p&gt;For example, we can create a function that basically does what the &lt;code&gt;in&lt;/code&gt; operator in the above function does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isComplex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnyData&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;ComplexData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ComplexData&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;isComplex&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This can be used in place of the &lt;code&gt;in&lt;/code&gt; check in the above example like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getComplexName2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnyData&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// isComplex is the name of the key that we expect in `ComplexData` but not `SimpleData`&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isComplex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="//../../../docs/javascript/typescript-basics"&gt;My TS Notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in"&gt;MDN The &lt;code&gt;in&lt;/code&gt; operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof"&gt;MDN The &lt;code&gt;typeof&lt;/code&gt; operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html"&gt;TS Docs on Narrowing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
      <category>functions</category>
    </item>
    <item>
      <title>stdout: Localhost HTTP Proxy with Node.js</title>
      <dc:creator>Nabeel Valley</dc:creator>
      <pubDate>Tue, 08 Mar 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/nabeelvalley/stdout-localhost-http-proxy-with-nodejs-1hlf</link>
      <guid>https://dev.to/nabeelvalley/stdout-localhost-http-proxy-with-nodejs-1hlf</guid>
      <description>&lt;h1&gt;
  
  
  Contents
&lt;/h1&gt;

&lt;p&gt;A localhost HTTP proxy is useful for debugging and can be easily defined using Node.js by installing &lt;code&gt;http-proxy&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add http-proxy

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

&lt;/div&gt;



&lt;p&gt;And then adding the following to an &lt;code&gt;index.js&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const httpProxy = require('http-proxy')

const target = 'http://my-target-website.com:1234'

httpProxy.createProxyServer({ target }).listen(8080)

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

&lt;/div&gt;



&lt;p&gt;Which will create a server that listens on &lt;code&gt;8080&lt;/code&gt; and will proxy requests to the target&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>http</category>
      <category>proxy</category>
    </item>
    <item>
      <title>Build Data Visualizations with React</title>
      <dc:creator>Nabeel Valley</dc:creator>
      <pubDate>Fri, 11 Feb 2022 15:40:53 +0000</pubDate>
      <link>https://dev.to/nabeelvalley/build-data-visualizations-with-react-35al</link>
      <guid>https://dev.to/nabeelvalley/build-data-visualizations-with-react-35al</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;If you want to take a look at the full code alongside the resulting SVG then head on over to &lt;a href="https://nabeelvalley.co.za/blog/2022/11-02/d3-with-react"&gt;my website&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;React is a library for building reactive user interfaces using JavaScript (or Typescript) and D3 (short for &lt;em&gt;Data-Driven Documents&lt;/em&gt;) is a set of libraries for working with visualizations based on data&lt;/p&gt;

&lt;p&gt;Before getting started, I would recommend familiarity with SVG, React, and D3&lt;/p&gt;

&lt;p&gt;Some good references for SVG are on the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial"&gt;MDN SVG Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A good place to start for React would be the &lt;a href="https://reactjs.org/"&gt;React Docs&lt;/a&gt; or &lt;a href="///docs/react/complete-react.md"&gt;my React Notes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And lastly, the &lt;a href="https://github.com/d3/d3/wiki"&gt;D3 Docs&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Stared
&lt;/h2&gt;

&lt;p&gt;To follow along, you will need to install &lt;a href="https://nodejs.org/en/"&gt;Node.js&lt;/a&gt; and be comfortable using the terminal&lt;/p&gt;

&lt;p&gt;I'm going to be using a React App with TypeScript initialized with Vite as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn create vite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then selecting the &lt;code&gt;react-ts&lt;/code&gt; option when prompted. Next, install &lt;code&gt;d3&lt;/code&gt; from the project root with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add d3
yarn add &lt;span class="nt"&gt;--dev&lt;/span&gt; @types/d3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we've got a basic project setup, we can start talking about D3&lt;/p&gt;

&lt;h2&gt;
  
  
  Scales (&lt;code&gt;d3-scale&lt;/code&gt;)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/d3/d3-scale"&gt;&lt;code&gt;d3-scale&lt;/code&gt; Documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Broadly, scales allow us to map from one set of values to another set of values,&lt;/p&gt;

&lt;p&gt;Scales in D3 are a set of tools which map a dimension of data to a visual variable. They help us go from something like &lt;code&gt;count&lt;/code&gt; in our data to something like &lt;code&gt;width&lt;/code&gt; in our rendered SVG&lt;/p&gt;

&lt;p&gt;We can create scales for a sample dataset like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Datum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Datum&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🍊&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🍇&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🍏&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🍌&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🍐&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🍋&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🍎&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🍉&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Also, a common thing to do when working with scales is to define margins around out image, this is done simply as an object like so:&lt;/p&gt;


&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This just helps us simplify some position/layout things down the line&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Scales work by taking a value from the &lt;code&gt;domain&lt;/code&gt; (data space) and returning a value from &lt;code&gt;range&lt;/code&gt; (visual space):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleLinear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;    &lt;span class="c1"&gt;// values of the data space&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;// values of the visual space&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// position = scale(value)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, there's also the &lt;code&gt;invert&lt;/code&gt; method which goes the other way - from &lt;code&gt;range&lt;/code&gt; to &lt;code&gt;domain&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;// position === 30&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// value === 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;invert&lt;/code&gt; method is useful for things like calculating a &lt;code&gt;value&lt;/code&gt; from a mouse &lt;code&gt;position&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;D3 has different Scale types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Continuous (Linear, Power, Log, Identity, Time, Radial)&lt;/li&gt;
&lt;li&gt;Sequential&lt;/li&gt;
&lt;li&gt;Diverging&lt;/li&gt;
&lt;li&gt;Quantize&lt;/li&gt;
&lt;li&gt;Quantile&lt;/li&gt;
&lt;li&gt;Threshold&lt;/li&gt;
&lt;li&gt;Ordinal (Band, Point)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Continuous Scales
&lt;/h3&gt;

&lt;p&gt;These scales map continuous data to other continuous data&lt;/p&gt;

&lt;p&gt;D3 has a few different continuous scale types: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Linear&lt;/li&gt;
&lt;li&gt;Power&lt;/li&gt;
&lt;li&gt;Log&lt;/li&gt;
&lt;li&gt;Identity&lt;/li&gt;
&lt;li&gt;Radial&lt;/li&gt;
&lt;li&gt;Time&lt;/li&gt;
&lt;li&gt;Sequential Color&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For my purposes at the moment I'm going to be looking at the methods for Linear and Sequential Color scales, but the documentation explains all of the above very thoroughly and is worth a read for additional information on their usage&lt;/p&gt;

&lt;h4&gt;
  
  
  Linear
&lt;/h4&gt;

&lt;p&gt;We can use a &lt;code&gt;linear&lt;/code&gt; scale in the fruit example for mapping count to an x width:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleLinear&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxX&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we don't want the custom &lt;code&gt;domain&lt;/code&gt; to &lt;code&gt;range&lt;/code&gt; interpolation we can create a custom &lt;code&gt;interpolator&lt;/code&gt;. An &lt;code&gt;interpolator&lt;/code&gt; is a function that takes a value from the &lt;code&gt;domain&lt;/code&gt; and returns the resulting &lt;code&gt;range&lt;/code&gt; value&lt;/p&gt;

&lt;p&gt;D3 has a few different &lt;code&gt;interpolators&lt;/code&gt; included for tasks such as interpolating colors or rounding values&lt;/p&gt;

&lt;p&gt;We can create a custom color domain to interpolate over and use the &lt;code&gt;interpolateHsl&lt;/code&gt; or &lt;code&gt;interpolateRgb&lt;/code&gt; functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleLinear&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxX&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pink&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lightgreen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolateHsl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sequential Color
&lt;/h3&gt;

&lt;p&gt;If for some reason we want to use the pre-included color scales&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;scaleSequential&lt;/code&gt; scale is a method that allows us to map to a &lt;code&gt;color&lt;/code&gt; range using an &lt;code&gt;interpolator&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;D3 has a few different interpolators we can use with this function like &lt;code&gt;d3.interpolatePurples&lt;/code&gt;, &lt;code&gt;d3.interpolateRainbow&lt;/code&gt; or &lt;code&gt;d3.interpolateCool&lt;/code&gt; among others which look quite nice&lt;/p&gt;

&lt;p&gt;We can create a color scale using the &lt;code&gt;d3.interpolatePurples&lt;/code&gt; which will map the data to a scale of purples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleSequential&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxX&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolatePurples&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These can be used instead of the &lt;code&gt;scaleLinear&lt;/code&gt; with &lt;code&gt;interpolateHsl&lt;/code&gt; for example above but to provide a pre-calibrated color scale&lt;/p&gt;

&lt;h3&gt;
  
  
  Ordinal Scales
&lt;/h3&gt;

&lt;p&gt;Ordinal scales have a discrete domain and range and are used for the mapping of discrete data. These are a good fit for mapping a scale with categorical data. D3 offers us the following scales:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Band Scale&lt;/li&gt;
&lt;li&gt;Point Scale&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Band Scale
&lt;/h4&gt;

&lt;p&gt;A Band Scale is a type of Ordinal Scale where the output &lt;code&gt;range&lt;/code&gt; is continuous and numeric&lt;/p&gt;

&lt;p&gt;We can create a mapping for where each of our labels should be positioned with &lt;code&gt;scaleBand&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleBand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The domain can be any size array, unlike in the case of continuous scales where the are usually start and end values&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Building a Bar Graph
&lt;/h2&gt;

&lt;p&gt;When creating visuals with D3 there are a few different ways we can output to SVG data. D3 provides us with some methods for creating shapes and elements programmatically via a builder pattern - similar to how we create scales. &lt;/p&gt;

&lt;p&gt;However, there are also cases where we would want to define out SVG elements manually, such as when working with React so that the react renderer can handle the rendering of the SVG elements and we can manage our DOM structure in a way that's a bit more representative of the way we work in React&lt;/p&gt;

&lt;h3&gt;
  
  
  The SVG Root
&lt;/h3&gt;

&lt;p&gt;Every SVG image has to have an &lt;code&gt;svg&lt;/code&gt; root element. To help ensure that this root scales correctly we also use it with a &lt;code&gt;viewBox&lt;/code&gt; attribute which specifies which portion of the SVG is visible since the contents can go outside of the bounds of the View Box and we may not want to display this overflow content by default&lt;/p&gt;

&lt;p&gt;Using the definitions for &lt;code&gt;margin&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; from before we can get the &lt;code&gt;viewBox&lt;/code&gt; for the SVG we're trying to render like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;viewBox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`0 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then, using that value in the &lt;code&gt;svg&lt;/code&gt; element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* we will render the graph in here */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point we don't really have anything in the SVG, next up we'll do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add Bars to the SVG&lt;/li&gt;
&lt;li&gt;Add Y Labels to the SVG&lt;/li&gt;
&lt;li&gt;Add X Labels to the SVG&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Bars
&lt;/h3&gt;

&lt;p&gt;We can create Bars using the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rect&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bandwidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We make use of the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; functions which help us get the positions for the &lt;code&gt;rect&lt;/code&gt; as well as &lt;code&gt;y.bandWidth()&lt;/code&gt; and &lt;code&gt;x(d.count)&lt;/code&gt; to &lt;code&gt;height&lt;/code&gt; and &lt;code&gt;width&lt;/code&gt; for the element&lt;/p&gt;

&lt;p&gt;We can then add that into the SVG using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;bars&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Y Labels
&lt;/h3&gt;

&lt;p&gt;Next, using similar concepts as above, we can add the Y Labels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yLabels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0.35em"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we can add this into the SVG, and also wrapping the element in a &lt;code&gt;g&lt;/code&gt; with a some basic text alignment and translation for positioning it correctly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;
      &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"steelblue"&lt;/span&gt;
      &lt;span class="na"&gt;textAnchor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"end"&lt;/span&gt;
      &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`translate(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bandwidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;yLabels&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;bars&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  X Labels
&lt;/h3&gt;

&lt;p&gt;Next, we can add the X Labels over each &lt;code&gt;rect&lt;/code&gt; using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xLabels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0.35em"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the resulting code looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;
      &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"steelblue"&lt;/span&gt;
      &lt;span class="na"&gt;textAnchor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"end"&lt;/span&gt;
      &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`translate(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bandwidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;yLabels&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;bars&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;
      &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt;
      &lt;span class="na"&gt;textAnchor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"end"&lt;/span&gt;
      &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`translate(-6, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bandwidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;xLabels&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Final Result
&lt;/h3&gt;

&lt;p&gt;The code for the entire file/graph can be seen below:&lt;/p&gt;

&lt;p&gt;Fruit.tsx&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;d3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../data/fruit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleLinear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxX&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolateRound&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleBand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleSequential&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxX&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolateCool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Fruit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({})&lt;/span&gt; &lt;span class="o"&gt;=&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;viewBox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`0 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yLabels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;

  &lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xLabels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;


        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;yLabels&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;bars&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;xLabels&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Ticks and Grid Lines
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that D3 includes a &lt;code&gt;d3-axis&lt;/code&gt; package but that doesn't quite work given that we're manually creating the SVG using React and not D3&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We may want to add Ticks and Grid Lines on the X-Axis, we can do this using the scale's &lt;code&gt;ticks&lt;/code&gt; method like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xGrid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ticks&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;line&lt;/span&gt;
      &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lightgrey"&lt;/span&gt;
      &lt;span class="na"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;y1&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;y2&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt; &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"darkgrey"&lt;/span&gt; &lt;span class="na"&gt;textAnchor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"middle"&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then render this in the &lt;code&gt;svg&lt;/code&gt; as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;xGrid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* previous graph content */&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Building a Line Graph
&lt;/h2&gt;

&lt;p&gt;We can apply all the same as in the Bar Graph before to draw a Line Graph. The example I'll be using consists of a &lt;code&gt;Datum&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Datum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Given that the X-Axis is a &lt;code&gt;DateTime&lt;/code&gt; we will need to do some additional conversions as well as formatting&lt;/p&gt;

&lt;h3&gt;
  
  
  Working with Domains
&lt;/h3&gt;

&lt;p&gt;In the context of this graph it would also be useful to have an automatically calculated domain instead of a hardcoded one as in the previous example&lt;/p&gt;

&lt;p&gt;We can use the &lt;code&gt;d3.extent&lt;/code&gt; function to calculate a domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateDomain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tempDomain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then use this domain definitions in a &lt;code&gt;scale&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tempScale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleLinear&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tempDomain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolateRound&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateScale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dateDomain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a Line
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;d3.line&lt;/code&gt; function is useful for creating a &lt;code&gt;d&lt;/code&gt; attribute for an SVG &lt;code&gt;path&lt;/code&gt; element which defines the line segments&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;line&lt;/code&gt; function requires &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; mappings. The line for the graph path can be seen as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Datum&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dateScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;tempScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;))(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also include the &lt;code&gt;Datum&lt;/code&gt; type in the above to scope down the type of &lt;code&gt;data&lt;/code&gt; allowed in the resulting function&lt;/p&gt;

&lt;h3&gt;
  
  
  Formatting
&lt;/h3&gt;

&lt;p&gt;D3 includes functions for formatting &lt;code&gt;DateTime&lt;/code&gt;s. We can create a formatter for a &lt;code&gt;DateTime&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%Y-%m&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then use the formatter like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dateTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Grid Lines
&lt;/h3&gt;

&lt;p&gt;We can define the X Axis and grid lines similar to how we did it previously:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xGrid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dateTicks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;line&lt;/span&gt;
      &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lightgrey"&lt;/span&gt;
      &lt;span class="na"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dateScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;y1&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dateScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;y2&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;strokeDasharray&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt; &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"darkgrey"&lt;/span&gt; &lt;span class="na"&gt;textAnchor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"middle"&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dateScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the Y Axis grid lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yGrid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tempTicks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;line&lt;/span&gt;
      &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"lightgrey"&lt;/span&gt;
      &lt;span class="na"&gt;y1&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tempScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;y2&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tempScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;strokeDasharray&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt;
      &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"darkgrey"&lt;/span&gt;
      &lt;span class="na"&gt;textAnchor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"end"&lt;/span&gt;
      &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tempScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Final result
&lt;/h3&gt;

&lt;p&gt;Using all the values that have been defined above, we can create the overall graph and grid lines like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;xGrid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;yGrid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"steelblue"&lt;/span&gt; &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortanately, since DEV seems to be breaking my code samples, you'll have to jump over to my website if you want to see the final code and SVG samples &lt;a href="https://nabeelvalley.co.za/blog/2022/11-02/d3-with-react"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>d3</category>
      <category>graph</category>
      <category>svg</category>
    </item>
    <item>
      <title>blog: Building Serverless Apps using the Serverless Stack Framework</title>
      <dc:creator>Nabeel Valley</dc:creator>
      <pubDate>Thu, 17 Jun 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/nabeelvalley/blog-building-serverless-apps-using-the-serverless-stack-framework-3pla</link>
      <guid>https://dev.to/nabeelvalley/blog-building-serverless-apps-using-the-serverless-stack-framework-3pla</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Prior to doing any of the below you will require your &lt;code&gt;~/.aws/credentials&lt;/code&gt; file to be configured with the credentials for your AWS account&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Serverless Stack Framework
&lt;/h2&gt;

&lt;p&gt;SST Framework is a framework built on top of CDK for working with Lambdas and other CDK constructs&lt;/p&gt;

&lt;p&gt;It provides easy CDK setups and a streamlined debug and deploy process and even has integration with the VSCode debugger to debug stacks on AWS&lt;/p&gt;

&lt;h3&gt;
  
  
  Init Project
&lt;/h3&gt;

&lt;p&gt;To init a new project use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-serverless-stack@latest my-sst-app --language typescript

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

&lt;/div&gt;



&lt;p&gt;Which will create a Serverless Stack applocation using TypeScript&lt;/p&gt;

&lt;h3&gt;
  
  
  Run the App
&lt;/h3&gt;

&lt;p&gt;You can run the created project in using the config defined in the &lt;code&gt;sst.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "my-sst-app",
  "stage": "dev",
  "region": "us-east-1",
  "lint": true,
  "typeCheck": true
}

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

&lt;/div&gt;



&lt;p&gt;Using the following commands command will build then deploy a dev stack and allow you to interact with it via AWS/browser/Postman/etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run start

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

&lt;/div&gt;



&lt;p&gt;Additionally, running using the above command will also start the application with hot reloading enabled so when you save files the corresponding AWS resources will be redeployed so you can continue testing&lt;/p&gt;

&lt;h3&gt;
  
  
  The Files
&lt;/h3&gt;

&lt;p&gt;The application is structured like a relatively normal Lambda/CDK app with &lt;code&gt;lib&lt;/code&gt; which contains the following CDK code:&lt;/p&gt;

&lt;h4&gt;
  
  
  Stack
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;lib/index.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import MyStack from "./MyStack";
import * as sst from "@serverless-stack/resources";

export default function main(app: sst.App): void {
  // Set default runtime for all functions
  app.setDefaultFunctionProps({
  runtime: "nodejs12.x"
  });

  new MyStack(app, "my-stack");

  // Add more stacks
}

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;lib/MyStack.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as sst from "@serverless-stack/resources";

export default class MyStack extends sst.Stack {
  constructor(scope: sst.App, id: string, props?: sst.StackProps) {
  super(scope, id, props);

  // Create the HTTP API
  const api = new sst.Api(this, "Api", {
    routes: {
    "GET /": "src/lambda.handler" },
  });

  // Show API endpoint in output
  this.addOutputs({
    "ApiEndpoint": api.httpApi.apiEndpoint,
  });
  }
}

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

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;src&lt;/code&gt; which contains the lambda code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/lambda.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } from "aws-lambda";

export const handler: APIGatewayProxyHandlerV2 = async (
  event: APIGatewayProxyEventV2
) =&amp;gt; {
  return {
  statusCode: 200,
  headers: { "Content-Type": "text/plain" },
  body: `Hello, World! Your request was received at ${event.requestContext.time}.`,
  };
};

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add a new Endpoint
&lt;/h3&gt;

&lt;p&gt;Using the defined constructs it's really easy for us to add an additional endpoint:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/hello.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } from "aws-lambda";

export const handler: APIGatewayProxyHandlerV2 = async (
  event: APIGatewayProxyEventV2
) =&amp;gt; {
  const response = {
    data: 'Hello, World! This is another lambda but with JSON'
  }

  return {
  statusCode: 200,
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(response),
  };
};

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

&lt;/div&gt;



&lt;p&gt;And then in the stack we just update the routes:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lib/MyStack.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const api = new sst.Api(this, "Api", {
  routes: {
  "GET /": "src/lambda.handler",
  "GET /hello": "src/hello.handler" // new endpoint handler
  },
});

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

&lt;/div&gt;



&lt;p&gt;So that the full stack looks like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lib/MyStack.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as sst from "@serverless-stack/resources";

export default class MyStack extends sst.Stack {
  constructor(scope: sst.App, id: string, props?: sst.StackProps) {
  super(scope, id, props);

  // Create the HTTP API
  const api = new sst.Api(this, "Api", {
    routes: {
    "GET /": "src/lambda.handler",
    "GET /hello": "src/hello.handler"
    },
  });

  // Show API endpoint in output
  this.addOutputs({
    "ApiEndpoint": api.httpApi.apiEndpoint,
  });
  }
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  VSCode Debugging
&lt;/h3&gt;

&lt;p&gt;SST supports VSCode Debugging, all that's required is for you to create a &lt;code&gt;.vscode/launch.json&lt;/code&gt; filw with the following content:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.vscode/launch.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug SST Start",
      "type": "node",
      "request": "launch",
      "runtimeExecutable": "npm",
      "runtimeArgs": ["start"],
      "port": 9229,
      "skipFiles": ["&amp;lt;node_internals&amp;gt;/**"]
    },
    {
      "name": "Debug SST Tests",
      "type": "node",
      "request": "launch",
      "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/sst",
      "args": ["test", "--runInBand", "--no-cache", "--watchAll=false"],
      "cwd": "${workspaceRoot}",
      "protocol": "inspector",
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "env": { "CI": "true" },
      "disableOptimisticBPs": true
    }
  ]
} 

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

&lt;/div&gt;



&lt;p&gt;This will then allow you to run &lt;code&gt;Debug SST Start&lt;/code&gt; which will configure the AWS resources using the &lt;code&gt;npm start&lt;/code&gt; command and connect the debugger to the instance so you can debug your functions locally as well as make use of the automated function deployment&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a DB
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;From &lt;a href="https://serverless-stack.com/examples/how-to-create-a-crud-api-with-serverless-using-dynamodb.html"&gt;these docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can define our table using the &lt;code&gt;sst.Table&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const table = new sst.Table(this, "Notes", {
  fields: {
  userId: sst.TableFieldType.STRING,
  noteId: sst.TableFieldType.NUMBER
  },
  primaryIndex: {
  partitionKey: "userId", sortKey: "noteId"
  }
})

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

&lt;/div&gt;



&lt;p&gt;Next, we can add some endpoint definitions for the functions we'll create as well as access to the table name via the environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const api = new sst.Api(this, "Api", {
  defaultFunctionProps: {
      timeout: 60, // increase timeout so we can debug
    environment: {
      tableName: table.dynamodbTable.tableName,
    },
  },
  routes: {
  // .. other routes
    "GET /notes": "src/notes/getAll.handler", // userId in query
    "GET /notes/{noteId}": "src/notes/get.handler", // userId in query
    "POST /notes": "src/notes/create.handler"
  },
});

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

&lt;/div&gt;



&lt;p&gt;And lastly we can grant the permissions to our &lt;code&gt;api&lt;/code&gt; to access the &lt;code&gt;table&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;api.attachPermissions([table])

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

&lt;/div&gt;



&lt;p&gt;Adding the above to the &lt;code&gt;MyStack.ts&lt;/code&gt; file results in the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as sst from "@serverless-stack/resources";

export default class MyStack extends sst.Stack {
  constructor(scope: sst.App, id: string, props?: sst.StackProps) {
  super(scope, id, props);

  const table = new sst.Table(this, "Notes", {
    fields: {
    userId: sst.TableFieldType.STRING,
    noteId: sst.TableFieldType.STRING
    },
    primaryIndex: {
    partitionKey: "userId", sortKey: "noteId"
    }
  })

  // Create the HTTP API
  const api = new sst.Api(this, "Api", {
    defaultFunctionProps: {
    timeout: 60, // increase timeout so we can debug
    environment: {
      tableName: table.dynamodbTable.tableName,
    },
    },
    routes: {
    // .. other routes
    "GET /notes": "src/notes/getAll.handler", // userId in query
    "GET /notes/{noteId}": "src/notes/get.handler", // userId in query
    "POST /notes": "src/notes/create.handler"
    },
  });

  api.attachPermissions([table])

  // Show API endpoint in output
  this.addOutputs({
    "ApiEndpoint": api.httpApi.apiEndpoint,
  });
  }
}

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

&lt;/div&gt;



&lt;p&gt;Before we go any further, we need to install some dependencies in our app, particularly &lt;code&gt;uuid&lt;/code&gt; for generating unique id's for notes, we can install a dependency with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install uuid
npm install aws-sdk

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define Common Structures
&lt;/h3&gt;

&lt;p&gt;We'll also create some general helper functions for returning responses of different types, you can view the details for their files below but these just wrap the response in a status and header as well as stringify the body&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/responses/successResponse.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const successResponse = &amp;lt;T&amp;gt;(item: T) =&amp;gt; {
  return {
  statusCode: 200,
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(item),
  };
};

export default successResponse;

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;src/responses/badResuestsResponse.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const badRequestResponse = (msg: string) =&amp;gt; {
  return {
  statusCode: 400,
  headers: { "Content-Type": "text/plain" },
  body: msg,
  };
}

export default badRequestResponse

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;src/responses/internalErrorResponse.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const internalErrorResponse = (msg: string) =&amp;gt; {
  console.error(msg);
  return {
    statusCode: 500,
    headers: { "Content-Type": "text/plain" },
    body: "internal error",
  };
  };

export default internalErrorResponse

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

&lt;/div&gt;



&lt;p&gt;And we've also got a &lt;code&gt;Note&lt;/code&gt; type which will be the data that gets stored/retreived:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/notes/Note.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Note = {
  userId: string;
  noteId: string;
  content?: string;
  createdAt: number;
};

export default Note

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Access DB
&lt;/h3&gt;

&lt;p&gt;Once we've got a DB table defined as above, we can then access the table to execute different queries&lt;/p&gt;

&lt;p&gt;We would create a DB object instance using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const db = new DynamoDB.DocumentClient();

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Create
&lt;/h4&gt;

&lt;p&gt;A &lt;code&gt;create&lt;/code&gt; is the simplest one of the database functions for us to implement, this uses the &lt;code&gt;db.put&lt;/code&gt; function with the &lt;code&gt;Item&lt;/code&gt; to save which is of type &lt;code&gt;Note&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const create = async (tableName: string, item: Note) =&amp;gt; {
  await db.put({ TableName: tableName, Item: item }).promise();
};

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Get
&lt;/h4&gt;

&lt;p&gt;We can implement a &lt;code&gt;getOne&lt;/code&gt; function by using &lt;code&gt;db.get&lt;/code&gt; and providing the full &lt;code&gt;Key&lt;/code&gt; consisting of the &lt;code&gt;userId&lt;/code&gt; and &lt;code&gt;noteId&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const getOne = async (tableName: string, noteId: string, userId: string) =&amp;gt; {
  const result = await db.get({
    TableName: tableName,
    Key: {
      userId: userId,
      noteId: noteId
    }
  }).promise();

  return result.Item
};

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  GetAll
&lt;/h4&gt;

&lt;p&gt;We can implement a &lt;code&gt;getByUserId&lt;/code&gt; function which will make use of &lt;code&gt;db.query&lt;/code&gt; and use the &lt;code&gt;ExpressionAttributeValues&lt;/code&gt; to populate the &lt;code&gt;KeyConditionExpression&lt;/code&gt; as seen below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const getByUserId = async (tableName: string, userId: string) =&amp;gt; {
  const result = await db.query({
    TableName: tableName,
    KeyConditionExpression: "userId = :userId",
    ExpressionAttributeValues: {
      ":userId": userId,
    },
  }).promise();

  return result.Items
};

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define Lambdas
&lt;/h3&gt;

&lt;p&gt;Now that we know how to write data to Dynamo, we can implement the following files for the endpoints we defined above:&lt;/p&gt;

&lt;h4&gt;
  
  
  Create
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;src/notes/create.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } from "aws-lambda";
import { DynamoDB } from "aws-sdk";
import { v1 } from "uuid";
import internalErrorResponse from "../responses/internalErrorResponse";
import successResponse from "../responses/successResponse";
import badRequestResponse from "../responses/badRequestResponse"
import Note from "./Note";

const db = new DynamoDB.DocumentClient();

const toItem = (data: string, content: string): Note =&amp;gt; {
  return {
    userId: data,
    noteId: v1(),
    content: content,
    createdAt: Date.now(),
  };
};

const parseBody = (event: APIGatewayProxyEventV2) =&amp;gt; {
  const data = JSON.parse(event.body || "{}");

  return {
    userId: data.userId,
    content: data.content,
  };
};

const isValid = (data: Partial&amp;lt;Note&amp;gt;) =&amp;gt;
  typeof data.userId !== "undefined" &amp;amp;&amp;amp; typeof data.content !== "undefined";

const create = async (tableName: string, item: Note) =&amp;gt; {
  await db.put({ TableName: tableName, Item: item }).promise();
};

export const handler: APIGatewayProxyHandlerV2 = async (
  event: APIGatewayProxyEventV2
) =&amp;gt; {
  if (typeof process.env.tableName === "undefined")
    return internalErrorResponse("tableName is undefined");

  const tableName = process.env.tableName;
  const data = parseBody(event);

  if (!isValid(data)) return badRequestResponse("userId and content are required");

  const item = toItem(data.userId, data.content);
  await create(tableName, item);

  return successResponse(item)
};

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Get
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;src/notes/get.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } from "aws-lambda";
import { DynamoDB } from "aws-sdk";
import badRequestResponse from "../responses/badRequestResponse";
import internalErrorResponse from "../responses/internalErrorResponse";
import successResponse from "../responses/successResponse";

type RequestParams = {
  noteId?: string;
  userId?: string
};

const db = new DynamoDB.DocumentClient();

const parseBody = (event: APIGatewayProxyEventV2): RequestParams =&amp;gt; {
  const pathData = event.pathParameters;
  const queryData = event.queryStringParameters;

  return {
    noteId: pathData?.noteId,
    userId: queryData?.userId
  };
};

const isValid = (data: RequestParams) =&amp;gt; typeof data.noteId !== "undefined" &amp;amp;&amp;amp; typeof data.userId !== 'undefined'

const getOne = async (tableName: string, noteId: string, userId: string) =&amp;gt; {
  const result = await db.get({
    TableName: tableName,
    Key: {
      userId: userId,
      noteId: noteId
    }
  }).promise();

  return result.Item
};

export const handler: APIGatewayProxyHandlerV2 = async (
  event: APIGatewayProxyEventV2
) =&amp;gt; {
  const data = parseBody(event);

  if (typeof process.env.tableName === "undefined")
    return internalErrorResponse("tableName is undefined");

  const tableName = process.env.tableName;

  if (!isValid(data)) return badRequestResponse("noteId is required in path, userId is required in query");

  const items = await getOne(tableName, data.noteId as string, data.userId as string);

  return successResponse(items)
};
import { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } from "aws-lambda";
import { DynamoDB } from "aws-sdk";
import badRequestResponse from "../responses/badRequestResponse";
import internalErrorResponse from "../responses/internalErrorResponse";
import successResponse from "../responses/successResponse";

type RequestParams = {
  noteId?: string;
  userId?: string
};

const db = new DynamoDB.DocumentClient();

const parseBody = (event: APIGatewayProxyEventV2): RequestParams =&amp;gt; {
  const pathData = event.pathParameters;
  const queryData = event.queryStringParameters;

  return {
    noteId: pathData?.noteId,
    userId: queryData?.userId
  };
};

const isValid = (data: RequestParams) =&amp;gt; typeof data.noteId !== "undefined" &amp;amp;&amp;amp; typeof data.userId !== 'undefined'

const getOne = async (tableName: string, noteId: string, userId: string) =&amp;gt; {
  const result = await db.get({
    TableName: tableName,
    Key: {
      userId: userId,
      noteId: noteId
    }
  }).promise();

  return result.Item
};

export const handler: APIGatewayProxyHandlerV2 = async (
  event: APIGatewayProxyEventV2
) =&amp;gt; {
  const data = parseBody(event);

  if (typeof process.env.tableName === "undefined")
    return internalErrorResponse("tableName is undefined");

  const tableName = process.env.tableName;

  if (!isValid(data)) return badRequestResponse("noteId is required in path, userId is required in query");

  const items = await getOne(tableName, data.noteId as string, data.userId as string);

  return successResponse(items)
};

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  GetAll
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;src/notes/getAll.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } from "aws-lambda";
import { DynamoDB } from "aws-sdk";
import badRequestResponse from "../responses/badRequestResponse";
import internalErrorResponse from "../responses/internalErrorResponse";
import successResponse from "../responses/successResponse";

type PathParams = {
  userId?: string;
};

const db = new DynamoDB.DocumentClient();

const parseBody = (event: APIGatewayProxyEventV2): PathParams =&amp;gt; {
  const data = event.queryStringParameters;

  return {
    userId: data?.userId,
  };
};

const isValid = (data: PathParams) =&amp;gt; typeof data.userId !== "undefined";

const getByUserId = async (tableName: string, userId: string) =&amp;gt; {
  const result = await db.query({
    TableName: tableName,
    KeyConditionExpression: "userId = :userId",
    ExpressionAttributeValues: {
      ":userId": userId,
    },
  }).promise();

  return result.Items
};

export const handler: APIGatewayProxyHandlerV2 = async (
  event: APIGatewayProxyEventV2
) =&amp;gt; {
  const data = parseBody(event);

  if (typeof process.env.tableName === "undefined")
    return internalErrorResponse("tableName is undefined");

  const tableName = process.env.tableName;

  if (!isValid(data)) return badRequestResponse("userId is required in query");

  const items = await getByUserId(tableName, data.userId as string);

  return successResponse(items)
};

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Testing
&lt;/h4&gt;

&lt;p&gt;Once we've got all the above completed, we can actually test our endpoints and create and read back data&lt;/p&gt;

&lt;p&gt;&lt;code&gt;create&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST https://AWS_ENDPOINT_HERE/notes

{
  "userId": "USER_ID",
  "content": "Hello world"
}

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

&lt;/div&gt;



&lt;p&gt;Which responds with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;200

{
  "content": "Hello world",
  "createdAt": 1619177078298,
  "noteId": "NOTE_ID_UUID",
  "userId": "USER_ID"
}

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;get&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET https://AWS_ENDPOINT_HERE/notes/NOTE_ID_UUID?userId=USER_ID


200

{
  "content": "Hello world",
  "createdAt": 1619177078298,
  "noteId": "NOTE_ID_UUID",
  "userId": "USER_ID"
}

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;getAll&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET htttps://AWS_ENDPOINT_HERE/notes?userId=USER_ID


200

[
  {
    "content": "Hello world",
    "createdAt": 1619177078298,
    "noteId": "NOTE_ID_UUID",
    "userId": "USER_ID"
  }
]

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating Notes Using a Queue
&lt;/h3&gt;

&lt;p&gt;When working with microservices a common pattern is to use a message queue for any operations that can happen in an asynchronous fashion, we can create an SQS queue which we can use to stage messages and then separately save them at a rate that we're able to process them&lt;/p&gt;

&lt;p&gt;In order to make this kind of logic we're going to break up our &lt;code&gt;create&lt;/code&gt; data flow - a the moment it's this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lambda -&amp;gt; dynamo
return &amp;lt;-

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

&lt;/div&gt;



&lt;p&gt;We're going to turn it into this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lambda1 -&amp;gt; sqs
 return &amp;lt;-

          sqs -&amp;gt; lambda2 -&amp;gt; dynamo

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

&lt;/div&gt;



&lt;p&gt;This kind of pattern becomes especially useful if we're doing a lot more stuff with the data other than just the single DB operation and also allows us to retry things like saving to the DB if we have errors, etc.&lt;/p&gt;

&lt;p&gt;A more complex data flow could look something like this (not what we're implementing):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lambda1 -&amp;gt; sqs
 return &amp;lt;-

           sqs -&amp;gt; lambda2 -&amp;gt; dynamo // save to db
               -&amp;gt; lambda3 -&amp;gt; s3 // generate a report
           sqs &amp;lt;-

           sqs -&amp;gt; lambda4 // send an email

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Create Queue
&lt;/h4&gt;

&lt;p&gt;SST provides us with the &lt;code&gt;sst.Queue&lt;/code&gt; class that we can use for this purpose&lt;/p&gt;

&lt;p&gt;To create a Queue you can use the following in stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const queue = new sst.Queue(this, "NotesQueue", {
  consumer: "src/consumers/createNote.handler",
});

queue.attachPermissions([table]);
queue.consumerFunction?.addEnvironment(
  "tableName",
  table.dynamodbTable.tableName
);

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

&lt;/div&gt;



&lt;p&gt;The above code does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;queue&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Give the queue permission to access the &lt;code&gt;table&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add the &lt;code&gt;tableName&lt;/code&gt; environment variable to the &lt;code&gt;queue&lt;/code&gt;'s &lt;code&gt;consumerFunction&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will also need to grant permissions to the API to access the &lt;code&gt;queue&lt;/code&gt; so that our &lt;code&gt;create&lt;/code&gt; handler is able to add messages to the &lt;code&gt;queue&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;api.attachPermissions([table, queue]);

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

&lt;/div&gt;



&lt;p&gt;Which means our Stack now looks like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lib/MyStack.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as sst from "@serverless-stack/resources";

export default class MyStack extends sst.Stack {
  constructor(scope: sst.App, id: string, props?: sst.StackProps) {
    super(scope, id, props);

    const table = new sst.Table(this, "Notes", {
      fields: {
        userId: sst.TableFieldType.STRING,
        noteId: sst.TableFieldType.STRING,
      },
      primaryIndex: {
        partitionKey: "userId",
        sortKey: "noteId",
      },
    });

    const queue = new sst.Queue(this, "NotesQueue", {
      consumer: "src/consumers/createNote.handler",
    });

    queue.attachPermissions([table]);
    queue.consumerFunction?.addEnvironment(
      "tableName",
      table.dynamodbTable.tableName
    );

    // Create the HTTP API
    const api = new sst.Api(this, "Api", {
      defaultFunctionProps: {
        timeout: 60, // increase timeout so we can debug
        environment: {
          tableName: table.dynamodbTable.tableName,
          queueUrl: queue.sqsQueue.queueUrl,
        },
      },
      routes: {
        "GET /": "src/lambda.handler",
        "GET /hello": "src/hello.handler",
        "GET /notes": "src/notes/getAll.handler",
        "POST /notes": "src/notes/create.handler",
        "GET /notes/{noteId}": "src/notes/get.handler",
      },
    });

    api.attachPermissions([table, queue]);

    // Show API endpoint in output
    this.addOutputs({
      ApiEndpoint: api.httpApi.apiEndpoint,
    });
  }
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Update the Create Handler
&lt;/h4&gt;

&lt;p&gt;Since we plan to create notes via a queue we will update our &lt;code&gt;create&lt;/code&gt; function in the handler to create a new message in the &lt;code&gt;queue&lt;/code&gt;, this is done using the &lt;code&gt;SQS&lt;/code&gt; class from &lt;code&gt;aws-sdk&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/notes/create.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { SQS } from "aws-sdk";

const queue = new SQS();

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

&lt;/div&gt;



&lt;p&gt;Once we've got our instance, the &lt;code&gt;create&lt;/code&gt; function is done by means of the &lt;code&gt;queue.sendMessage&lt;/code&gt; function:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/notes/create.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const create = async (queueUrl: string, item: Note) =&amp;gt; {
  return await queue
    .sendMessage({
      QueueUrl: queueUrl,
      DelaySeconds: 0,
      MessageBody: JSON.stringify(item),
    })
    .promise();
};

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

&lt;/div&gt;



&lt;p&gt;Lastly, our &lt;code&gt;handler&lt;/code&gt; remains mostly the same with the exception of some additional validation to check that we have the &lt;code&gt;queue&lt;/code&gt; connection information in the environment:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/notes/create.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const handler: APIGatewayProxyHandlerV2 = async (
  event: APIGatewayProxyEventV2
) =&amp;gt; {
  // pre-save validation
  if (typeof process.env.queueUrl === "undefined")
    return internalErrorResponse("queueUrl is undefined");

  const queueUrl = process.env.queueUrl;

  const data = parseBody(event);

  if (!isValid(data))
    return badRequestResponse("userId and content are required");

  // save process
  const item = toItem(data.userId, data.content);
  const creatresult = await create(queueUrl, item);

  if (!creatresult.MessageId) internalErrorResponse("MessageId is undefined");

  return successResponse(item);
};

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

&lt;/div&gt;



&lt;p&gt;Implementing the above into the &lt;code&gt;create&lt;/code&gt; handler means that our &lt;code&gt;create.ts&lt;/code&gt; file now looks like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/notes/create.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } from "aws-lambda";
import { v1 } from "uuid";
import internalErrorResponse from "../responses/internalErrorResponse";
import successResponse from "../responses/successResponse";
import badRequestResponse from "../responses/badRequestResponse";
import Note from "./Note";
import { SQS } from "aws-sdk";

const queue = new SQS();

// helper functions start

const toItem = (data: string, content: string): Note =&amp;gt; {
  return {
    userId: data,
    noteId: v1(),
    content: content,
    createdAt: Date.now(),
  };
};

const parseBody = (event: APIGatewayProxyEventV2) =&amp;gt; {
  const data = JSON.parse(event.body || "{}");

  return {
    userId: data.userId,
    content: data.content,
  };
};

const isValid = (data: Partial&amp;lt;Note&amp;gt;) =&amp;gt;
  typeof data.userId !== "undefined" &amp;amp;&amp;amp; typeof data.content !== "undefined";

// helper functions end

const create = async (queueUrl: string, item: Note) =&amp;gt; {
  return await queue
    .sendMessage({
      QueueUrl: queueUrl,
      DelaySeconds: 0,
      MessageBody: JSON.stringify(item),
    })
    .promise();
};

export const handler: APIGatewayProxyHandlerV2 = async (
  event: APIGatewayProxyEventV2
) =&amp;gt; {
  // pre-save validation
  if (typeof process.env.queueUrl === "undefined")
    return internalErrorResponse("queueUrl is undefined");

  const queueUrl = process.env.queueUrl;

  const data = parseBody(event);

  if (!isValid(data))
    return badRequestResponse("userId and content are required");

  // save process
  const item = toItem(data.userId, data.content);
  const creatresult = await create(queueUrl, item);

  if (!creatresult.MessageId) internalErrorResponse("MessageId is undefined");

  return successResponse(item);
};

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Add Queue-Based Create Handler
&lt;/h4&gt;

&lt;p&gt;Now that we've updated our logic to save the notes into the &lt;code&gt;queue&lt;/code&gt;, we need to add the logic for the &lt;code&gt;src/consumers/createNote.handler&lt;/code&gt; consumer function as we specified above, this handler will be sent an &lt;code&gt;SQSEvent&lt;/code&gt; and will make use of the DynamoDB Table we gave it permissions to use&lt;/p&gt;

&lt;p&gt;First, we take the &lt;code&gt;create&lt;/code&gt; function that was previously on the &lt;code&gt;create.ts&lt;/code&gt; file for saving to the DB:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/consumers/createNote.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { DynamoDB } from "aws-sdk";

const db = new DynamoDB.DocumentClient();

const create = async (tableName: string, item: Note) =&amp;gt; {
  const createResult = await db
    .put({ TableName: tableName, Item: item })
    .promise();
  if (!createResult) throw new Error("create failed");

  return createResult;
};

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

&lt;/div&gt;



&lt;p&gt;We'll also need a function for parsing the &lt;code&gt;SQSRecord&lt;/code&gt; object into a &lt;code&gt;Note&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/consumers/createNote.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const parseBody = (record: SQSRecord): Note =&amp;gt; {
  const { noteId, userId, content, createdAt } = JSON.parse(
    record.body
  ) as Note;

  // do this to ensure we only extract information we need
  return {
    noteId,
    userId,
    content,
    createdAt,
  };
};

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

&lt;/div&gt;



&lt;p&gt;And finally we consume the above through the &lt;code&gt;handler&lt;/code&gt;, you can see in the below code that we are iterating over the &lt;code&gt;event.Records&lt;/code&gt; object, this is because the &lt;code&gt;SQSEvent&lt;/code&gt; adds each new event into this array, the reason for this is because we can also specify batching into our Queue so that the handler is only triggered after &lt;code&gt;n&lt;/code&gt; events instead of each time, and though this isn't happening in our case, we still should handle this for our handler:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/consumers/createNote.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const handler: SQSHandler = async (event) =&amp;gt; {
  // pre-save environment check
  if (typeof process.env.tableName === "undefined")
    throw new Error("tableName is undefined");

  const tableName = process.env.tableName;

  for (let i = 0; i &amp;lt; event.Records.length; i++) {
    const r = event.Records[i];
    const item = parseBody(r);
    console.log(item);

    const result = await create(tableName, item);
    console.log(result);
  }
};

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

&lt;/div&gt;



&lt;p&gt;Putting all the above together our &lt;code&gt;createNote.ts&lt;/code&gt; file now has the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { SQSHandler, SQSRecord } from "aws-lambda";
import Note from "../notes/Note";
import { DynamoDB } from "aws-sdk";

const db = new DynamoDB.DocumentClient();

const create = async (tableName: string, item: Note) =&amp;gt; {
  const createResult = await db
    .put({ TableName: tableName, Item: item })
    .promise();
  if (!createResult) throw new Error("create failed");

  return createResult;
};

const parseBody = (record: SQSRecord): Note =&amp;gt; {
  const { noteId, userId, content, createdAt } = JSON.parse(
    record.body
  ) as Note;

  // do this to ensure we only extract information we need
  return {
    noteId,
    userId,
    content,
    createdAt,
  };
};

export const handler: SQSHandler = async (event) =&amp;gt; {
  if (typeof process.env.tableName === "undefined")
    throw new Error("tableName is undefined");

  const tableName = process.env.tableName;

  for (let i = 0; i &amp;lt; event.Records.length; i++) {
    const r = event.Records[i];
    const item = parseBody(r);
    console.log(item);

    const result = await create(tableName, item);
    console.log(result);
  }
};

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

&lt;/div&gt;



&lt;p&gt;This completes the implementation of the asynchronous saving mechanism for notes. As far as a consumer of our API is concerned, nothing has changed and they will still be able to use the API exactly as we had in the Testing section above&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy
&lt;/h2&gt;

&lt;p&gt;Thus far, we've just been running our API in &lt;code&gt;debug&lt;/code&gt; mode via the &lt;code&gt;npm run start&lt;/code&gt; command, while useful for testing this adds a lot of code to make debugging possible, and isn't something we'd want in our final deployed code&lt;/p&gt;

&lt;p&gt;Deploying using &lt;code&gt;sst&lt;/code&gt; is still very easy, all we need to do is run the &lt;code&gt;npm run deploy&lt;/code&gt; command and this will update our lambda to use a production build of the code instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run deploy

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Teardown
&lt;/h2&gt;

&lt;p&gt;Lastly, the &lt;code&gt;sst&lt;/code&gt; CLI also provides us with a function to teardown our &lt;code&gt;start&lt;/code&gt;/&lt;code&gt;deploy&lt;/code&gt; code. So once you're done playing around you can use this to teardown all your deployed services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run remove

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note that running the &lt;code&gt;remove&lt;/code&gt; command will not delete the DB tables, you will need to do this manually&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>serverless</category>
      <category>aws</category>
      <category>typescript</category>
    </item>
    <item>
      <title>stdout: Multi-module Python project using an __init__.py file</title>
      <dc:creator>Nabeel Valley</dc:creator>
      <pubDate>Thu, 06 May 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/nabeelvalley/stdout-multi-module-python-project-using-an-init-py-file-2b45</link>
      <guid>https://dev.to/nabeelvalley/stdout-multi-module-python-project-using-an-init-py-file-2b45</guid>
      <description>&lt;p&gt;When creating a multi-module project for Python, especially when coming from another language ecosystem, you may encounter issues importing code from other files, let's take a look at this&lt;/p&gt;

&lt;h2&gt;
  
  
  The Modules
&lt;/h2&gt;

&lt;p&gt;In our project, we've got the following files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package1
  |- module1.py
package2
  |- namespace2
       |- module2.py
main.py

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

&lt;/div&gt;



&lt;p&gt;Let's say each of our modules export a function, here's the code for them:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;package1/module1.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def hello_p1_m1():
  return "hello"

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;package2/subpackage1/module1.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def hello_p2_s1_m1():
  return "hello"

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Main
&lt;/h2&gt;

&lt;p&gt;Now that we've got our files with their functions separated, we try using them from the &lt;code&gt;main.py&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;main.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import package1.module1 as p1m1
import package2.namespace1.module1 as p2s1m1

print(p1m1.hello_p1_m1())
print(p2n1m1.hello_p2_s1_m1())

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Error
&lt;/h2&gt;

&lt;p&gt;Now, we try to run this using &lt;code&gt;python&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python main.py

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

&lt;/div&gt;



&lt;p&gt;And we get the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Traceback (most recent call last):
  File "main.py", line 1, in &amp;lt;module&amp;gt;
    import package1.module1 as p1m1
ImportError: No module named package1.module1

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Now, this can be pretty annoying, but the solution is very simple. Python identifies a &lt;code&gt;module&lt;/code&gt; as a single file, and the assumption that leads to the issue above is that we assume a &lt;code&gt;package&lt;/code&gt; has the same convention of just being a directory&lt;/p&gt;

&lt;p&gt;However, a &lt;code&gt;packgage&lt;/code&gt; requires an &lt;code&gt;__init__.py&lt;/code&gt; file to be defined so that they are recognized correctly&lt;/p&gt;

&lt;p&gt;So, we need to add two files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;package1/ __init__.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package2/subpackage1/ __init__.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, these files are completely empty, and only serve as information. Note that we don't need to include a file in &lt;code&gt;package2&lt;/code&gt; directly as this directory does not contain any modules within it so is not really a package in itself and is simply a wrapper &lt;code&gt;subpackage1&lt;/code&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Custom Attributes in C# Web Controllers</title>
      <dc:creator>Nabeel Valley</dc:creator>
      <pubDate>Sat, 06 Mar 2021 17:42:41 +0000</pubDate>
      <link>https://dev.to/nabeelvalley/custom-attributes-in-c-web-controllers-3726</link>
      <guid>https://dev.to/nabeelvalley/custom-attributes-in-c-web-controllers-3726</guid>
      <description>&lt;p&gt;Implementing an attribute for a WebAPI or class in C# can help to reduce duplication and centralize parts of the application logic. This could be used for a variety of tasks such as logging information when methods are called as well as managinng authorization&lt;/p&gt;

&lt;p&gt;In this post I'm going to cover the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Attribute Types and Execution Order

&lt;ul&gt;
&lt;li&gt;IActionFilter&lt;/li&gt;
&lt;li&gt;IAuthorizationFilter&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Modify Response Data&lt;/li&gt;
&lt;li&gt;Attribute on a Class&lt;/li&gt;
&lt;li&gt;Attributes with Input Parameters&lt;/li&gt;
&lt;li&gt;Attribute Setting at Class and Method Level&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Attribute Types and Execution Order
&lt;/h2&gt;

&lt;p&gt;There are a few different attribute types that we can handle on a WebAPI that provide us with the ability to wrap some functionality around our endpoints, below are some of the common attributes that we can implement and the order in which they execute (&lt;a href="https://stackoverflow.com/questions/19249511/difference-between-iactionfilter-and-iauthorizationfilter"&gt;StackOverflow&lt;/a&gt;)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Authorization - &lt;code&gt;IAuthorizationFilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Action - &lt;code&gt;IActionFilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Result - &lt;code&gt;IResultFilter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Exception - &lt;code&gt;IExceptionFilter&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  IActionFilter
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;IActionFilter&lt;/code&gt; executes before and after a method is executed and contains two different methods for doing this, namely the &lt;code&gt;OnActionExecuting&lt;/code&gt; and &lt;code&gt;OnActionExecuted&lt;/code&gt; methods respectively. A basic implemtation of &lt;code&gt;IActionFilter&lt;/code&gt; would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace CSharpAttributes.Attributes
{
  public class LogStatusAttribute : Attribute, IActionFilter
  {
    public LogStatusAttribute()
    {
      Console.WriteLine("Attribute Initialized");
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
      Console.WriteLine("OnActionExecuting");
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
      Console.WriteLine("OnActionExecuted");
    }
  }
}

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

&lt;/div&gt;



&lt;p&gt;This can then be implemented on a controller method with a &lt;code&gt;[LogStatus]&lt;/code&gt; attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[LogStatus]
[HttpGet]
public IEnumerable&amp;lt;WeatherForecast&amp;gt; Get()
{
  Console.WriteLine("Executing Get");
  return data;
}

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

&lt;/div&gt;



&lt;p&gt;The order of logging which we see will be as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Attribute Initialized&lt;/code&gt; when the controller is instantiated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OnActionExecuting&lt;/code&gt; when the controller is called&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Executing Get&lt;/code&gt; when the controller is executed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OnActionExecuted&lt;/code&gt; when the controller is done executing&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  IAuthorizationFilter
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;IAuthorizationFilter&lt;/code&gt; executes as the first filter on a controller's method call&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace CSharpAttributes.Attributes
{
  public class CustomAuthorizeAttribute : Attribute, IAuthorizationFilter
  {
    public CustomAuthorizeAttribute()
    {
      Console.WriteLine("Attribute Initialized");
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
      Console.WriteLine("OnAuthorization");
    }
  }
}

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

&lt;/div&gt;



&lt;p&gt;This can then be implemented on a controller method with a &lt;code&gt;[CustomAuthorize]&lt;/code&gt; attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[CustomAuthorize]
[HttpGet]
public IEnumerable&amp;lt;WeatherForecast&amp;gt; Get()
{
  Console.WriteLine("Executing Get");
  return data;
}

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

&lt;/div&gt;



&lt;p&gt;The order of logging which we see will be as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Attribute Initialized&lt;/code&gt; when the controller is instantiated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OnAuthorization&lt;/code&gt; when the controller is called&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Executing Get&lt;/code&gt; when the controller is executed&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Modify Response Data
&lt;/h2&gt;

&lt;p&gt;An attribute's &lt;code&gt;context&lt;/code&gt; parameter gives us ways by which we can access the &lt;code&gt;HttpContext&lt;/code&gt; as well as set the result of a method call so that it can be handled down the line. For example, we can implement our CustomAuthorize attribute with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void OnAuthorization(AuthorizationFilterContext context)
{
  if (!context.HttpContext.Request.Headers.ContainsKey("X-Custom-Auth"))
  {
    context.Result = new UnauthorizedResult();
  }

  Console.WriteLine("Attribute Called");
}

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

&lt;/div&gt;



&lt;p&gt;This will mean that if we set the &lt;code&gt;context.Result&lt;/code&gt; in our method then the controller will not be executed and the endpoint will return the &lt;code&gt;UnauthorizedResult&lt;/code&gt; early. You can also see that we're able to access things like the &lt;code&gt;HttpContext&lt;/code&gt; which makes it easy for us to view the request/response data and do things based on that&lt;/p&gt;

&lt;h2&gt;
  
  
  Attribute on a Class
&lt;/h2&gt;

&lt;p&gt;Note that it's also possible to apply the above to each method in a class by adding the attribute at the top of the class declaration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ApiController]
[LogStatus]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
  ...

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Attributes with Input Parameters
&lt;/h2&gt;

&lt;p&gt;We are also able to create attributes that enable the consumer to modify their behaviour by taking input parameters to the constructor, we can update our &lt;code&gt;LogStatus&lt;/code&gt; attribute to do something like add a prefix before all logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace CSharpAttributes.Attributes
{
  public class LogStatusAttribute : Attribute, IActionFilter
  {
    private readonly string _prefix;

    public LogStatusAttribute(string prefix = "")
    {
      _prefix = prefix;
      Console.WriteLine("Attribute Initialized");
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
      Console.WriteLine(_prefix + "OnActionExecuted");
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
      Console.WriteLine(_prefix + "OnActionExecuting");
    }
  }
}

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

&lt;/div&gt;



&lt;p&gt;Then, applying to our controller method like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[LogStatus("WeatherController-Get:")]
[HttpGet]
public IEnumerable&amp;lt;WeatherForecast&amp;gt; Get()
{
  Console.WriteLine("Executing Get");
  return data;
}

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

&lt;/div&gt;



&lt;p&gt;So the new output will look like so:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Attribute Initialized&lt;/code&gt; when the controller is instantiated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WeatherForecast-Get:OnActionExecuting&lt;/code&gt; when the controller is called&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Executing Get&lt;/code&gt; when the controller is executed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WeatherForecast-Get:OnActionExecuted&lt;/code&gt; when the controller is done executing&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Attribute Setting at Class and Method Level
&lt;/h2&gt;

&lt;p&gt;Since an attribute can be implemented at a class and method level it's useful for us to be able to implement it at a class and the override the behaviour or add behaviour for a specific method&lt;/p&gt;

&lt;p&gt;We can do this by setting the attribute inheritence to &lt;code&gt;false&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Updating out &lt;code&gt;LogStatusAttribute&lt;/code&gt; we can add the &lt;code&gt;AttributeUsage&lt;/code&gt; Attribute as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace CSharpAttributes.Attributes
{
  [AttributeUsage(AttributeTargets.All, Inherited = false)]
  public class LogStatusAttribute : Attribute, IActionFilter
  {
    ...

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

&lt;/div&gt;



&lt;p&gt;This means that we can independently apply the attribute at class and method levels, so now our controller can look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace CSharpAttributes.Controllers
{
  [ApiController]
  [Route("[controller]")]
  [LogStatus("WeatherForecast:")]
  public class WeatherForecastController : ControllerBase
  {
    [LogStatus("Get:")]
    [HttpGet]
    public IEnumerable&amp;lt;WeatherForecast&amp;gt; Get()
    {
      Console.WriteLine("Executing Get");
      return data;
    }
  }
}

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

&lt;/div&gt;



&lt;p&gt;Which will output the logs as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Attribute Initialized&lt;/code&gt; when the controller is instantiated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WeatherForecast:OnActionExecuting&lt;/code&gt; when the class is called&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Get:OnActionExecuting&lt;/code&gt; when the controller is called&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Executing Get&lt;/code&gt; when the controller is executed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Get:OnActionExecuted&lt;/code&gt; when the controller is done executing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WeatherForecast:OnActionExecuted&lt;/code&gt; when the class is done executing&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>csharp</category>
      <category>web</category>
      <category>api</category>
      <category>controller</category>
    </item>
    <item>
      <title>Code in a Container</title>
      <dc:creator>Nabeel Valley</dc:creator>
      <pubDate>Sun, 26 Jul 2020 16:20:29 +0000</pubDate>
      <link>https://dev.to/nabeelvalley/code-in-a-container-57pp</link>
      <guid>https://dev.to/nabeelvalley/code-in-a-container-57pp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post originally appeared on &lt;a href="https://nabeelvalley.netlify.app/blog/2020/25-07/developing-in-a-container-vscode/"&gt;my website&lt;/a&gt;. To keep up with my latest posts and projects you can follow me on &lt;a href="https://dev.to/nabeelvalley"&gt;DEV&lt;/a&gt;, &lt;a href="https://twitter.com/not_nabeel"&gt;Twitter&lt;/a&gt; or &lt;a href="https://github.com/nabeelvalley/"&gt;GitHub&lt;/a&gt; where my profiles are kept up to date with my work&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Recently I'd started using Visual Studio Code's &lt;em&gt;Remote Containers&lt;/em&gt; functionality for development and it's been really useful&lt;/p&gt;

&lt;p&gt;The Remote Containers extension allows us to write code and develop applications within a virtualized environment that makes it easier for us to manage our development environment as well as more closely resemble our target deployment environment (if we're deploying to Docker or Kubernetes)&lt;/p&gt;

&lt;p&gt;In this post, I'll take a look at what a Docker container is, why we would want to use one as a development environment, and how we can go about setting one up for VSCode&lt;/p&gt;

&lt;p&gt;Contents&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Docker Containers&lt;/li&gt;
&lt;li&gt;
Docker Images

&lt;ul&gt;
&lt;li&gt;Create an Application&lt;/li&gt;
&lt;li&gt;Create a Dockerfile&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Development Containers

&lt;ul&gt;
&lt;li&gt;Why Develop in a Container&lt;/li&gt;
&lt;li&gt;How to Develop in a Container&lt;/li&gt;
&lt;li&gt;Use an Existing Dockerfile&lt;/li&gt;
&lt;li&gt;Using a Preconfigured Dockerfile&lt;/li&gt;
&lt;li&gt;Which Method to Use&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Summary

&lt;ul&gt;
&lt;li&gt;Further Reading&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;If you intend to follow along with this post you'll need to have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Windows or Mac OS version capable of running Docker Desktop&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/desktop/#download-and-install"&gt;Docker Desktop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers"&gt;Visual Studio Code's Remote Containers Extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker"&gt;Visual Studio Code's Docker Extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Some familiarity with using the command line&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Docker Containers
&lt;/h1&gt;

&lt;p&gt;A Container, in this context, is a simple virtual machine that contains the code required to run an application with all its dependencies&lt;/p&gt;

&lt;p&gt;A Docker container is built from a &lt;code&gt;docker image&lt;/code&gt; and run by the &lt;code&gt;docker&lt;/code&gt; command. I'll explain these as we go along&lt;/p&gt;

&lt;p&gt;To check that Docker is installed correctly on your machine run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run hello-world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If your install is working correctly you should see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete

Digest: sha256:49a1c8800c94df04e9658809b006fd8a686cab8028d33cfba2cc049724254202
Status: Downloaded newer image for hello-world:latest

Hello from Docker

...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Docker Images
&lt;/h1&gt;

&lt;p&gt;Docker images are typically used to run applications in a production-type environment, every Docker container we run needs to be based on an image, every running container is like an instance of an image - similar to how objects are an instance of a class&lt;/p&gt;

&lt;p&gt;An image states what our container will need to be made of, what it depends on, and how it runs. We define how docker should build our image in a &lt;code&gt;Dockerfile&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We're going to go through some of the basics of Docker Images and Docker as would typically be done when creating a container to be run in production before we get into development containers so you've got an understanding of how this all works&lt;/p&gt;

&lt;p&gt;To get started create a new folder and open it from Visual Studio Code and do the following:&lt;/p&gt;

&lt;h2&gt;
  
  
  Create an Application
&lt;/h2&gt;

&lt;p&gt;We'll need a simple "hello-world" web server using Node.js, for the sake of example. You can, however, use any language (or Languages) you want when creating an application to run within Docker. You do not need to have any dependencies for the specific application or language installed on your computer, we will handle this using Docker&lt;/p&gt;

&lt;p&gt;For our purpose, create a file called &lt;code&gt;index.js&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requestListener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serverListeningCallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Server started&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestListener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serverListeningCallback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can see in the above on the last line that the application will listen on port 8080, just keep this in mind&lt;/p&gt;

&lt;p&gt;We don't need to run this file as yet, but if we want, we can run this with the following command from our working directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;node app.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At this point our working directory should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;working-directory
|__ index.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Create a Dockerfile
&lt;/h2&gt;

&lt;p&gt;There are a few steps that are the same for most &lt;code&gt;Dockerfile&lt;/code&gt;s you'll be building:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A Base Image that your container/image should use, in our case &lt;code&gt;node:12&lt;/code&gt;, which has &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt; preinstalled&lt;/li&gt;
&lt;li&gt;Copy all the code in the current (&lt;code&gt;.&lt;/code&gt;) directory&lt;/li&gt;
&lt;li&gt;Define your runtime port/ports (in the case of a web application)&lt;/li&gt;
&lt;li&gt;The command that will be run to start the application&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Any line starting with a &lt;code&gt;#&lt;/code&gt; is a comment, Docker will ignore these&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# step 1 - FROM baseImage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:12&lt;/span&gt;

&lt;span class="c"&gt;# step 2 - COPY source destination&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# step 3 - EXPOSE port&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;

&lt;span class="c"&gt;# step 4 - CMD stratupCommandArray&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "app.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At this point our working directory should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;working-directory
|__ index.js
|__ Dockerfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can build our image, based on the &lt;code&gt;Dockerfile&lt;/code&gt; using the following &lt;code&gt;docker&lt;/code&gt; command:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note the &lt;code&gt;.&lt;/code&gt; at the end of the command&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t my-docker-app .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above command can be broken down as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;docker build&lt;/code&gt; the command from the Docker CLI to build an image&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-t my-docker-app&lt;/code&gt; says what we want our image to be called, in the above &lt;code&gt;my-docker-app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.&lt;/code&gt; which is the directory in which the &lt;code&gt;Dockerfile&lt;/code&gt; is located, in our case our current directory&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can then run the image we just built like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -p 8080:8080 my-docker-app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;docker run&lt;/code&gt; is the command from the &lt;code&gt;Docker CLI&lt;/code&gt; to run a container&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p 8080:8080&lt;/code&gt; is our port mapping, it is ordered as &lt;code&gt;HOST_PORT:CONTAINER_PORT&lt;/code&gt; and allows us to say which port on our host we want to map to our container, the container port is the same port that our app listens on and is &lt;code&gt;EXPOSE&lt;/code&gt;d in the &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;my-docker-app&lt;/code&gt; is the image tag we would like to run&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Each time we change the app files for a container like above we need to rebuild the container before running, and that normally making changes to files during the image build or container run will not modify the original files on our computer&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that the application is running on port &lt;code&gt;8080&lt;/code&gt; you can open &lt;code&gt;http://localhost:8080&lt;/code&gt; in your browser and you should see your &lt;code&gt;Hello World&lt;/code&gt; app running&lt;/p&gt;

&lt;p&gt;When you're done with that you can go back to the terminal where the container was started and use &lt;code&gt;ctrl + c&lt;/code&gt; to stop the container&lt;/p&gt;

&lt;p&gt;If you've never used Docker before and have got everything running this far, congratulations! If you've got any questions you can comment below or hit me up on &lt;a href="https://twitter.com/not_nabeel"&gt;Twitter @not_nabeel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moving swiftly along&lt;/p&gt;

&lt;h1&gt;
  
  
  Development Containers
&lt;/h1&gt;

&lt;p&gt;So now that we understand a bit about containers and how we can go about using them in production, we'll look at why we may want to use them as a development environment&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Develop in a Container
&lt;/h2&gt;

&lt;p&gt;As developers, we are far too familiar with the "it runs on my machine" dilemma. Development environments can be wildly inconsistent between different developers or different operating systems, and ensuring that our development code runs easily on everyone's computer can be challenging&lt;/p&gt;

&lt;p&gt;Containers can help us to explicitly define our development environment, our application dependencies, what networking relationships, and (potentially) what other sibling applications need to be running in development, like databases, or other application tiers&lt;/p&gt;

&lt;p&gt;Visual Studio Code can help transport us into a container so that we work on our application in a well-defined environment, not just run our application within one while reducing the overall number of things we need to have installed on our computer&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Develop in a Container
&lt;/h2&gt;

&lt;p&gt;To develop in a Container using Visual Studio Code we will need to have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/desktop/#download-and-install"&gt;Docker Desktop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers"&gt;Visual Studio Code's Remote Containers Extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;What's important to note is that we don't need any of our application's runtime or development dependencies installed, like Node.js, these will all be handled by VSCode within our container&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To configure our project for running in a container we need to first open the project folder (the folder we used previously) in Visual Studio Code&lt;/p&gt;

&lt;h3&gt;
  
  
  Use an Existing Dockerfile
&lt;/h3&gt;

&lt;p&gt;Once open use the keyboard shortcut &lt;code&gt;ctrl + shift + p&lt;/code&gt; to open the Command Palette and search for &lt;code&gt;Remote-Containers: Add Development Container Configuration Files&lt;/code&gt; and click &lt;code&gt;enter&lt;/code&gt;, you will then have an option to use the existing Dockerfile &lt;code&gt;from Dockerfile&lt;/code&gt; which will generate a &lt;code&gt;.devcontainer/devcontainer.json&lt;/code&gt; file&lt;/p&gt;

&lt;p&gt;At this point our working directory should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;working-directory
|__ .devcontainer
|   |__ devcontainer.json
|
|__ index.js
|__ Dockerfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.devcontainer/devcontainer.json&lt;/code&gt; file that was created will contain the following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;devcontainer.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="c1"&gt;// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;// https://github.com/microsoft/vscode-dev-containers/tree/v0.128.0/containers/docker-existing-dockerfile&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Existing Dockerfile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Sets the run context to one level up instead of the .devcontainer folder.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dockerFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Dockerfile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Set *default* container specific settings.json values on container create.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"settings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"terminal.integrated.shell.linux"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Add the IDs of extensions you want installed when the container is created.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above file is the configuration for our development container, we can also allow VSCode to generate a Dockerfile which we'll look at later in the post&lt;/p&gt;

&lt;p&gt;We'll stick to our simple &lt;code&gt;Dockerfile&lt;/code&gt; for this post, but if you've got a different &lt;code&gt;Dockerfile&lt;/code&gt; when running your application in Production and Development then you may need a different file in the &lt;code&gt;dockerFile&lt;/code&gt; property below&lt;/p&gt;

&lt;p&gt;Now that we've got a starting point we can add a little to our configuration so that everything is just right:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Change the &lt;code&gt;name&lt;/code&gt; property to name our workspace (purely aesthetic)&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;forwardPorts&lt;/code&gt; property to expose our application port to our localhost network, be sure to add the &lt;code&gt;,&lt;/code&gt; after &lt;code&gt;"extensions":[]&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once we make the above changes we should have this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;devcontainer.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My Workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Sets the run context to one level up instead of the .devcontainer folder.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dockerFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Dockerfile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Set *default* container specific settings.json values on container create.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"settings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"terminal.integrated.shell.linux"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Add the IDs of extensions you want installed when the container is created.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Use 'forwardPorts' to make a list of ports inside the container available locally.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"forwardPorts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that we've configured our build container, use &lt;code&gt;ctrl + shift + p&lt;/code&gt; to open the Command Palette again and search for &lt;code&gt;Remote-Containers: Reopen in Container&lt;/code&gt; and click &lt;code&gt;enter&lt;/code&gt; which will build the container and set up an image with the following setup for us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Linked ports as defined in the &lt;code&gt;forwardPorts&lt;/code&gt; property&lt;/li&gt;
&lt;li&gt;Configure a VSCode development server inside the container so our editor can link to it&lt;/li&gt;
&lt;li&gt;Mount our system's file directory into the container so we can edit our files&lt;/li&gt;
&lt;li&gt;Does not run the &lt;code&gt;CMD&lt;/code&gt; command from our &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open a VSCode window linked to the container so we can start working with our code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that you're in the container you can edit your files and run it by doing the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use &lt;code&gt;ctrl + shift + p&lt;/code&gt; and then search for &lt;code&gt;Terminal: Create new Integrated Terminal&lt;/code&gt; and click &lt;code&gt;enter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;node app.js&lt;/code&gt; into the new Terminal window and click &lt;code&gt;enter&lt;/code&gt; to run our app.js file&lt;/li&gt;
&lt;li&gt;Navigate to &lt;code&gt;http://localhost:8080&lt;/code&gt; in your browser to view your running app&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point we've created a container to use as a development file and run our application, you can stop the application with &lt;code&gt;ctrl + c&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can switch from developing in a container back to your local environment with &lt;code&gt;ctrl + shift + p&lt;/code&gt; and searching for &lt;code&gt;Remote-Containers: Reopen locally&lt;/code&gt; and clicking &lt;code&gt;enter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now that we're back on our local environment (and not docker) we can look at the other way we can set up our project for VSCode&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a Preconfigured Dockerfile
&lt;/h3&gt;

&lt;p&gt;Visual Studio Code's Remote Containers Extension provides some pre-configured &lt;code&gt;Dockerfile&lt;/code&gt;s for common application or application framework types. One of the available preconfigured &lt;code&gt;Dockerfile&lt;/code&gt;s is for working on Node.js applications&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The preconfigured files usually just provide a starting point for applications and often you will need to modify these to suit your application, we don't need this for the application we're working on however&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To redefine our Docker development config, let's delete the &lt;code&gt;.devcontainer&lt;/code&gt; directory in our application and regenerate this&lt;/p&gt;

&lt;p&gt;We can regenerate the files needed with &lt;code&gt;ctrl + shift + p&lt;/code&gt;, and searching for &lt;code&gt;Remote-Containers: Add Development Container Configuration Files&lt;/code&gt; again, clicking &lt;code&gt;enter&lt;/code&gt; and then selecting the &lt;code&gt;From a predefined configuration definition&lt;/code&gt; option, and then selecting &lt;code&gt;Node.js 12&lt;/code&gt;, this should now create a &lt;code&gt;.devcontainer/devcontainer.json&lt;/code&gt; file as well as a new &lt;code&gt;.devcontainer/Dockerfile&lt;/code&gt; that we did not have previously, our working directory will now look like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;working-directory
|__ .devcontainer
|   |__ devcontainer.json  
|   |__ Dockerfile         # predefined dev container Dockerfile
|
|__ index.js
|__ Dockerfile             # our self-defined Dockerfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we look at the &lt;code&gt;devcontainer.json&lt;/code&gt; file we will see something similar to what we had before:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;devcontainer.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Node.js 12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dockerFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dockerfile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Set *default* container specific settings.json values on container create.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"settings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"terminal.integrated.shell.linux"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/bin/bash"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;// Add the IDs of extensions you want installed when the container is created.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"dbaeumer.vscode-eslint"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You may, however, note that the &lt;code&gt;dockerFile&lt;/code&gt; property is missing, this just means that VSCode will use the default &lt;code&gt;Dockerfile&lt;/code&gt; which has been created in the &lt;code&gt;.devcontainer&lt;/code&gt; directory&lt;/p&gt;

&lt;p&gt;We can go ahead and change the name if we want, we should also add the &lt;code&gt;forwardPorts&lt;/code&gt; option as we did previously:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;devcontainer.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&gt;...&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"forwardPorts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c1"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now looking at the &lt;code&gt;Dockerfile&lt;/code&gt; which defines the base development container:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; mcr.microsoft.com/vscode/devcontainers/javascript-node:0-12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is a bit different to ours because Visual Studio Code will handle the file copying and port exposing on its own for the development container. Note that this configuration can only be used for development and can't really be deployed as a production container. This type of setup is necessary if our development image and production image will be different (which they usually are)&lt;/p&gt;

&lt;p&gt;Now that the development container has been set-up, we can use &lt;code&gt;ctrl + shift + p&lt;/code&gt; and &lt;code&gt;Remote-Containers: Reopen in Container&lt;/code&gt; to open our development container, from here we can work on our application and run the application the same as we did before&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Method to Use
&lt;/h2&gt;

&lt;p&gt;We've looked at two different methods for configuring our development container, either of which can be used in any project. Below are my recommendations:&lt;/p&gt;

&lt;p&gt;If you've got an existing &lt;code&gt;Dockerfile&lt;/code&gt; and your development container can be the same as your production container, for things like simple &lt;code&gt;node.js&lt;/code&gt; or &lt;code&gt;python&lt;/code&gt; apps, and you don't want to maintain another &lt;code&gt;Dockerfile&lt;/code&gt; then this may be a quick solution to opt for&lt;/p&gt;

&lt;p&gt;Otherwise, if your development container needs to be different from your production one then it's probably easier to start with a predefined VSCode Container as a base and add in any development configuration you need to the &lt;code&gt;.devcontainer/Dockerfile&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lastly, if you don't have an existing &lt;code&gt;Dockerfile&lt;/code&gt; at all then I'd suggest using a predefined one so that even if it's not fully configured you've got a relatively good starting point, especially when working with more complex languages and frameworks as a custom &lt;code&gt;Dockerfile&lt;/code&gt; for these can be some work to configure&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;In this post, we've covered the basics of using Docker to run your applications in a container as well as how to define and build your images. We also looked at why we may want to use a container for development and how we can do this using Visual Studio Code&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;p&gt;For some more in-depth information on Docker and VSCode Development Containers you can look at the following resources:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://nabeelvalley.netlify.com/docs/"&gt;My General Docker Notes&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nabeelvalley.netlify.com/docs/containers-and-microservices/docker/"&gt;Docker Basics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nabeelvalley.netlify.com/docs/containers-and-microservices/build-an-express-app-with-mongo/"&gt;Express Application with MongoDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nabeelvalley.netlify.com/docs/containers-and-microservices/docker-multi-stage/"&gt;Multi-stage Builds&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/"&gt;Docker's Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/docs/remote/containers"&gt;VSCode's Remote Containers Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>docker</category>
      <category>containers</category>
      <category>vscode</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Code For Noobs</title>
      <dc:creator>Nabeel Valley</dc:creator>
      <pubDate>Thu, 21 May 2020 05:23:47 +0000</pubDate>
      <link>https://dev.to/nabeelvalley/code-for-noobs-2j26</link>
      <guid>https://dev.to/nabeelvalley/code-for-noobs-2j26</guid>
      <description>&lt;p&gt;So I've been meaning to write an introductory post about the basics of JavaScript for quite some time. A few weeks ago I managed to finally get something going on &lt;a href="https://twitter.com/not_nabeel/status/1255743195557888000"&gt;this Twitter thread (@not_nabeel)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's get into it&lt;/p&gt;

&lt;h1&gt;
  
  
  0. What is Programming
&lt;/h1&gt;

&lt;p&gt;Programming is our way of telling a computer to do things. This can be anything from checking our spelling to making trippy digital art&lt;/p&gt;

&lt;p&gt;The basics of programming are the same in most languages and doesn't involve much math or binary (&lt;code&gt;0010101&lt;/code&gt;) like a lot of people seem to think. Programming languages &lt;em&gt;usually&lt;/em&gt; make use of a very small subset of words and concepts of a normal human language like English&lt;/p&gt;

&lt;p&gt;The language I'm going to be using is called &lt;code&gt;JavaScript&lt;/code&gt; but many of these concepts are the same in most other programming languages&lt;/p&gt;

&lt;h1&gt;
  
  
  1. What is JavaScript?
&lt;/h1&gt;

&lt;p&gt;JavaScript is the language used to add interactivity to a website but it can also be used to do pretty much anything you like. JavaScript runs in all modern web browsers and can be accessed through your browser's developer tools, but it can also be used on other devices using something like &lt;a href="https://twitter.com/nodejs"&gt;@nodejs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For our purposes though, we don't need to worry too much about how that all works right now. To get started we'll be using tools like &lt;a href="https://twitter.com/CodePen"&gt;@CodePen&lt;/a&gt;, &lt;a href="https://twitter.com/replit"&gt;@replit&lt;/a&gt; and &lt;a href="https://twitter.com/glitch"&gt;@glitch&lt;/a&gt; which give you text editor and a place to run your code&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You'll see some code samples in the post as you go along, the interactive examples can be found &lt;a href="https://nabeelvalley.netlify.app/blog/2020/17-05/code-for-noobs/"&gt;on my website&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  2. Text Data
&lt;/h1&gt;

&lt;p&gt;In a program, we can store different types of data (known as "data types")&lt;/p&gt;

&lt;p&gt;When we store text we use a data type called &lt;code&gt;string&lt;/code&gt;. In JavaScript a string is just text surrounded in either double quotes, single quotes, or &lt;code&gt;`these things`&lt;/code&gt; (which are known as backticks):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i am text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i am also text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="s2"&gt;`me too.`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="s2"&gt;`unlike the others,
  i can b
multiple lines
lllooonnnggg
    and have random spaces`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  3. Variables
&lt;/h1&gt;

&lt;p&gt;If we want to keep our data for use at a later stage we need to give it a name, otherwise how do we know what data we're trying to use right? To give a piece of data (or text, in our case) a name we create a &lt;code&gt;variable&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We create a variable using &lt;code&gt;let&lt;/code&gt; or &lt;code&gt;const&lt;/code&gt; along with a variable name and the data that we want to give the name to  :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// this code shouldn't do anything if you run it&lt;/span&gt;
&lt;span class="c1"&gt;// we are just creating some variables&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myOtherText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bye World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We use &lt;code&gt;let&lt;/code&gt; for data whose data may change and &lt;code&gt;const&lt;/code&gt; for data whose data won't you can remember this like: &lt;code&gt;const = constant&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that it is also possible to use the keyword &lt;code&gt;var&lt;/code&gt; to create a variable. This is something that is left over from older versions of JavaScript and can have some effects that are better to just avoid (if you're interested you can read &lt;a href="https://medium.com/@josephcardillo/the-difference-between-function-and-block-scope-in-JavaScript-4296b2322abe"&gt;this article about how it impacts variable scope&lt;/a&gt; but it is a bit of a more challenging concept to understand)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When creating a variable, there are a few rules we need to follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Variable names &lt;strong&gt;must not&lt;/strong&gt; contain spaces or stuff like &lt;code&gt;!@#%%^&amp;amp;\*()&lt;/code&gt;, underscores and dollar signs are okay though&lt;/li&gt;
&lt;li&gt;Variable names &lt;strong&gt;must not&lt;/strong&gt; be a word the language has set aside for something else. e.g &lt;code&gt;const&lt;/code&gt; or &lt;code&gt;let&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Variable names &lt;strong&gt;must not&lt;/strong&gt; start with a number&lt;/li&gt;
&lt;li&gt;Variable names &lt;strong&gt;should be&lt;/strong&gt; descriptive. while names like "x" and "blah" are allowed, if they have no meaning in the context it's better to opt for something people will understand&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  4. Printing Data
&lt;/h1&gt;

&lt;p&gt;Languages have ways we can show data to a user (or programmer). In JavaScript this is the "console.log" function. We'll discuss functions later on but for now know that when we give them data, and they do stuff&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// print the data&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bob Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;//prints -&amp;gt; Bob Smith&lt;/span&gt;

&lt;span class="c1"&gt;// print a variable&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jenny&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jenny Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jenny&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// prints -&amp;gt; Jenny Smith&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  5. Numbers
&lt;/h1&gt;

&lt;p&gt;Numbers are another type of data in JavaScript, to store a number we can just write the number. using numbers we can also do things like getting fat or running from the po-lice&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;-&lt;/code&gt; is plus&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-&lt;/code&gt; is minus&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;*&lt;/code&gt; is multiply&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/&lt;/code&gt; is divide
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myWeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;food&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myNewWeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myWeight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;food&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myNewWeight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; 250&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myWeightAfterRunnin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myWeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;myWeight&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myWeightAfterRunnin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; 80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But, JavaScript lets us add do maths with anything. so maybe like - don't do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dontDoThis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apple&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pineapple&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dontDoThis&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; NaN (Not a Number)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  6. Arrays
&lt;/h1&gt;

&lt;p&gt;Arrays are how we store a set of data. an array can have different data types in it, but usually, we want to be storing the same stuff in an array. we make an array by wrapping our items in &lt;code&gt;[ ]&lt;/code&gt; and separating each item  with a comma (&lt;code&gt;,&lt;/code&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFriends&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;don't&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;have&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;any&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thingsToRemember&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uhmm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;idk, i guess i forgot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multipleLines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;arrays don't have to be&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;on a single&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we want to get a specific element in an array we can use the variable name with the index (position) of the element. the index starts at 0. we will get &lt;code&gt;undefined&lt;/code&gt; (I'll explain this in a bit) if we try to get a value at an index that does not exist&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zeroeth index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;first index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;second index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;third index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; zeroeth index&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; first index&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; second index&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; third index&lt;/span&gt;

&lt;span class="c1"&gt;// indexes that do not exist in our array&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; undefined&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  7. Booleans
&lt;/h1&gt;

&lt;p&gt;So far we've looked at strings and numbers, we have an even more basic data type called a boolean. a boolean is a value that can either be true or false. when creating a variable for a boolean we do not wrap the value in quotes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myTrueBool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myFalseBool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myTrueBool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myFalseBool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  8. Complex Data
&lt;/h1&gt;

&lt;p&gt;If we want to store data that are more complex than the ones we've seen above, we can make use of "objects". use &lt;code&gt;{ }&lt;/code&gt; around our data to group more basic data. these use &lt;code&gt;keys&lt;/code&gt; as names for values in the object&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jenny&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jenny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;idk, can't ask a woman that&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;favouriteBooks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;To not kill a Mockingbird&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Why are books so voilent, yoh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// we can get specific values using their keys&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jennyName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jenny&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jennyBooks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jenny&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;favouriteBooks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  9. Undefined and Null
&lt;/h1&gt;

&lt;p&gt;the values &lt;code&gt;undefined&lt;/code&gt; and &lt;code&gt;null&lt;/code&gt; have a special meaning.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;undefined&lt;/code&gt; is a representation for a variable that does not have a value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;null&lt;/code&gt; is a value of "nothing"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What's wrong with chocolate? &lt;code&gt;null&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;What's a &lt;em&gt;flobuir&lt;/em&gt;? &lt;code&gt;undefined&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  10. Functions
&lt;/h1&gt;

&lt;p&gt;Functions are a way we can group code for a specific set of instructions, usually with some end purpose. In JavaScript we define a function in one of two ways: using the word &lt;code&gt;function&lt;/code&gt; or with the &lt;code&gt;fat arrow syntax&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// using the "function" keyword&lt;/span&gt;
&lt;span class="c1"&gt;// this creates a variable called "myFunc1"&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;myFunc&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stuff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I am Function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// we can also create the variable using&lt;/span&gt;
&lt;span class="c1"&gt;// "let" or "const" like we do for other variables&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myLetFunc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stuff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I am another Function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// fat arrow function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFatFunc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Phat Funk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// single line fat-arrow functions don't need the {}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mySingleLineFunct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;single line&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To use a function we simply write the name of the function and then add &lt;code&gt;()&lt;/code&gt; at the end, provided the function doesn't take any data (also known as &lt;code&gt;parameters&lt;/code&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sayHello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// "call" the function&lt;/span&gt;
&lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// prints -&amp;gt; Hello&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sayBye&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BYEE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// "call" the function&lt;/span&gt;
&lt;span class="nx"&gt;sayBye&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// prints -&amp;gt; BYEE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Remember earlier I said that functions take data and do stuff? For us to give a function data we need to tell it what variables to store that data as when we call it. We do this by having the data in the &lt;code&gt;()&lt;/code&gt; when we create (or 'declare') our function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="c1"&gt;// use the function&lt;/span&gt;
&lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; Hello Bob&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sayBye&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bye &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;//use the function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jenny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;sayBye&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; Bye Jenny&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When computers are following our code they do so from the top down, so the first line is handled by the computer before the second. the second before the third, etc. functions are a way for us to reuse code that was written on a line higher up in our code. You may notice that we use the variable &lt;code&gt;name&lt;/code&gt; in a lot of different places above. this uses &lt;code&gt;scope&lt;/code&gt; and broadly means any variable name created in a function (or pretty much anywhere between &lt;code&gt;{ }&lt;/code&gt;) is only available within that section&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Scope complicated, you can read more about it &lt;a href="https://scotch.io/tutorials/understanding-scope-in-JavaScript"&gt;here&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Functions can also take multiple parameters, this is done by listing the parameters between the () and separating them by commas. the order that we list them when we create our function is the same as the order we need to put them when using the function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sayBye&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bye &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// use the function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jennyName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jenny&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jennySurname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;sayBye&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jennyName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jennySurname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; Bye Jenny Smith&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Functions are also able to give us back a value after doing some stuff. They do this by using the &lt;code&gt;return&lt;/code&gt; keyword which tells it what to give back. A function stops processing when it sees the keyword &lt;code&gt;return&lt;/code&gt; - anything after it in a function is ignored&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;num1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;num2&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mySum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;addNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mySum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// print -&amp;gt; 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;That's it for now, I'll definitely be updating this post/series as things are added over on &lt;a href="https://nabeelvalley.netlify.app/blog/2020/17-05/code-for-noobs/"&gt;My Blog&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nabeel Valley&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>programming</category>
      <category>introduction</category>
      <category>functions</category>
      <category>variables</category>
    </item>
    <item>
      <title>The Gatsby Migration, pt.1 - Setting the Scene</title>
      <dc:creator>Nabeel Valley</dc:creator>
      <pubDate>Tue, 21 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/nabeelvalley/the-gatsby-migration-pt-1-setting-the-scene-22l7</link>
      <guid>https://dev.to/nabeelvalley/the-gatsby-migration-pt-1-setting-the-scene-22l7</guid>
      <description>&lt;h1&gt;
  
  
  Contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;The React App&lt;/li&gt;
&lt;li&gt;Hard Coded Pages&lt;/li&gt;
&lt;li&gt;Dynamic Post Page&lt;/li&gt;
&lt;li&gt;App Layout and Routes&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Lately I've been a little concerned with my current SPA approach on my personal site as well as a few others. More specifically the high initial load time due to the calls to the backend to retrieve content&lt;/p&gt;

&lt;p&gt;With the aim of solving this problem I've spent a lot of time looking at and playing with Static Site Generators.Foreword: they're all a lot more complicated than one would think&lt;/p&gt;

&lt;p&gt;So for a static site the "static" content only changes so often, based on this we can generate page content with the data we're planning to load in - that's what we're going to try to do&lt;/p&gt;

&lt;p&gt;Now we'll be starting off with a React app generated with &lt;code&gt;create-react-app&lt;/code&gt; so that we can have a starting point for our Gatsby site as well as understanding how we can approach some of the challenges when switching over to a site generator like Gatsby&lt;/p&gt;

&lt;p&gt;For the sake of completeness, this series will be broken into four posts covering the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Creating the initial React App&lt;/strong&gt; (This post)&lt;/li&gt;
&lt;li&gt;&lt;a href="//../01-02/gatsby-migration-2"&gt;Rendering the "Dumb" pages with Gatsby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="//../15-03/gatsby-migration-3"&gt;Rendering the "Smart" page with Gatsby&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The React App
&lt;/h2&gt;

&lt;p&gt;First we're going to be starting off with a new React app that we will work on changing into a Gatsby one parts &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;3&lt;/code&gt;, we'll then focus on using plugins to enhance our content in &lt;code&gt;4&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For this part we'll build a basic React app that has the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Two "hard-coded" pages and a 404 page&lt;/li&gt;
&lt;li&gt;A dynamic page with an API call to retrieve data&lt;/li&gt;
&lt;li&gt;Overall app layout with child routes for &lt;code&gt;1&lt;/code&gt; - &lt;code&gt;3&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To get started, we'll create a fresh React App:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app gatsby-to-be

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



&lt;p&gt;And add the &lt;code&gt;react-router&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add react-router-dom

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



&lt;p&gt;Running this command should set up the application, if you don't know much about React I'd suggest taking a look at &lt;a href="https://create-react-app.dev/docs/getting-started"&gt;the documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next &lt;code&gt;cd gatsby-to-be&lt;/code&gt; and run &lt;code&gt;yarn start&lt;/code&gt;, you should be able to visit the application in your browser at &lt;code&gt;http://localhost:3000/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Looking at the generated files we have a &lt;code&gt;public&lt;/code&gt; directory with some icons, an &lt;code&gt;index.html&lt;/code&gt; file into which our React application will run once built, and a &lt;code&gt;src&lt;/code&gt; directory that has the application code. The &lt;code&gt;index.js&lt;/code&gt; file is what loads the application into the DOM and the &lt;code&gt;App.js&lt;/code&gt; file which is the main component for our application&lt;/p&gt;

&lt;h2&gt;
  
  
  Hard Coded Pages
&lt;/h2&gt;

&lt;p&gt;We will create the following three hard-coded pages in the &lt;code&gt;src/pages&lt;/code&gt; directory&lt;/p&gt;

&lt;p&gt;These pages are just React components that we will assign Routes to.&lt;/p&gt;

&lt;p&gt;The pages we are using are known as &lt;code&gt;functional&lt;/code&gt; components because they are javascript functions that return JSX&lt;/p&gt;

&lt;p&gt;If we intend to use JSX in a file we need to ensure that we import &lt;code&gt;React&lt;/code&gt;. The other component we are importing is the &lt;code&gt;Link&lt;/code&gt; component which is a lot like a normal HTML &lt;code&gt;a&lt;/code&gt; tag but with some special functionality to make the client-side navigation work&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Blog.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react"
import { Link } from "react-router-dom"

const Blog = () =&amp;gt; (
  &amp;lt;div className="Blog"&amp;gt;
    &amp;lt;h1&amp;gt;Blog&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;This is the Blog page&amp;lt;/p&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;Link to="/blog/post-1"&amp;gt;Post 1&amp;lt;/Link&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;Link to="/blog/post-2"&amp;gt;Post 2&amp;lt;/Link&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
)

export default Blog

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



&lt;p&gt;Additionally we have the &lt;code&gt;Home.js&lt;/code&gt; and &lt;code&gt;NotFound.js&lt;/code&gt; files which are similar to the &lt;code&gt;Blog.js&lt;/code&gt; file we created&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;Home.js&lt;/code&gt;
&lt;/h1&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react"

const Home = () =&amp;gt; (
  &amp;lt;div className="Home"&amp;gt;
    &amp;lt;h1&amp;gt;Home&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;This is the Home page&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
)

export default Home

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



&lt;h1&gt;
  
  
  &lt;code&gt;NotFound.js&lt;/code&gt;
&lt;/h1&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react"

const NotFound = () =&amp;gt; (
  &amp;lt;div className="NotFound"&amp;gt;
    &amp;lt;h1&amp;gt;404&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;Page Not Found&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
)

export default NotFound

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



&lt;h2&gt;
  
  
  Dynamic Post Page
&lt;/h2&gt;

&lt;p&gt;Next up we'll create a component that can render out content for a blog post. This will consist of a few &lt;code&gt;hooks&lt;/code&gt; which are react functions that we can use to sort of control the data in a function&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Post&lt;/code&gt; component will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Display a loading indicator initially&lt;/li&gt;
&lt;li&gt;Figure out what post we're trying to render based on the URL&lt;/li&gt;
&lt;li&gt;Retrieve a JSON file from the &lt;code&gt;public&lt;/code&gt; directory based&lt;/li&gt;
&lt;li&gt;Set the component state after reading the file&lt;/li&gt;
&lt;li&gt;Display the content from the file in a JSX template&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;useState&lt;/code&gt; hook is used to initialize the state the component, in this case using the &lt;code&gt;hasError&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; variables, as well as providing the functions necessary for updating those in the form of &lt;code&gt;setHasError&lt;/code&gt; and &lt;code&gt;setData&lt;/code&gt; respectively&lt;/p&gt;

&lt;p&gt;We use &lt;code&gt;fetch&lt;/code&gt; in the &lt;code&gt;useEffect&lt;/code&gt; hook to retrieve the data from the &lt;code&gt;public&lt;/code&gt; directory. The &lt;code&gt;useEffect&lt;/code&gt; hook allows us to pass a function that will be called to update side effects. The second input, in our case &lt;code&gt;[]&lt;/code&gt; is the array of objects that, when are changed, we want the hook to run - since we only want it to run once and don't care about any other state changes we pass in an empty array for this value&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Post.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

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

const Post = ({ match }) =&amp;gt; {
  const slug = match.params.slug

  const [hasError, setHasError] = useState(false)
  const [data, setData] = useState(null)

  useEffect(() =&amp;gt; {
    const fetchData = async () =&amp;gt; {
      try {
        const res = await fetch(`/posts/${slug}.json`)
        const json = await res.json()
        setData(json)
      } catch (error) {
        console.log(error.toString())
        setHasError(true)
      }
    }

    fetchData()
  }, [])

  return (
    &amp;lt;div className="Post"&amp;gt;
      &amp;lt;p&amp;gt;
        This is the &amp;lt;code&amp;gt;{slug}&amp;lt;/code&amp;gt; page
      &amp;lt;/p&amp;gt;
      {data ? (
        &amp;lt;div className="content"&amp;gt;
          &amp;lt;h1&amp;gt;{data.title}&amp;lt;/h1&amp;gt;
          &amp;lt;p&amp;gt;{data.body}&amp;lt;/p&amp;gt;
          &amp;lt;img src={data.image} alt="" /&amp;gt;
        &amp;lt;/div&amp;gt;
      ) : hasError ? (
        &amp;lt;div className="error"&amp;gt;
          &amp;lt;h1&amp;gt;Error&amp;lt;/h1&amp;gt;
          &amp;lt;p&amp;gt;{hasError}&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      ) : (
        &amp;lt;p&amp;gt;Loading .. &amp;lt;/p&amp;gt;
      )}
    &amp;lt;/div&amp;gt;
  )
}

export default Post

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



&lt;p&gt;In the above component we're making use of the following pattern to decide what to render conditionally:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If the data is loaded then show the data&lt;/li&gt;
&lt;li&gt;Else if there is an error then show the error data&lt;/li&gt;
&lt;li&gt;Otherwise show a loading message&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The way we are rendering the &lt;code&gt;Post&lt;/code&gt; component with a parameter for &lt;code&gt;match&lt;/code&gt;. The &lt;code&gt;match&lt;/code&gt; parameter will be passed in as a &lt;code&gt;prop&lt;/code&gt; from the &lt;code&gt;Router&lt;/code&gt; that we will configure next, this allows us to use the &lt;code&gt;slug&lt;/code&gt; from the URL to retrieve the content for the page&lt;/p&gt;

&lt;p&gt;The two data files we have to pull content from in the &lt;code&gt;public/posts&lt;/code&gt; directory are &lt;code&gt;post-1.json&lt;/code&gt; and &lt;code&gt;post-2.json&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;post-1.json&lt;/code&gt;
&lt;/h1&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "title": "Post 1",
  "body": "Hello world, how are you",
  "image": "/posts/1.jpg"
}

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



&lt;h1&gt;
  
  
  &lt;code&gt;post-2.json&lt;/code&gt;
&lt;/h1&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "title": "Post 2",
  "body": "Hello world, I am fine",
  "image": "/posts/2.jpg"
}

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



&lt;blockquote&gt;
&lt;p&gt;The images &lt;code&gt;posts/1.jpg&lt;/code&gt; and &lt;code&gt;posts/2.jpg&lt;/code&gt; can also just be any images in that directory&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  App Layout and Routes
&lt;/h2&gt;

&lt;p&gt;Lastly, we'll specify our application layout with the relevant routes in the &lt;code&gt;App.js&lt;/code&gt; file, referencing the components we have created, we do this using the &lt;code&gt;BrowserRouter&lt;/code&gt;. When we switch the project over to a Gatsby one, the &lt;code&gt;App.js&lt;/code&gt; file will be converted into our &lt;code&gt;Layout&lt;/code&gt; component to wrap our different pages&lt;/p&gt;

&lt;p&gt;We use the &lt;code&gt;Router&lt;/code&gt; component and the page inside of it, this essentially handles Routing via the &lt;code&gt;Link&lt;/code&gt; components. Next we have a &lt;code&gt;div&lt;/code&gt; as a wrapper for our component as well as a &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;nav&lt;/code&gt;, and &lt;code&gt;main&lt;/code&gt; tags to organise the page&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Route&lt;/code&gt; component takes in the component that we would like to display for a given route, and the &lt;code&gt;Switch&lt;/code&gt; helps us to ensure that only route is actively being fisplayed at a time. The &lt;code&gt;Switch&lt;/code&gt; will navigate from the first to last &lt;code&gt;Route&lt;/code&gt; and render the first one that matches the given &lt;code&gt;path&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Fow now, our &lt;code&gt;App.js&lt;/code&gt; file is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react"
import "./App.css"
import { BrowserRouter as Router, Link, Switch, Route } from "react-router-dom"
import Home from "./pages/Home"
import Blog from "./pages/Blog"
import Post from "./pages/Post"
import NotFound from "./pages/NotFound"

const App = () =&amp;gt; (
  &amp;lt;Router&amp;gt;
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;header&amp;gt;
        &amp;lt;nav&amp;gt;
          &amp;lt;h1&amp;gt;My Website Title&amp;lt;/h1&amp;gt;
          &amp;lt;Link to="/"&amp;gt;Home&amp;lt;/Link&amp;gt;
          &amp;lt;Link to="/blog"&amp;gt;Blog&amp;lt;/Link&amp;gt;
        &amp;lt;/nav&amp;gt;
      &amp;lt;/header&amp;gt;
      &amp;lt;main&amp;gt;
        &amp;lt;Switch&amp;gt;
          &amp;lt;Route exact path="/" component={Home}&amp;gt;&amp;lt;/Route&amp;gt;

          &amp;lt;Route exact path="/blog" component={Blog}&amp;gt;&amp;lt;/Route&amp;gt;

          &amp;lt;Route exact path="/blog/:slug" component={Post}&amp;gt;&amp;lt;/Route&amp;gt;

          &amp;lt;Route path="/*" component={NotFound}&amp;gt;&amp;lt;/Route&amp;gt;
        &amp;lt;/Switch&amp;gt;
      &amp;lt;/main&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/Router&amp;gt;
)

export default App

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



&lt;p&gt;In the above component we can see that where we are rendering the &lt;code&gt;Post&lt;/code&gt; component we have a parameter in the route called &lt;code&gt;slug&lt;/code&gt;, this parameter will be passed in to the &lt;code&gt;Post&lt;/code&gt; component as part of the &lt;code&gt;match&lt;/code&gt; object&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;We have built a fairly simple application that makes use of both static and data-based pages, we have also tied all of these together using the &lt;code&gt;App&lt;/code&gt; component and a &lt;code&gt;Router&lt;/code&gt; with the following routes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;/&lt;/code&gt; which will render the &lt;code&gt;Home&lt;/code&gt; component&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/blog&lt;/code&gt; which will render the &lt;code&gt;Blog&lt;/code&gt; component&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/blog/:slug&lt;/code&gt; which will render the &lt;code&gt;Post&lt;/code&gt; component and retrieve the data based on the given &lt;code&gt;slug&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/*&lt;/code&gt; which will match any other routes and render the &lt;code&gt;NotFound&lt;/code&gt; component&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the next post we're going to look at how to take what we have so far and transform this application into a Gatsby one, but for now it may be useful to think about what kind of steps we may need to take if we'd like to make this a static website based on the way our current routes work&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nabeel Valley&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    </item>
    <item>
      <title>Intro to F# Web APIs</title>
      <dc:creator>Nabeel Valley</dc:creator>
      <pubDate>Wed, 30 Oct 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/nabeelvalley/intro-to-f-web-apis-558b</link>
      <guid>https://dev.to/nabeelvalley/intro-to-f-web-apis-558b</guid>
      <description>&lt;p&gt;So we're going to be taking a bit of a look on how you can go about building your first F# Web API using .NET Core. I'm going to cover a lot of the basics, a lot of which should be familiar to anyone who has worked with .NET Web Applications and F# in general.&lt;/p&gt;

&lt;p&gt;Along the way I'm also going to go through some important concepts that I feel are maybe not that clear from a documentation perspective that are actually super relevant to using this F# in a real-life context&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're totally new to F# though you may want to take a look at &lt;a href="https://fsharpforfunandprofit.com/"&gt;F# for Fun and Profit&lt;/a&gt; or my personal quick reference documentation over on &lt;a href="https://github.com/nabeelvalley/Docs/blob/master/dotnet/intro-to-fs.md"&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Assuming you've got the .NET Core SDK with F# installed, you can simply create a new project with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet new webapi --language F# --name FSharpWebApi

code .\FSharpWebApi

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



&lt;blockquote&gt;
&lt;p&gt;Alternatively, if you're feeling a little &lt;em&gt;unexperimental&lt;/em&gt; you can use the Visual Studio project creation wizard, psshhtt&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once you have the project open you can run the following command to launch the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet run

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



&lt;p&gt;Which should start the application on &lt;code&gt;https://localhost:5001&lt;/code&gt; and &lt;code&gt;http://localhost:5000&lt;/code&gt;, you can see the current existing endpoint at &lt;code&gt;/weatherforecast&lt;/code&gt;, this is handled by the &lt;code&gt;Controllers/WeatherForecastController.fs&lt;/code&gt; file&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking Around
&lt;/h2&gt;

&lt;p&gt;Looking at the structure of the project files you should see the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FSharpWebApi
│ appsettings.Development.json
│ appsettings.json
│ FSharpWebApi.fsproj
│ Program.fs
│ Startup.fs
│ WeatherForecast.fs
│
├───Controllers
│ WeatherForecastController.fs
│
└───Properties
        launchSettings.json

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



&lt;p&gt;So, mostly we see the typical Web API stuff that we'd expect for a C# project such as the &lt;code&gt;startup&lt;/code&gt; and &lt;code&gt;program&lt;/code&gt; files. In F# they serve pretty much the same purpose.&lt;/p&gt;

&lt;p&gt;Looking at the &lt;code&gt;Program.fs&lt;/code&gt; file we can see that it contains the &lt;code&gt;main&lt;/code&gt; function and configures the Web Host, next we can see that the &lt;code&gt;Startup.fs&lt;/code&gt; file contains the usual configuration methods. We should note that the method calls within these functions are piped to an &lt;code&gt;ignore&lt;/code&gt; so the the functions to not return their respective &lt;code&gt;Builders&lt;/code&gt; as this will break the application&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Program.fs&lt;/code&gt; and &lt;code&gt;Startup.fs&lt;/code&gt; files can be seen below&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Program.fs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace FSharpWebApi

module Program =
    let exitCode = 0

    let CreateHostBuilder args =
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(fun webBuilder -&amp;gt;
                webBuilder.UseStartup&amp;lt;Startup&amp;gt;() |&amp;gt; ignore
            )

    [&amp;lt;EntryPoint&amp;gt;]
    let main args =
        CreateHostBuilder(args).Build().Run()

        exitCode

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



&lt;p&gt;&lt;code&gt;Startup.fs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace FSharpWebApi

type Startup private () =
    new (configuration: IConfiguration) as this =
        Startup() then
        this.Configuration &amp;lt;- configuration

    // This method gets called by the runtime. Use this method to add services to the container.
    member this.ConfigureServices(services: IServiceCollection) =
        // Add framework services.
        services.AddControllers() |&amp;gt; ignore

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    member this.Configure(app: IApplicationBuilder, env: IWebHostEnvironment) =
        if (env.IsDevelopment()) then
            app.UseDeveloperExceptionPage() |&amp;gt; ignore

        app.UseHttpsRedirection() |&amp;gt; ignore
        app.UseRouting() |&amp;gt; ignore

        app.UseAuthorization() |&amp;gt; ignore

        app.UseEndpoints(fun endpoints -&amp;gt;
            endpoints.MapControllers() |&amp;gt; ignore
            ) |&amp;gt; ignore

    member val Configuration : IConfiguration = null with get, set

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



&lt;p&gt;Next we have the &lt;code&gt;FSharpWebApi.fsproj&lt;/code&gt; file which contains references to the relevant code files. It's important to note that the order of the files in the &lt;code&gt;ItemGroup&lt;/code&gt; specifies the order that files depend on each other. Lower files depend on files higher up&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Project Sdk="Microsoft.NET.Sdk.Web"&amp;gt;

  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;TargetFramework&amp;gt;netcoreapp3.0&amp;lt;/TargetFramework&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;

  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;Compile Include="WeatherForecast.fs" /&amp;gt;
    &amp;lt;Compile Include="Controllers/WeatherForecastController.fs" /&amp;gt;
    &amp;lt;Compile Include="Startup.fs" /&amp;gt;
    &amp;lt;Compile Include="Program.fs" /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;

&amp;lt;/Project&amp;gt;

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



&lt;p&gt;Lastly, we have a controller that resides in the &lt;code&gt;Controllers/WeatherForecastController.fs&lt;/code&gt; with its types defined in the &lt;code&gt;WeatherForecast.fs&lt;/code&gt; file. Looking at the &lt;code&gt;WeatherForecast.fs&lt;/code&gt; file we can see that the type has a few simple properties and one function&lt;/p&gt;

&lt;p&gt;&lt;code&gt;WeatherForecast.fs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace FSharpWebApi

open System

type WeatherForecast =
    { Date: DateTime
      TemperatureC: int
      Summary: string }

    member this.TemperatureF =
        32 + (int (float this.TemperatureC / 0.5556))

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



&lt;p&gt;Next up, we can see the controller which contains a single &lt;code&gt;GET&lt;/code&gt; endpoint which delivers a random array of weather forecasts. Here we can see a few different things. First, the namespace is &lt;code&gt;FSharpWebApi.Controllers&lt;/code&gt;, this pretty much follows the .NET standard of the Namespace being related to the Folder name, we can also see the &lt;code&gt;ApiController&lt;/code&gt; attribute that adds &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-3.0#apicontroller-attribute"&gt;some useful functionality&lt;/a&gt; for basic API handling and the &lt;code&gt;Route&lt;/code&gt; attribute that states the controller route&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;WeatherForecastController&lt;/code&gt; type defines the controller and that it inherits from &lt;code&gt;ControllerBase&lt;/code&gt;, additionally the constructor requires the &lt;code&gt;ILogger&lt;/code&gt; service which will be provided by DependencyInjection&lt;/p&gt;

&lt;p&gt;Lastly, looking at the &lt;code&gt;__Get&lt;/code&gt; method we can see the &lt;code&gt;HttpGet&lt;/code&gt; attribute that specifies that this is a Get Method, and the &lt;code&gt;__&lt;/code&gt; shows that we don't care about references to the function's &lt;code&gt;this&lt;/code&gt;, and the return type for the function is an &lt;code&gt;array&lt;/code&gt; of &lt;code&gt;WeatherForecast&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;WeatherForecastController.fs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace FSharpWebApi.Controllers

open System
open Microsoft.AspNetCore.Mvc
open Microsoft.Extensions.Logging
open FSharpWebApi

[&amp;lt;ApiController&amp;gt;]
[&amp;lt;Route("[controller]")&amp;gt;]
type WeatherForecastController (logger : ILogger&amp;lt;WeatherForecastController&amp;gt;) =
    inherit ControllerBase()

    let summaries = [| "Freezing"; "Bracing"; "Chilly"; "Cool"; "Mild"; "Warm"; "Balmy"; "Hot"; "Sweltering"; "Scorching" |]

    [&amp;lt;HttpGet&amp;gt;]
    member __.Get() : WeatherForecast[] =
        let rng = System.Random()
        [|
            for index in 0..4 -&amp;gt;
                { Date = DateTime.Now.AddDays(float index)
                  TemperatureC = rng.Next(-20,55)
                  Summary = summaries.[rng.Next(summaries.Length)] }
        |]

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



&lt;h2&gt;
  
  
  Creating a Controller
&lt;/h2&gt;

&lt;p&gt;Creating a new controller is not particularly complex given that we have the above as a starting point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Handler
&lt;/h2&gt;

&lt;p&gt;We're going to create a handler that is able to return a simple message for an &lt;code&gt;even&lt;/code&gt; param, and a &lt;code&gt;404&lt;/code&gt; for a &lt;code&gt;odd&lt;/code&gt; param in order to look at how we can return actual response codes in cases where we aren't always able to return something of a constant type&lt;/p&gt;

&lt;p&gt;First, we can create a &lt;code&gt;Controllers/MessageController.fs&lt;/code&gt; file with just some basic scaffolding to start with. We'll define a &lt;code&gt;Get&lt;/code&gt; controller that just returns the &lt;code&gt;id&lt;/code&gt; it receives as a route param multiplied by two if the the result &lt;code&gt;shouldDouble&lt;/code&gt; param is set to &lt;code&gt;true&lt;/code&gt;. Additionally we can see the &lt;code&gt;sprint&lt;/code&gt; function used to format the output as a string&lt;/p&gt;

&lt;p&gt;Before we can add the data to the actual controller we need to add the &lt;code&gt;&amp;lt;Compile Include="Controllers/MessageController.fs" /&amp;gt;&lt;/code&gt; to the &lt;code&gt;ItemGroup&lt;/code&gt; in the &lt;code&gt;FSharpWebApi.fsproj&lt;/code&gt; file, :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FSharpWebApi.fsproj&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;Compile Include="WeatherForecast.fs" /&amp;gt;
    &amp;lt;Compile Include="Controllers/WeatherForecastController.fs" /&amp;gt;
    &amp;lt;Compile Include="Controllers/MessageController.fs" /&amp;gt;
    &amp;lt;Compile Include="Startup.fs" /&amp;gt;
    &amp;lt;Compile Include="Program.fs" /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;

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



&lt;p&gt;And then we can put together the controller in the &lt;code&gt;MessageController.fs&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MessageController.fs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace FSharpWebApi.Controllers

open Microsoft.AspNetCore.Mvc
open Microsoft.Extensions.Logging

[&amp;lt;ApiController&amp;gt;]
[&amp;lt;Route("[controller]")&amp;gt;]
type MessageController (logger : ILogger&amp;lt;MessageController&amp;gt;) =
    inherit ControllerBase()

    [&amp;lt;HttpGet("{id}")&amp;gt;]
    member __.Get (id : int, shouldDouble : bool) : string=
        logger.LogInformation("I am a controller")

        let result =
            match shouldDouble with
            | true -&amp;gt; id * 2
            | false -&amp;gt; id

        sprintf "Hello %d" result

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



&lt;p&gt;From the function's signature we can see that it has an &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;shouldDouble&lt;/code&gt; values as inputs and that it returns a string. We have made these explicit however if we were to leave them out it would be fine too as F# would be able to infer the types, see that below:&lt;/p&gt;

&lt;p&gt;We can open the following URLs in our browser and should be able to open the &lt;code&gt;/message/3&lt;/code&gt; and &lt;code&gt;/message/3?shouldDouble=true&lt;/code&gt; routes and see &lt;code&gt;hello 3&lt;/code&gt; and &lt;code&gt;hello 6&lt;/code&gt; respectively&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that if not specified the handler inputs will try to be parsed from the body&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, if we would want to update this to return some sort of general HTTP Response Code when a user sends some kind of input, for example if the &lt;code&gt;result&lt;/code&gt; is 4, we will need to modify the function such that we are able to reference the &lt;code&gt;this&lt;/code&gt; and the return type of the function is now an &lt;code&gt;IActionResult&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[&amp;lt;HttpGet("{id}")&amp;gt;]
member this.Get (id : int, shouldDouble : bool) : IActionResult =
    logger.LogInformation("I am a controller")

    let result =
        match shouldDouble with
        | true -&amp;gt; id * 2
        | false -&amp;gt; id

    match result with
    | 4 -&amp;gt; this.NoContent() :&amp;gt; IActionResult
    | _ -&amp;gt;
        sprintf "Hello %d" result
        |&amp;gt; this.Ok
        :&amp;gt; IActionResult

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



&lt;p&gt;From this we can see that we are using an additional match to either return &lt;code&gt;this.NoContent()&lt;/code&gt; as an &lt;code&gt;IActionResult&lt;/code&gt; or &lt;code&gt;this.Ok&lt;/code&gt; with the piped message as an &lt;code&gt;IActionResult&lt;/code&gt;. Just note that the following matches are equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// call the `this.Ok` function with
match result with
| 4 -&amp;gt; this.NoContent() :&amp;gt; IActionResult
| _ -&amp;gt;
    this.Ok(sprintf "Hello %d" result) :&amp;gt; IActionResult

// pipe the result of the format through
match result with
| 4 -&amp;gt; this.NoContent() :&amp;gt; IActionResult
| _ -&amp;gt;
    sprintf "Hello %d" result
    |&amp;gt; this.Ok
    :&amp;gt; IActionResult

// pipe the result of the format through on a single line
match result with
| 4 -&amp;gt; this.NoContent() :&amp;gt; IActionResult
| _ -&amp;gt; sprintf "Hello %d" result |&amp;gt; this.Ok :&amp;gt; IActionResult

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



&lt;h2&gt;
  
  
  Post Handler
&lt;/h2&gt;

&lt;p&gt;We can also create a &lt;code&gt;POST&lt;/code&gt; handler that will pretty much do the same as the above handler, we can pretty much just take the values from the function body and pass it to the previous handler we put together&lt;/p&gt;

&lt;p&gt;Before we can create the handler, we need to create a type called &lt;code&gt;PostData&lt;/code&gt; that can be used by the method to receive data, we can define this towards the top of the file, above the type definition for our &lt;code&gt;MessageController&lt;/code&gt;. The type also needs to have the &lt;code&gt;CLIMutable&lt;/code&gt; attribute so that the JSON deserializer can parse the data from the post body into it correctly&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[&amp;lt;CLIMutable&amp;gt;]
type PostData =
    { id : int
      shouldDouble : bool }

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



&lt;p&gt;Next we simply need to define the &lt;code&gt;Post&lt;/code&gt; method with an &lt;code&gt;HttpPost&lt;/code&gt; attribute which will just call the &lt;code&gt;this.Get&lt;/code&gt; using the input params. this can be done pretty simply too&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[&amp;lt;HttpPost&amp;gt;]
member this.Post(data : PostData) : IActionResult =
    this.Get(data.id, data.shouldDouble)

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



&lt;p&gt;And that's really all that's needed&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So yeah, that's pretty much it - Not that bad right? I feel like there are a couple of things that feel a little bit weird because of the pieces of OOP running around from C# that add a bit more overhead than I'd like, but it's .NET, that's inevitable&lt;/p&gt;

&lt;p&gt;Still a few more to posts on F# to come, so stay in tuned&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nabeel Valley&lt;/p&gt;
&lt;/blockquote&gt;

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