Categories
JavaScript

How to Manipulate Date and Time in JavaScript with Moment.js

There were issues with time zones with YYYY-MM-DD dates being parsed into UTC time as opposed to local time. Which creates bugs for developers who aren’t aware of this problem. See https://stackoverflow.com/questions/29174810/javascript-date-timezone-issue

Also there are difference in support for parts of Dates in different browsers. (See https://stackoverflow.com/questions/11253351/javascript-date-object-issue-in-safari-and-ie)

It is also hard to add and subtract timestamps with built in Date functions. There is no way to do this without writing a lot of code and doing a lot of checks. Also, there is no way to compare 2 times.

Formatting dates is also not available without writing your own code for using third party libraries.

Moment.js solves all of these issues by providing built in functions to do all these common operations. It provides functions for parsing and formatting dates.

The momentconstructor is where you can pass in a date string, and a moment object will be created. For example, you can pass in:

moment('2019-08-04')

and you will get back a moment which you can compare with other moment objects, and add or subtract by different time spans.

If you do not passing in anything to the moment constructor, you get the current date and time.

It also takes a second argument. If you want to make sure a date is parsed as a YYYY-MM-DD date, then write moment(‘2019–08–04’, 'YYYY-MM-DD') . If you don’t know the format of your date or time, then you can pass in an array of possible formats and Moment will pick the right one:

moment('2019–08–04', ['YYYY-MM-DD', 'DD-MM-YYYY']);

After you create a Moment object, then you can do many things like formatting dates:

const a = moment('2019–08–04', 'YYYY-MM-DD').format('MMMM Do YYYY, h:mm:ss a');
console.log(a);

// August 4th 2019, 12:00:00 am

const b = moment('2019–08–04', 'YYYY-MM-DD').format('dddd');
console.log(b);

// Sunday

const c = moment('2019–08–04', 'YYYY-MM-DD').format("MMM Do YY");
console.log(c);

// Aug 4th 19

const d = moment('2019–08–04', 'YYYY-MM-DD').format('YYYY [escaped] YYYY');
console.log(d);

// 2019 escaped 2019

const e = moment('2019–08–04', 'YYYY-MM-DD').format();
console.log(e);

// 2019-08-04T00:00:00-07:00

From the above examples, we see that we can format dates in pretty much any way we want.

We can also tell what time span a date is relative to another date by writing:

const augDate = moment('2019–08–04', 'YYYY-MM-DD');
const sepDate = moment('2019–09–04', 'YYYY-MM-DD');

console.log(augDate.from(sepDate)); // a month ago

We can also add or subtract Moment dates:

const augDate = moment('2019–08–04', 'YYYY-MM-DD');
const sepDate = moment('2019–09–04', 'YYYY-MM-DD');

console.log(augDate.add(10, 'days').calendar()); // 08/14/2019
console.log(augDate.subtract(10, 'days').calendar()); // 07/25/2019

It is easy to compare 2 dates

moment('2010-01-01').isSame('2010-01-01', 'month'); // true
moment('2010-01-01').isSame('2010-05-01', 'day');   // false, different month
moment('2008-01-01').isSame('2011-01-01', 'month'); // false, different year

You can also check if a date is has Daylight Saving Time in effect or not:

const augDate = moment('2019–08–04', 'YYYY-MM-DD');
const decDate = moment('2019–12–04', 'YYYY-MM-DD');
console.log(augDate.isDST()) // true
console.log(decDate.isDST()) // false

And you can convert back to JavaScript date any time by calling the toDate() function on a Moment object.

Categories
React

How To Build a Static Site With Gatsby.js

If you want to build a static website or a blog and you know web development, you have many choices of static website generators.

If you want to use React to build your static website, Gatsby could be a choice that suits your needs. It is used by many large corporations to build their websites, according to the Gatsby website.

In this piece, we will use Gatsby to build a small blog with pagination for blog posts and a menu which lets readers get categories. Once the reader clicks on the link for a category, they will go to a page listing all the posts tagged with those categories.

Gatsby can get content from files and from network sources like an API endpoint. Content is obtained through GraphQL endpoints which you can message to display data in a way you want, via templates.

You can also build static page files that display contents that don’t change. You write the code to get the content and display them with templates.

Then, you build the static web pages from the code you wrote. Plugins for Gatsby will provide the functionality that you want.

There are a few hoops to go through to build a static website or blog. Also, you cannot use most third-party React components with Gatsby as they are dynamic.

Also, the command-line utility has problems with case-sensitive paths on Windows, causing RelayParser: Encountered duplicate definitions for one or more documents from duplicate case-insensitive file paths in various parts of the project folder.

Therefore, Linux or Mac OS are probably the best choices for using the Gatsby CLI. Also, multiple page queries have to be made in one file and you pipe them all to templates in the same file.

The gatsby-node.js in the project is where the query for content takes place.

Now that we are aware of the caveats, we can start building our website. We will build a blog with some blog entries. The layout of the blog is a header for the top and content on the rest of the page.

We will have a template for displaying all the blog entries with pagination with five posts each. Also, we will have a categories page for displaying the list of articles with the given tag. We will use Bootstrap for styling.

We start by installing the Gatsby CLI by running npm install -g gatsby-cli. Once that is installed, we run the CLI program to add the initial code for the website. We run gatsby new gatsby-blog to build a new site.

Next, we install some add-on packages for Gatsby to do things like getting content from markdown files and displaying images.

Install the packages by running:

npm i @mdx-js/mdx @mdx-js/react bootstrap gatsby-image gatsby-paginate gatsby-plugin-manifest gatsby-plugin-mdx gatsby-plugin-offline gatsby-plugin-react-helmet gatsby-plugin-sharp gatsby-remark-images gatsby-source-filesystem gatsby-transformer-remark gatsby-transformer-sharp jquery lodash popper.js react-helmet

The main packages on this list are gatsby-image for displaying images, gatsby-source-filesystem for getting the markdown files and displaying them in our templates.

react-helmet for adding a head tag to our blog for including external CSS and script files. gatsby-transformer-remark is for converting markdown into HTML text. gatsby-transformer-sharp is for transforming images from various sources to display on our website.

With the package installation out of the way, we can start writing code. In the components folder, we first work on header.js.

In there, we put:

import { Link } from "gatsby"
import PropTypes from "prop-types"
import React from "react"
import { StaticQuery, graphql } from "gatsby"
import _ from "lodash"
import "./header.css"

const Header = ({ siteTitle }) => (
  <nav className="navbar navbar-expand-md bg-dark navbar-dark">
    <a className="navbar-brand" href="#">
      {siteTitle}
    </a>

    <button
      className="navbar-toggler"
      type="button"
      data-toggle="collapse"
      data-target="#collapsibleNavbar"
    >
      <span className="navbar-toggler-icon"></span>
    </button>
    <div className="collapse navbar-collapse" id="collapsibleNavbar">
      <ul className="navbar-nav">
        <li className="nav-item">
          <Link to="blog/page/1" className="nav-link">
            Home
          </Link>
        </li>
        <li className="nav-item dropdown">
          <a
            className="nav-link dropdown-toggle"
            href="#"
            id="navbarDropdown"
            role="button"
            data-toggle="dropdown"
            aria-haspopup="true"
            aria-expanded="false"
          >
            Categories
          </a>
          <div className="dropdown-menu" aria-labelledby="navbarDropdown">
            <StaticQuery
              query={graphql`
                query CategoryQuery {
                  allMarkdownRemark(limit: 2000) {
                    group(field: frontmatter___tags) {
                      fieldValue
                    }
                  }
                }
              `}
              render={data => {
                return data.allMarkdownRemark.group.map(g => {
                  return (
                    <Link
                      to={`tags/${g.fieldValue}`}
                      className="dropdown-item"
                    >
                      {_.capitalize(g.fieldValue)}
                    </Link>
                  )
                })
              }}
            />
          </div>
        </li>
      </ul>
    </div>
  </nav>
)

Header.propTypes = {
  siteTitle: PropTypes.string,
}

Header.defaultProps = {
  siteTitle: ``,
}

export default Header

This adds the Bootstrap navigation bar to our app. We get the tags for all our posts and display them in a drop-down in the navigation bar.

In header.css, we put:

.navbar-brand {
  font-size: 20px;
  margin-top: -20px;
}

nav.navbar {
  padding-bottom: 0px;
  height: 60px;
}

To change the height of the navigation bar and change font sizes and margins.

Next, we work on the common layout for the blog. We create a file called layout.js in the components folder, if it does not exist yet, and add:

/**
 * Layout component that queries for data
 * with Gatsby's useStaticQuery component
 *
 * See: [https://www.gatsbyjs.org/docs/use-static-query/](https://www.gatsbyjs.org/docs/use-static-query/)
 */

import React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import { Helmet } from "react-helmet"
import Header from "./header"
import "./layout.css"

const Layout = ({ children }) => {
  const data = useStaticQuery(graphql`
    query SiteTitleQuery {
      site {
        siteMetadata {
          title
        }
      }
    }
  `)

  return (
    <>
      <Helmet>
        <title>Gatsby Blog</title>
        <script
          src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
          integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
          crossOrigin="anonymous"
        ></script>
        <script
          src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
          integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
          crossOrigin="anonymous"
        ></script>
        <script
          src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
          integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
          crossOrigin="anonymous"
        ></script>
        <link
          href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
          rel="stylesheet"
          integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
          crossOrigin="anonymous"
        />
      </Helmet>
      <Header siteTitle={data.site.siteMetadata.title} />
      <div
        style={{
          margin: `0 auto`,
          maxWidth: 960,
          padding: `0px 1.0875rem 1.45rem`,
          paddingTop: 0,
        }}
      >
        <main>{children}</main>
        <footer>
          © {new Date().getFullYear()}, Built with
          {` `}
          <a href="https://www.gatsbyjs.org">Gatsby</a>
        </footer>
      </div>
    </>
  )
}

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default Layout

In this file, we add the head tag for our HTML pages. We include the Bootstrap CSS and code files and jQuery in the Helmet component, which will be converted to the head tag in our pages.

Next, we add our content, create a markdown-pages folder in the src folder. Then, we create some markdown files.

We add the following files into the markdown-pages folder:

check-variable-number.md
clone-array.md
concat-array.md
exponentiation.md
get-length-obj.md
repeat-string.md
send-email.md

Then, in check-variable-number.md, we add:

---
path: "/blog/check-variable-number"
date: "2019-05-04"
title: "How to Check if a Variable is a Number"
tags: ["number"]
---

We can check if a variable is a number in multiple ways.

## isNaN

We can check by calling `isNaN` with the variable as the argument. It also detects if a string’s content is a number. For example:

isNaN(1) // false isNaN(‘1’) // false isNaN(‘abc’) // true


**Note:** `isNaN(null)` is `true` .

### typeof Operator

We can use the `typeof` operator before a variable to check if it’s a number, like so:

typeof 1 == ‘number’ // true typeof ‘1’ == ‘number’ // false


![]([https://cdn-images-1.medium.com/max/800/1*3X6EiKc-njoRpCB1AWnv3Q.png](https://cdn-images-1.medium.com/max/800/1*3X6EiKc-njoRpCB1AWnv3Q.png))

In clone-array.md, we add:

---
path: "/blog/clone-array"
date: "2019-05-04"
title: "How to Clone Array in JavaScript"
tags: ["array"]
---

There are a few ways to clone an array in JavaScript,

### Object.assign

`Object.assign` allows us to make a shallow copy of any kind of object including arrays.

For example:

<pre>const a = [1,2,3];
const b = Object.assign([], a); // [1,2,3]</pre>

### Array.slice

The `Array.slice` function returns a copy of the original array.

For example:

<pre>const a = [1,2,3];
const b = a.slice(0); // [1,2,3]</pre>

### Array.from

The `Array.slice` function returns a copy of the original array. It takes array like objects like `Set` and it also takes an array as an argument.

<pre>const a = [1,2,3];
const b = Array.from(a); // [1,2,3]</pre>

### Spread Operator

The fastest way to copy an array, which is available with ES6 or later, is the spread operator.

<pre>const a = [1,2,3];
const b = [...a]; // [1,2,3]</pre>

### JSON.parse and JSON.stringify

This allows for deep copy of an array and only works if the objects in the array are plain objects. It can be used like this:

<pre>const a = [1,2,3];
const b = JSON.parse(JSON.stringify(a)); // [1,2,3]</pre>

Next, in concat-array.md, we add:

---
path: "/blog/concat-array"
date: "2019-05-04"
title: "How to Concatenate Array in JavaScript"
tags: ["array"]
---

There are a few ways to concatenate arrays in JavaScript.

## Array.concat

We can all `Array.concat` on an array to combine 2 arrays and return the new one. For example:

const a = [1,2,3]; const b = [4,5]; const c = a.concat(b) // [1,2,3,4,5]


## Array.push

We can push elements of one array into another.

const a = [1,2,3]; const b = [4,5]; let c = Object.assign([], a); for (let i = 0; i < b.length; i++){ c.push(b[i]); } console.log(c); // [1,2,3,4,5]


What we did is make a copy of `a` and assigned it to `c` , then pushed the elements of `b` by looping through it and adding them to the end of `c` .

## Spread Operator

With ES6 or later, we can use the spread operator to spread the items from another array into a new array by doing the following:

const a = [1,2,3]; const b = [4,5]; const c = […a, …b]; console.log(c); // [1,2,3,4,5]


![]([https://cdn-images-1.medium.com/max/800/1*3X6EiKc-njoRpCB1AWnv3Q.png](https://cdn-images-1.medium.com/max/800/1*3X6EiKc-njoRpCB1AWnv3Q.png))

In exponentiation.md, we add:

---
path: "/blog/exponentiation"
date: "2019-05-04"
title: "How to do Exponentiation in JavaScript"
tags: ["number"]
---

There are multiple to compute exponents with JavaScript.

The newest way is the exponentiation operator `**`, available with ES2016 or higher.

For example, we can do this:

const a = 2 ** 3; // 8


It is right associative, so `a ** b ** c` is equal to `a ** (b ** c)`. This works with all exponents.

For example:

const a = 2 ** (3 ** 4); const b = 2 ** 3 ** 4; a == b // true, both are 2.4178516392292583e+24


Detail browser compatibility is available at [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Browser_compatibility](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Browser_compatibility)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Browser_compatibility]%28https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Browser_compatibility%29)

We can also use the `Math.pow` function, like this:

const a = Math.pow(2,3) // 8


It takes 2 arguments, the first is the base and the second is the exponent. `Math.pow` works with all exponents.

`Math.pow` is compatible with all recent browsers.

![]([https://cdn-images-1.medium.com/max/800/1*3X6EiKc-njoRpCB1AWnv3Q.png](https://cdn-images-1.medium.com/max/800/1*3X6EiKc-njoRpCB1AWnv3Q.png))

In get-length-obj.md, we add:

---
path: "/blog/get-length-obj"
date: "2019-05-04"
title: "How to Get the Length of An Object"
tags: ["object"]
---

There are 2 ways to get the length of the list of keys of an object.

## Object.keys

`Object.keys` gets the top level list of keys of an object and returns an array of them. For example:

const a = {foo: 1, bar: 2}; const length = Object.keys(a).length // 2


## Object.getPropertyNames

`Object.getPropertyNames` also gets a list of all top level of keys of an object and return them as an array. For example:

const a = {foo: 1, bar: 2}; const length = Object.getOwnPropertyNames(a).length // 2


## for…in Loop

There is a special loop for looping through the keys of an object. You can do the following:

const a = {foo: 1, bar: 2}; let keysCount = 0; for (let key in a) { keysCount++; } console.log(`keysCount) // 2


![]([https://cdn-images-1.medium.com/max/800/1*3X6EiKc-njoRpCB1AWnv3Q.png](https://cdn-images-1.medium.com/max/800/1*3X6EiKc-njoRpCB1AWnv3Q.png))

In repeat-strings.md, we add:

---
path: "/blog/repeat-strings"
date: "2019-05-04"
title: "How to Repeat Strings with JavaScript"
tags: ["string"]
---

There are a few ways to repeat a string in JavaScript. JavaScript strings have a built in `repeat()` function. You can also use a loop to do the same thing.

## String.repeat Function

To use the `repeat` function, you pass in the number of times you want to repeat the string as an argument. It returns a new string

For example:

const hello = "hello"; const hello5 = A.repeat(5); console.log(hello5); // "hellohellohellohellohello"


## Use a loop

You can use `for` loop and `while` loop to do repeatedly concatenate strings.

Using a `for` loop, you can do:

const hello = "hello";


With a `while` loop, you can do:

const hello = "hello";


They both involve increment indexes up to the maximum.

![]([https://cdn-images-1.medium.com/max/800/1*3X6EiKc-njoRpCB1AWnv3Q.png](https://cdn-images-1.medium.com/max/800/1*3X6EiKc-njoRpCB1AWnv3Q.png))

In send-email.md, we add:

---
path: "/blog/send-email"
date: "2019-05-04"
title: "How to Send Email with SendGrid in Node.js Apps"
tags: ["array"]
---

SendGrid is a great service made by Twilio for sending emails. Rather than setting up your own email server for sending email with your apps, we use SendGrid to do the hard work for us. It also decrease the chance of email ending up in spam since it is a known trustworthy service.

It also has very easy to use libraries for various platforms for sending emails. Node.js is one of the platforms that are supported.

To send emails with SendGrid, install the SendGrid SDK package by running `npm i [@sendgrid/mail](http://twitter.com/sendgrid/mail "Twitter profile for @sendgrid/mail")` . Then in your code, add `const sgMail = require(‘[@sendgrid/mail](http://twitter.com/sendgrid/mail "Twitter profile for @sendgrid/mail")’);` to import the installed package.

Then in your code, you send email by:

sgMail.setApiKey(process.env.SENDGRID_API_KEY); const msg = { to: email, from: ‘email@example.com‘, subject: ‘Example Email’, text: Dear user, Here is your email., html: <p>Dear user,</p></pre> Here is your email.</p>, }; sgMail.send(msg);


where `process.env.SENDGRID_API_KEY` is the SendGrid’s API, which should be stored as an environment variable since it is a secret.

Testing is easy since you don’t need to set up a local development email server.

Sending email is this simple and easy with SendGrid API. It is also free if you send small amounts of email, which is a great benefit.

![]([https://cdn-images-1.medium.com/max/800/1*EdbfsnL3ABxWj2iVWmoIWA.png](https://cdn-images-1.medium.com/max/800/1*EdbfsnL3ABxWj2iVWmoIWA.png))

In each file, we have the metadata between the dotted lines. They will be obtained from GraphQL queries and can be displayed on our pages, and we will display them.

Now that we’ve worked on our content, we can work on the static pages. We change default 404 pages by adding the top navigation bar.

In 404.js, we replace the existing code with:

import React from "react"

import Layout from "../components/layout"
import SEO from "../components/seo"
import Header from "../components/header";

const NotFoundPage = () => (
  <Layout>
    <SEO title="404: Not found" />
    <h1>NOT FOUND</h1>
    <p>You just hit a route that doesn&#39;t exist... the sadness.</p>
  </Layout>
)

export default NotFoundPage

Everything in the Layout component will be applied to this page, including the navigation bar and Bootstrap styles.

In index.js, we replace the existing code with:

import React from "react"

import Layout from "../components/layout"
import SEO from "../components/seo"
import { useEffect } from "react"
import { navigate } from "gatsby"

const IndexPage = () => {
  useEffect(() => {
    navigate("/blog/page/1")
  }, [])

  return (
    <Layout>
      <SEO title="Home" />
    </Layout>
  )
}

export default IndexPage

To redirect to our blog template, which we will create.

Next, we create our templates. We create a templates folder in the src folder to store our templates.

In there, create blog-list-template.js and add:

import React from "react"
import { graphql, Link } from "gatsby"
import Layout from "../components/layout"
export default class BlogList extends React.Component {
  constructor(props) {
    super(props)
    this.state = { pageNumArray: [1] }
  }

  componentDidMount() {
    this.setPageArray()
  }

  componentWillReceiveProps() {
    this.setPageArray()
  }

  setPageArray() {
    const totalCount = this.props.data.allMarkdownRemark.totalCount
    const postsPerPage = this.props.data.allMarkdownRemark.pageInfo.perPage
    let pageNumArray = Array.from(
      { length: Math.ceil(totalCount / postsPerPage) },
      (v, i) => i + 1
    )
    this.setState({ pageNumArray })
  }

render() {
    const posts = this.props.data.allMarkdownRemark.edges
    const pathNames = this.props.location.pathname.split("/")
    const page = pathNames[pathNames.length - 1]
    return (
      <Layout>
        {posts.map(({ node }) => {
          const title = node.frontmatter.title || node.fields.slug
          return (
            <div key={node.fields.slug}>
              <h1>{title}</h1>
              <b>Date Posted: {node.frontmatter.date}</b>
              <div dangerouslySetInnerHTML={{ __html: node.html }} />
            </div>
          )
        })}
        <nav aria-label="Page navigation example">
          <ul className="pagination">
            {this.state.pageNumArray.map(p => (
              <li className={`page-item ${page == p ? "active" : ""}`} key={p}>
                <Link className={`page-link`} to={`blog/page/${p}`}>
                  {p}
                </Link>
              </li>
            ))}
          </ul>
        </nav>
      </Layout>
    )
  }
}
export const blogListQuery = graphql`
  query blogListQuery($skip: Int!, $limit: Int!) {
    allMarkdownRemark(
      sort: { fields: [frontmatter___date], order: DESC }
      limit: $limit
      skip: $skip
    ) {
      edges {
        node {
          fields {
            slug
          }
          frontmatter {
            title
            date
          }
          html
        }
      }
      pageInfo {
        perPage
      }
      totalCount
    }
  }
`

In here, display the content that is providing the query that we will add in gatsby-node.js.

The blogListQuery filters the content by running the query and returning the results. Then, the results will be displayed in the component above.

The setPageArray function gets the page numbers by getting the total number of pages and then setting it in the component state so that we can have links to go the page, which is rendered by:

{this.state.pageNumArray.map(p => (
   <li className={`page-item ${page == p ? "active" : ""}`} key={p}>
     <Link className={`page-link`} to={`blog/page/${p}`}>
     {p}
     </Link>
   </li>
))}

The blog posts are rendered by:

{posts.map(({ node }) => {
  const title = node.frontmatter.title || node.fields.slug
  return (
    <div key={node.fields.slug}>
      <h1>{title}</h1>
      <b>Date Posted: {node.frontmatter.date}</b>
      <div dangerouslySetInnerHTML={{ __html: node.html }} />
      </div>
  )
})}

Gatsby sanitizes HTML so we can display it by setting it directly with dangerouslySetInnerHTML. Next, we make a template to display the posts with certain tags.

To do this, we create tags.js in the templates folder and add:

import React from "react"
import PropTypes from "prop-types"
import Layout from "../components/layout"
import _ from "lodash"
// Components
import { Link, graphql } from "gatsby"

const Tags = ({ pageContext, data }) => {
  const { tag } = pageContext
  const { edges, totalCount } = data.allMarkdownRemark
  const tagHeader = `${totalCount} post${
    totalCount === 1 ? "" : "s"
  } tagged with "${_.capitalize(tag)}"`

  return (
    <Layout>
      <h1>{tagHeader}</h1>
      {edges.map(({ node }) => {
        const { slug } = node.fields
        const { title, date } = node.frontmatter
        return (
          <div key={slug}>
            <h1>{title}</h1>
            <b>Date Posted: {date}</b>
            <div dangerouslySetInnerHTML={{ __html: node.html }} />
          </div>
        )
      })}
    </Layout>
  )
}

Tags.propTypes = {
  pageContext: PropTypes.shape({
    tag: PropTypes.string.isRequired,
  }),
  data: PropTypes.shape({
    allMarkdownRemark: PropTypes.shape({
      totalCount: PropTypes.number.isRequired,
      edges: PropTypes.arrayOf(
        PropTypes.shape({
          node: PropTypes.shape({
            frontmatter: PropTypes.shape({
              title: PropTypes.string.isRequired,
            }),
            fields: PropTypes.shape({
              slug: PropTypes.string.isRequired,
            }),
          }),
        }).isRequired
      ),
    }),
  }),
}

export default Tags

export const pageQuery = graphql`
  query($tag: String) {
    allMarkdownRemark(
      limit: 2000
      sort: { fields: [frontmatter___date], order: DESC }
      filter: { frontmatter: { tags: { in: [$tag] } } }
    ) {
      totalCount
      edges {
        node {
          fields {
            slug
          }
          frontmatter {
            title
            date
          }
          html
        }
      }
    }
  }
`

It works similarly to blog-list-template.js. The GraphQL query at the bottom gets the posts tagged with the given tag and then displays them by running the component code above.

The metadata of our pages is in the frontmatter object of each entry.

Next, in gatsby-config.js, we replace the existing code with:

module.exports = {
  siteMetadata: {
    title: `Gatsby Blog`,
    description: `Gatsby Blog`,
    author: `[@gatsbyjs](http://twitter.com/gatsbyjs "Twitter profile for @gatsbyjs")`,
  },
  plugins: [
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-plugin-mdx`,
      options: {
        gatsbyRemarkPlugins: [
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 1200,
            },
          },
        ],
      },
    },
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `gatsby-starter-default`,
        short_name: `starter`,
        start_url: `/blog/page/1`,
      },
    },
    // this (optional) plugin enables Progressive Web App + Offline functionality
    // To learn more, visit: [https://gatsby.dev/offline](https://gatsby.dev/offline)
    // `gatsby-plugin-offline`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `markdown-pages`,
        path: `${__dirname}/src/markdown-pages`,
      },
    },
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [
          {
            resolve: `gatsby-remark-images`,
            options: {
              // It's important to specify the maxWidth (in pixels) of
              // the content container as this plugin uses this as the
              // base for generating different widths of each image.
              maxWidth: 590,
            },
          },
        ],
      },
    },
  ],
}

So that all the packages we installed run.

Finally, in gatsby-node.js, we replace the existing code with:

const _ = require("lodash")
const path = require("path")
const { createFilePath } = require("gatsby-source-filesystem")

exports.createPages = async ({ graphql, actions, reporter }) => {
  const { createPage } = actions
  const result = await graphql(
    `
      {
        postRemark: allMarkdownRemark(
          sort: { fields: [frontmatter___date], order: DESC }
          limit: 1000
        ) {
          edges {
            node {
              fields {
                slug
              }
            }
          }
        }
        tagsGroup: allMarkdownRemark(limit: 2000) {
          group(field: frontmatter___tags) {
            fieldValue
          }
        }
      }
    `
  )
  if (result.errors) {
    reporter.panicOnBuild(`Error while running GraphQL query.`)
    return
  }
  // ...
  // Create blog-list pages
  const posts = result.data.postRemark.edges
  const postsPerPage = 5
  const numPages = Math.ceil(posts.length / postsPerPage)
  Array.from({ length: numPages }).forEach((_, i) => {
    createPage({
      path: `/blog/page/${i + 1}`,
      component: path.resolve("./src/templates/blog-list-template.js"),
      context: {
        limit: postsPerPage,
        skip: i * postsPerPage,
        numPages,
        currentPage: i + 1,
      },
    })
  })

const tags = result.data.tagsGroup.group
  tags.forEach(tag => {
    createPage({
      path: `/tags/${_.kebabCase(tag.fieldValue)}/`,
      component: path.resolve("./src/templates/tags.js"),
      context: {
        tag: tag.fieldValue,
      },
    })
  })
}
exports.onCreateNode = ({ node, actions, getNode }) => {
  const { createNodeField } = actions
  if (node.internal.type === `MarkdownRemark`) {
    const value = createFilePath({ node, getNode })
    createNodeField({
      name: `slug`,
      node,
      value,
    })
  }
}

In the file above, we have one query for getting all the posts and then create pages to display them in groups with the postRemark query below:

postRemark: allMarkdownRemark(
  sort: { fields: [frontmatter___date], order: DESC }
    limit: 1000
  ) {
  edges {
    node {
      fields {
        slug
      }
  }
}

We create the page files with:

const posts = result.data.postRemark.edges
  const postsPerPage = 5
  const numPages = Math.ceil(posts.length / postsPerPage)
  Array.from({ length: numPages }).forEach((_, i) => {
    createPage({
      path: `/blog/page/${i + 1}`,
      component: path.resolve("./src/templates/blog-list-template.js"),
      context: {
        limit: postsPerPage,
        skip: i * postsPerPage,
        numPages,
        currentPage: i + 1,
      },
    })
  })

It looks through the returned results and them pipes the resulting entry to the template to generate the pages during build time.

The tagsGroup query below:

tagsGroup: allMarkdownRemark(limit: 2000) {
    group(field: frontmatter___tags) {
      fieldValue
    }
}

Gets all the tags and then pipes the tags into the tags.js template, where it gets the page content and creates the pages during build time with posts for a given tag on each page.

Now we are ready to build the static website by running gatsby build. The files should be built in the public folder.

After that, we install an HTTP server for serving the built static files. We will install the http-server Node.js packages. Run npm i -g http-server. Then, run http-server /path/to/gatsby-blog/public.

After all that is done, we get:

Categories
Functional Javascript

Functional JavaScript — Piping and Functors

JavaScript is partly a functional language.

To learn JavaScript, we got to learn the functional parts of JavaScript.

In this article, we’ll look at how to pipe functions and functors with JavaScript.

Pipe

We can create a pipe function by creating a function that takes an array of functions as arguments.

It returns a function that takes a value and we call reduce on it with that calls fn with acc .

For example, we can write:

const compose = (...fns) =>
  (value) =>
  fns.reduceRight((acc, fn) => fn(acc), value)

The only difference is that we used reduceRight instead of reduce so that we don’t have to call reverse to apply all the functions.

Composition is Associative

Composition is associative, this means we can rearrange the parentheses of our operations

For instance:

compose(f, compose(g, h)) == compose(compose(f, g), h)

returns true .

Functors

Functor is a plain object that implements the function map while running River each value to produce a new object.

A functor is a container that holds some value in it.

For example, we can write:

const Container = function(val) {
  this.value = val;
}

to create our container.

Then we can use new to invoke the Container constructor:

let foo = new Container(3);

We can create a Container.of property to add a container to let us return a Container instance:

const Container = function(val) {
  this.value = val;
}

Container.of = function(value) {
  return new Container(value);
}

We added the of static method to return a Container instance.

The of method just gives us an alternative to using the new operator to create the Container instance.

Then we can create a Container instance with the of method:

const nested = Container.of(Container.of(1));

Then we’ll see the nested Container instances.

Functor Implements Method Called map

Functors implement the map method.

We can add it as an instance method by adding it to the prototype property:

const Container = function(val) {
  this.value = val;
}

Container.of = function(value) {
  return new Container(value);
}

Container.prototype.map = function(fn) {
  return Container.of(fn(this.value));
}

Then we can use the map method after we create a Container instance.

For instance, we can use it by writing:

const squared = Container.of(3).map(a => a ** 2);

Then squared is a Container instance with value being 9.

We call map repeatedly to repeat an operation.

So we can write:

const squared = Container.of(3)
  .map(square)
  .map(square)
  .map(square);

Then squared is a Container instance with value being 6561.

Functor is just an object that implements a map method.

Conclusion

Functors are plain objects that have value.

The object has a map method.

We can pipe functions to call multiple functions and get the returned value.

Composition is associative, so we can rearrange the parentheses of our operations.

Categories
Functional Javascript

Functional JavaScript — Partial Application and Composition

JavaScript is partly a functional language.

To learn JavaScript, we got to learn the functional parts of JavaScript.

In this article, we’ll look at how to use partial application and composition of functions with JavaScript.

Partial Application

Partial application is where we only apply some of the arguments that are expected in a function.

For example, if we have a function with 3 parameters:

const add = (x, y, z) => x + y + z;

Then we can create a function that has the add function with arguments partially applied by writing:

const add1 = (y, z) => add(1, y, z);

Then we can use it by writing:

const sum = add1(2, 3);

And we get 6.

To generalize this, we can write:

const partial = function(fn, ...partialArgs) {
  let args = partialArgs;
  return function(...fullArguments) {
    return fn(...[...partialArgs, ...fullArguments]);
  };
};

We create our own partial function by returning a function with the partialArgs and fullArguments spread as arguments into the fn function.

Then we can use it by writing:

const sum = partial(add, 1)(2, 3);

and sum is 6 again.

Currying vs. Partial Application

Currying is good whenever we need to convert functions that take multiple arguments to multiple functions that take one argument.

Situations where we need to convert a function that takes multiple arguments to a callback for map that only takes one parameter an example of that.

Partial application of a function is useful for any situation where we need to apply one or arguments to a function and return a function that has the arguments applied.

Composition

Composition is where we chain multiple function calls to return the result that we want.

We have many functions that do one thing, and we combine them into one so that we can get the result we want.

For instance, we can compose the array map and filter methods by writing:

const arr = [1, 2, 3]
  .filter(a => a % 2 === 1)
  .map(a => a ** 2);

And arr is [1, 9] .

We call filter to return an array with only the odd numbers.

And then we call map to square each odd number.

compose Function

We can generalize the compose function by writing:

const compose = (fn1, fn2) =>
  (c) => fn1(fn2(c))

Our function takes 2 functions as parameters and then we return a function that calls one after the other.

fn2 is called first, then fn1 is called on the result returned by fn2 .

Then we can use it by writing:

let number = compose(Math.round, parseFloat)('10.1')

We called compose with Math.round and parseFloat .

parseFloat is called first with '10.1' and then Math.round is called on the returned result.

Then number is 10.

Compose Many Functions

We can create a general version of the compose function by using the array reduce method.

For example, we can write:

const compose = (...fns) =>
  (value) =>
  fns.reverse().reduce((acc, fn) => fn(acc), value)

We created a function which takes an array of functions fns as a parameter.

Then we return a function that takes a value as the initial value and call reduce on it to call each function in the array with the returned result.

acc is the returned result from calling the functions so far, and fn is the function.

And then we can use it by writing:

let splitIntoSpaces = (str) => str.split(" ");
let count = (array) => array.length;
const countWords = compose(count, splitIntoSpaces)('foo bar baz');

We split the string by the space with splitIntoSpaces function.

And we get the length of the split string array with the count function.

And then we use compose to combine them together.

Once we call the returned function with a string, we get the number words separated by a space.

So countWords is 3.

Conclusion

We can partially apply and compose functions with JavaScript.

Partial application lets us call functions with some arguments applied.

And composition lets us call multiple functions in a chain.

Categories
Functional Javascript

Functional JavaScript — Monads

JavaScript is partly a functional language.

To learn JavaScript, we got to learn the functional parts of JavaScript.

In this article, we’ll look at how to pipe functions and functors with JavaScript.

MayBe Functors

A MayBe functor is one that lets us implement a map function in a different way.

We start off by creating a constructor that stores a value:

const MayBe = function(val) {
  this.value = val;
}

MayBe.of = function(val) {
  return new MayBe(val);
}

Then we add the methods unique to the MayBe functor.

We have the isNothing method to check if this.value has anything.

The map method will return something different depending on whether this.value has something or not.

We add:

MayBe.prototype.isNothing = function() {
  return (this.value === null || this.value === undefined);
};

MayBe.prototype.map = function(fn) {
  return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this.value));
};

Together, we have:

const MayBe = function(val) {
  this.value = val;
}

MayBe.of = function(val) {
  return new MayBe(val);
}

MayBe.prototype.isNothing = function() {
  return (this.value === null || this.value === undefined);
};

MayBe.prototype.map = function(fn) {
  return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this.value));
};

Then we can use it by writing:

const str = MayBe.of("foo").map((x) => x.toUpperCase())

Then we get the the value property of the MayBe instance is 'FOO' .

If this.value is null or undefined , then map will return a MayBe functor with value being null .

So if we have something like:

const str = MayBe.of("james")
  .map(() => undefined)
  .map((x) => `Mr. ${x}`)

We’ll get the final value of value being null instead of throwing an error.

Either Functor

The Either functor allows us to solve problems with branches.

We create a Nothing or Some functor and out them in an object.

So we write:

const Nothing = function(val) {
  this.value = val;
};

Nothing.of = function(val) {
  return new Nothing(val);
};

Nothing.prototype.map = function(f) {
  return this;
};

const Some = function(val) {
  this.value = val;
};

Some.of = function(val) {
  return new Some(val);
};

Some.prototype.map = function(fn) {
  return Some.of(fn(this.value));
}

Now if want to hold some data, then we can use the Some functor.

Otherwise, we use the Nothing functor to hold some non-existent value.

Monads

A monad is a functor with a chain method.

The chain method calls a join method to call it return an a MayBe instance if this.value has a value.

For example, we can write:

const MayBe = function(val) {
  this.value = val;
}

MayBe.of = function(val) {
  return new MayBe(val);
}

MayBe.prototype.isNothing = function() {
  return (this.value === null || this.value === undefined);
};

MayBe.prototype.map = function(fn) {
  return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this.value));
};

MayBe.prototype.join = function() {
  return this.isNothing() ? MayBe.of(null) : this.value;
}

MayBe.prototype.chain = function(f) {
  return this.map(f).join()
}

The join method checks if this.value is null or undefined .

If it is, then we return a null MayBe functor.

Otherwise, we return this.value .

chain just calls map and join together.

This way, if we map something to null , then it stays null .

Then we can use this by writing:

let mayBe = MayBe.of({
  data: [{
    title: 'foo',
    children: [{
      bar: 2
    }]
  }]
})

let ans = mayBe.map((arr) => arr.data)
  .chain((obj) => map(obj, (x) => {
    return {
      title: x.title
    }
  }))

then we get the title from the object we passed into of .

Conclusion

A monad is a functor that has the chain method, which does the mapping and joining together.