<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ 2020 - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ 2020 - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 26 May 2026 10:37:33 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/2020/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ The React + Apollo Tutorial for 2020 (Real-World Examples) ]]>
                </title>
                <description>
                    <![CDATA[ If you want to build apps with React and GraphQL, Apollo is the library you should use. I've put together a comprehensive cheatsheet that goes through all of the core concepts in the Apollo library, showing you how to use it with React from front to ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-apollo-client-2020-tutorial/</link>
                <guid isPermaLink="false">66d037b131fbfb6c3390f209</guid>
                
                    <category>
                        <![CDATA[ 2020 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Apollo GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ apollo client ]]>
                    </category>
                
                    <category>
                        <![CDATA[ cheatsheet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Tutorial ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Reed ]]>
                </dc:creator>
                <pubDate>Sat, 04 Jul 2020 13:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/07/React---Apollo-2020-Cheatsheet.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you want to build apps with React and GraphQL, Apollo is the library you should use.</p>
<p>I've put together a comprehensive cheatsheet that goes through all of the core concepts in the Apollo library, showing you how to use it with React from front to back.</p>
<h3 id="heading-want-your-own-copy">Want Your Own Copy?</h3>
<p>You can grab the PDF cheatsheet <strong><a target="_blank" href="https://reedbarger.com/resources/react-apollo-2020/">right here</a></strong> (it takes 5 seconds).</p>
<p>Here are some quick wins from grabbing the downloadable version:</p>
<ul>
<li>✓ Quick reference to review however and whenever</li>
<li>✓ Tons of useful code snippets based off of real-world projects</li>
<li>✓ Read this guide offline, wherever you like. On the train, at your desk, standing in line — anywhere.</li>
</ul>
<h3 id="heading-prefer-video-lessons">Prefer Video Lessons?</h3>
<p>A great deal of this cheatsheet is based off of the app built in the React + GraphQL 2020 Crash Course. </p>
<p>If you want some more hands-on video lessons, plus see how to build apps with React, GraphQL and Apollo, you can watch the course <a target="_blank" href="https://bit.ly/2020-react-graphql">right here</a>.</p>
<blockquote>
<p>Note: This cheatsheet does assume familiarity with React and GraphQL. If you need a quick refresher on GraphQL and how to write it, a great resource is the <a target="_blank" href="https://graphql.org/learn/">official GraphQL website</a>.</p>
</blockquote>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<h3 id="heading-getting-started">Getting Started</h3>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-apollo-and-why-do-we-need-it">What is Apollo and why do we need it?</a></li>
<li><a class="post-section-overview" href="#heading-apollo-client-basic-setup">Apollo Client setup</a></li>
<li><a class="post-section-overview" href="#heading-creating-a-new-apollo-client-basic-setup">Creating a new Apollo Client</a></li>
<li><a class="post-section-overview" href="#heading-providing-the-client-to-react-components">Providing the client to React components</a></li>
<li><a class="post-section-overview" href="#heading-using-the-client-directly">Using the client directly</a></li>
<li><a class="post-section-overview" href="#heading-writing-graphql-operations-in-js-files-gql">Writing GraphQL in .js files with gql</a></li>
</ul>
<h3 id="heading-core-apollo-react-hooks">Core Apollo React Hooks</h3>
<ul>
<li><a class="post-section-overview" href="#heading-usequery-hook">useQuery Hook</a></li>
<li><a class="post-section-overview" href="#heading-uselazyquery-hook">useLazyQuery Hook</a></li>
<li><a class="post-section-overview" href="#heading-usemutation-hook">useMutation Hook</a></li>
<li><a class="post-section-overview" href="#heading-usesubscription-hook">useSubscription Hook</a></li>
</ul>
<h3 id="heading-essential-recipes">Essential Recipes</h3>
<ul>
<li><a class="post-section-overview" href="#heading-manually-setting-the-fetch-policy">Manually setting the fetch policy</a></li>
<li><a class="post-section-overview" href="#heading-updating-the-cache-upon-a-mutation">Updating the cache upon a mutation</a></li>
<li><a class="post-section-overview" href="#heading-refetching-queries-with-usequery">Refetching queries with useQuery</a></li>
<li><a class="post-section-overview" href="#heading-refetching-queries-with-usemutation">Refetching queries with useMutation</a></li>
<li><a class="post-section-overview" href="#heading-using-the-client-with-useapolloclient">Accessing the client with useApolloClient</a></li>
</ul>
<h3 id="heading-what-is-apollo-and-why-do-we-need-it">What is Apollo and why do we need it?</h3>
<p>Apollo is a library that brings together two incredibly useful technologies used to build web and mobile apps: React and GraphQL. </p>
<p>React was made for creating great user experiences with JavaScript. GraphQL is a very straightforward and declarative new language to more easily and efficiently fetch and change data, whether it is from a database or even from static files. </p>
<p>Apollo is the glue that binds these two tools together. Plus it makes working with React and GraphQL a lot easier by giving us a lot of custom React hooks and features that enable us to both write GraphQL operations and execute them with JavaScript code. </p>
<p>We'll cover these features in-depth throughout the course of this guide.</p>
<h3 id="heading-apollo-client-basic-setup">Apollo Client basic setup</h3>
<p>If you are starting a project with a React template like Create React App, you will need to install the following as your base dependencies to get up and running with Apollo Client:</p>
<pre><code class="lang-bash">// with npm:
npm i @apollo/react-hooks apollo-boost graphql

// with yarn:
yarn add @apollo/react-hooks apollo-boost graphql
</code></pre>
<p><code>@apollo/react-hooks</code> gives us React hooks that make performing our operations and working with Apollo client better</p>
<p><code>apollo-boost</code> helps us set up the client along with parse our GraphQL operations</p>
<p><code>graphql</code> also takes care of parsing the GraphQL operations (along with gql)</p>
<h3 id="heading-apollo-client-subscriptions-setup">Apollo Client + subscriptions setup</h3>
<p>To use all manner of GraphQL operations (queries, mutations, and subscriptions), we need to install more specific dependencies as compared to just <code>apollo-boost</code>:</p>
<pre><code class="lang-bash">// with npm:
npm i @apollo/react-hooks apollo-client graphql graphql-tag apollo-cache-inmemory apollo-link-ws

// with yarn:
yarn add @apollo/react-hooks apollo-client graphql graphql-tag apollo-cache-inmemory apollo-link-ws
</code></pre>
<p><code>apollo-client</code> gives us the client directly, instead of from <code>apollo-boost</code></p>
<p><code>graphql-tag</code> is integrated into <code>apollo-boost</code>, but not included in <code>apollo-client</code></p>
<p><code>apollo-cache-inmemory</code> is needed to setup our own cache (which <code>apollo-boost</code>, in comparison, does automatically)</p>
<p><code>apollo-link-ws</code> is needed for communicating over websockets, which subscriptions require</p>
<h3 id="heading-creating-a-new-apollo-client-basic-setup">Creating a new Apollo Client (basic setup)</h3>
<p>The most straightforward setup for creating an Apollo client is by instantiating a new client and providing just the <code>uri</code> property, which will be your GraphQL endpoint:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> ApolloClient <span class="hljs-keyword">from</span> <span class="hljs-string">"apollo-boost"</span>;

<span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> ApolloClient({
  <span class="hljs-attr">uri</span>: <span class="hljs-string">"https://your-graphql-endpoint.com/api/graphql"</span>,
});
</code></pre>
<p><code>apollo-boost</code> was developed in order to make doing things like creating an Apollo Client as easy as possible. What it lacks for the time being, however, is support for GraphQL subscriptions over a websocket connection. </p>
<p>By default, it performs the operations over an http connection (as you can see through our provided uri above).</p>
<p>In short, use <code>apollo-boost</code> to create your client if you only need to execute queries and mutations in your app. </p>
<p>It setups an in-memory cache by default, which is helpful for storing our app data locally. We can read from and write to our cache to prevent having to execute our queries after our data is updated. We'll cover how to do that a bit later.</p>
<h3 id="heading-creating-a-new-apollo-client-subscriptions-setup">Creating a new Apollo Client (+ subscriptions setup)</h3>
<p>Subscriptions are useful for more easily displaying the result of data changes (through mutations) in our app. </p>
<p>Generally speaking, we use subscriptions as an improved kind of query. Subscriptions use a websocket connection to 'subscribe' to updates and data, enabling new or updated data to be immediately displayed to our users without having to reexecute queries or update the cache.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> ApolloClient <span class="hljs-keyword">from</span> <span class="hljs-string">"apollo-client"</span>;
<span class="hljs-keyword">import</span> { WebSocketLink } <span class="hljs-keyword">from</span> <span class="hljs-string">"apollo-link-ws"</span>;
<span class="hljs-keyword">import</span> { InMemoryCache } <span class="hljs-keyword">from</span> <span class="hljs-string">"apollo-cache-inmemory"</span>;

<span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> ApolloClient({
  <span class="hljs-attr">link</span>: <span class="hljs-keyword">new</span> WebSocketLink({
    <span class="hljs-attr">uri</span>: <span class="hljs-string">"wss://your-graphql-endpoint.com/v1/graphql"</span>,
    <span class="hljs-attr">options</span>: {
      <span class="hljs-attr">reconnect</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">connectionParams</span>: {
        <span class="hljs-attr">headers</span>: {
          <span class="hljs-attr">Authorization</span>: <span class="hljs-string">"Bearer yourauthtoken"</span>,
        },
      },
    },
  }),
  <span class="hljs-attr">cache</span>: <span class="hljs-keyword">new</span> InMemoryCache(),
});
</code></pre>
<h3 id="heading-providing-the-client-to-react-components">Providing the client to React components</h3>
<p>After creating a new client, passing it to all components is essential in order to be able to use it within our components to perform all of the available GraphQL operations.</p>
<p>The client is provided to the entire component tree using React Context, but instead of creating our own context, we import a special context provider from <code>@apollo/react-hooks</code> called <code>ApolloProvider</code> . We can see how it differs from the regular React Context due to it having a special prop, <code>client</code>, specifically made to accept the created client.</p>
<p>Note that all of this setup should be done in your index.js or App.js file (wherever your Routes declared) so that the Provider can be wrapped around all of your components. </p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { ApolloProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"@apollo/react-hooks"</span>;

<span class="hljs-keyword">const</span> rootElement = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>);
ReactDOM.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ApolloProvider</span> <span class="hljs-attr">client</span>=<span class="hljs-string">{client}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Switch</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{App}</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/new"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{NewPost}</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">exact</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/edit/:id"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{EditPost}</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Switch</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ApolloProvider</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>,
  rootElement
);
</code></pre>
<h3 id="heading-using-the-client-directly">Using the client directly</h3>
<p>The Apollo client is most important part of the library due to the fact that it is responsible for executing all of the GraphQL operations that we want to perform with React.</p>
<p>We can use the created client directly to perform any operation we like. It has methods corresponding to queries (<code>client.query()</code>), mutations (<code>client.mutate()</code>), and subscriptions (<code>client.subscribe()</code>). </p>
<p>Each method accepts an object and it's own corresponding properties:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// executing queries</span>
client
  .query({
    <span class="hljs-attr">query</span>: GET_POSTS,
    <span class="hljs-attr">variables</span>: { <span class="hljs-attr">limit</span>: <span class="hljs-number">5</span> },
  })
  .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(response.data))
  .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> <span class="hljs-built_in">console</span>.error(err));

<span class="hljs-comment">// executing mutations</span>
client
  .mutate({
    <span class="hljs-attr">mutation</span>: CREATE_POST,
    <span class="hljs-attr">variables</span>: { <span class="hljs-attr">title</span>: <span class="hljs-string">"Hello"</span>, <span class="hljs-attr">body</span>: <span class="hljs-string">"World"</span> },
  })
  .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(response.data))
  .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> <span class="hljs-built_in">console</span>.error(err));

<span class="hljs-comment">// executing subscriptions</span>
client
  .subscribe({
    <span class="hljs-attr">subscription</span>: GET_POST,
    <span class="hljs-attr">variables</span>: { <span class="hljs-attr">id</span>: <span class="hljs-string">"8883346c-6dc3-4753-95da-0cc0df750721"</span> },
  })
  .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(response.data))
  .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> <span class="hljs-built_in">console</span>.error(err));
</code></pre>
<p>Using the client directly can be a bit tricky, however, since in making a request, it returns a promise. To resolve each promise, we either need <code>.then()</code> and <code>.catch()</code> callbacks as above or to <code>await</code> each promise within a function declared with the <code>async</code> keyword.</p>
<h3 id="heading-writing-graphql-operations-in-js-files-gql">Writing GraphQL operations in .js files (gql)</h3>
<p>Notice above that I didn't specify the contents of the variables <code>GET_POSTS</code>, <code>CREATE_POST</code>, and <code>GET_POST</code>. </p>
<p>They are the operations written in the GraphQL syntax which specify how to perform the query, mutation, and subscription respectively. They are what we would write in any GraphiQL console to get and change data.</p>
<p>The issue here, however, is that we can't write and execute GraphQL instructions in JavaScript (.js) files, like our React code has to live in. </p>
<p>To parse the GraphQL operations, we use a special function called a tagged template literal to allow us to express them as JavaScript strings. This function is named <code>gql</code>.</p>
<pre><code class="lang-jsx">
<span class="hljs-comment">// if using apollo-boost</span>
<span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">"apollo-boost"</span>;
<span class="hljs-comment">// else, you can use a dedicated package graphql-tag</span>
<span class="hljs-keyword">import</span> gql <span class="hljs-keyword">from</span> <span class="hljs-string">"graphql-tag"</span>;

<span class="hljs-comment">// query</span>
<span class="hljs-keyword">const</span> GET_POSTS = gql<span class="hljs-string">`
  query GetPosts($limit: Int) {
    posts(limit: $limit) {
      id
      body
      title
      createdAt
    }
  }
`</span>;

<span class="hljs-comment">// mutation</span>
<span class="hljs-keyword">const</span> CREATE_POST = gql<span class="hljs-string">`
  mutation CreatePost($title: String!, $body: String!) {
    insert_posts(objects: { title: $title, body: $body }) {
      affected_rows
    }
  }
`</span>;

<span class="hljs-comment">// subscription</span>
<span class="hljs-keyword">const</span> GET_POST = gql<span class="hljs-string">`
  subscription GetPost($id: uuid!) {
    posts(where: { id: { _eq: $id } }) {
      id
      body
      title
      createdAt
    }
  }
`</span>;
</code></pre>
<h3 id="heading-usequery-hook">useQuery Hook</h3>
<p>The <code>useQuery</code> hook is arguably the most convenient way of performing a GraphQL query, considering that it doesn't return a promise that needs to be resolved.</p>
<p>It is called at the top of any function component (as all hooks should be) and receives as a first required argument—a query parsed with <code>gql</code>.</p>
<p>It is best used when you have queries that should be executed immediately, when a component is rendered, such as a list of data which the user would want to see immediately when the page loads.</p>
<p><code>useQuery</code> returns an object from which we can easily destructure the values that we need. Upon executing a query, there are three primary values will need to use within every component in which we fetch data. They are <code>loading</code>, <code>error</code>, and <code>data</code>.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> GET_POSTS = gql<span class="hljs-string">`
  query GetPosts($limit: Int) {
    posts(limit: $limit) {
      id
      body
      title
      createdAt
    }
  }
`</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { loading, error, data } = useQuery(GET_POSTS, {
    <span class="hljs-attr">variables</span>: { <span class="hljs-attr">limit</span>: <span class="hljs-number">5</span> },
  });

  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
  <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Error!<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-keyword">return</span> data.posts.map(<span class="hljs-function">(<span class="hljs-params">post</span>) =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Post</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{post.id}</span> <span class="hljs-attr">post</span>=<span class="hljs-string">{post}</span> /&gt;</span></span>);
}
</code></pre>
<p>Before we can display the data that we're fetching, we need to handle when we're loading (when <code>loading</code> is set to true) and we are attempting to fetch the data.</p>
<p>At that point, we display a div with the text 'Loading' or a loading spinner. We also need to handle the possibility that there is an error in fetching our query, such as if there's a network error or if we made a mistake in writing our query (syntax error).</p>
<p>Once we're done loading and there's no error, we can use our data in our component, usually to display to our users (as we are in the example above).</p>
<p>There are other values which we can destructure from the object that <code>useQuery</code> returns, but you'll need <code>loading</code>, <code>error</code>, and <code>data</code> in virtually every component where you execute <code>useQuery</code>. You can see a full list of all of the data we can get back from useQuery <a target="_blank" href="https://www.apollographql.com/docs/react/api/react-hooks/#result">here</a>.</p>
<h3 id="heading-uselazyquery-hook">useLazyQuery Hook</h3>
<p>The <code>useLazyQuery</code> hook provides another way to perform a query, which is intended to be executed at some time after the component is rendered or in response to a given data change.</p>
<p><code>useLazyQuery</code> is very useful for things that happen at any unknown point of time, such as in response to a user's search operation.</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Search</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [query, setQuery] = React.useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [searchPosts, { data }] = useLazyQuery(SEARCH_POSTS, {
    <span class="hljs-attr">variables</span>: { <span class="hljs-attr">query</span>: <span class="hljs-string">`%<span class="hljs-subst">${query}</span>%`</span> },
  });
  <span class="hljs-keyword">const</span> [results, setResults] = React.useState([]);

  React.useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!query) <span class="hljs-keyword">return</span>;
    <span class="hljs-comment">// function for executing query doesn't return a promise</span>
    searchPosts();
    <span class="hljs-keyword">if</span> (data) {
      setResults(data.posts);
    }
  }, [query, data, searchPosts]);

  <span class="hljs-keyword">if</span> (called &amp;&amp; loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-keyword">return</span> results.map(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">SearchResult</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{result.id}</span> <span class="hljs-attr">result</span>=<span class="hljs-string">{result}</span> /&gt;</span></span>
  ));
}
</code></pre>
<p><code>useLazyQuery</code> differs from <code>useQuery</code>, first of all, in what's returned from the hook. It returns an array which we can destructure, instead of an object.</p>
<p>Since we want to perform this query sometime after the component is mounted, the first element that we can destructure is a function which you can call to perform that query when you choose. This query function is named <code>searchPosts</code> in the example above.</p>
<p>The second destructured value in the array is an object, which we can use object destructuring on and from which we can get all of the same
properties as we did from <code>useQuery</code>, such as <code>loading</code>, <code>error</code>, and <code>data</code>.</p>
<p>We also get an important property named <code>called</code>,
which tells us if we've actually called this function to perform our query.
In that case, if <code>called</code> is true and <code>loading</code> is true, we want to
return "Loading..." instead of our actual data, because are waiting for the data to be returned. This is how <code>useLazyQuery</code> handles fetching data in a synchronous way without any promises.</p>
<p>Note that we again pass any required variables for the query operation as a property, variables, to the second argument. However, if we need, we can pass those variables on an object provided to the query function itself.</p>
<h3 id="heading-usemutation-hook">useMutation Hook</h3>
<p>Now that we know how to execute lazy queries, we know exactly how to work with the <code>useMutation</code> hook. </p>
<p>Like the <code>useLazyQuery</code> hook, it returns an array which we can destructure into its two elements. In the first element, we get back a function, which in this case, we can call it to perform our mutation operation. For next element, we can again destructure an object which returns to us <code>loading</code>, <code>error</code> and <code>data</code>. </p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { useMutation } <span class="hljs-keyword">from</span> <span class="hljs-string">"@apollo/react-hooks"</span>;
<span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">"apollo-boost"</span>;

<span class="hljs-keyword">const</span> CREATE_POST = gql<span class="hljs-string">`
  mutation CreatePost($title: String!, $body: String!) {
    insert_posts(objects: { body: $body, title: $title }) {
      affected_rows
    }
  }
`</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">NewPost</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [title, setTitle] = React.useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [body, setBody] = React.useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [createPost, { loading, error }] = useMutation(CREATE_POST);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleCreatePost</span>(<span class="hljs-params">event</span>) </span>{
    event.preventDefault();
    <span class="hljs-comment">// the mutate function also doesn't return a promise</span>
    createPost({ <span class="hljs-attr">variables</span>: { title, body } });
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>New Post<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleCreatePost}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(event)</span> =&gt;</span> setTitle(event.target.value)} /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(event)</span> =&gt;</span> setBody(event.target.value)} /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">disabled</span>=<span class="hljs-string">{loading}</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>
          Submit
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        {error &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{error.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Unlike with queries, however, we don't use <code>loading</code> or <code>error</code> in order to conditionally render something. We generally use <code>loading</code> in such situations as when we're submitting a form to prevent it being submitted multiple times, to avoid executing the same mutation needlessly (as you can see in the example above). </p>
<p>We use <code>error</code> to display what goes wrong with our mutation to our users. If for example, some required values to our mutation are not provided, we can easily use that error data to conditionally render an error message within the page so the user can hopefully fix what's going wrong.</p>
<p>As compared to passing variables to the second argument of <code>useMutation</code>, we can access a couple of useful callbacks when certain things take place, such as when the mutation is completed and when there is an error. These callbacks are named <code>onCompleted</code> and <code>onError</code>. </p>
<p>The <code>onCompleted</code> callback gives us access to the returned mutation data and it's very helpful to do something when the mutation is done, such as going to a different page. The <code>onError</code> callback gives us the returned error when there is a problem with the mutation and gives us other patterns for handling our errors.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> [createPost, { loading, error }] = useMutation(CREATE_POST, {
  <span class="hljs-attr">onCompleted</span>: <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Data from mutation"</span>, data),
  <span class="hljs-attr">onError</span>: <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error creating a post"</span>, error),
});
</code></pre>
<h3 id="heading-usesubscription-hook">useSubscription Hook</h3>
<p>The useSubscription hook works just like the useQuery hook. </p>
<p>useSubscription returns an object that we can destructure, that includes the same properties, loading, data, and error. </p>
<p>It executes our subscription immediately when the component is rendered. This means we  need to handle loading and error states, and only afterwards display/use our data.  </p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { useSubscription } <span class="hljs-keyword">from</span> <span class="hljs-string">"@apollo/react-hooks"</span>;
<span class="hljs-keyword">import</span> gql <span class="hljs-keyword">from</span> <span class="hljs-string">"graphql-tag"</span>;

<span class="hljs-keyword">const</span> GET_POST = gql<span class="hljs-string">`
  subscription GetPost($id: uuid!) {
    posts(where: { id: { _eq: $id } }) {
      id
      body
      title
      createdAt
    }
  }
`</span>;

<span class="hljs-comment">// where id comes from route params -&gt; /post/:id</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PostPage</span>(<span class="hljs-params">{ id }</span>) </span>{
  <span class="hljs-keyword">const</span> { loading, error, data } = useSubscription(GET_POST, {
    <span class="hljs-attr">variables</span>: { id },
    <span class="hljs-comment">// shouldResubscribe: true (default: false)</span>
    <span class="hljs-comment">// onSubscriptionData: data =&gt; console.log('new data', data)</span>
    <span class="hljs-comment">// fetchPolicy: 'network-only' (default: 'cache-first')</span>
  });

  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
  <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Error!<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-keyword">const</span> post = data.posts[<span class="hljs-number">0</span>];

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{post.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{post.body}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Just like useQuery, useLazyQuery and useMutation, useSubscription accepts <code>variables</code> as a property provided on the second argument. </p>
<p>It also accepts, however, some useful properties such as <code>shouldResubscribe</code>. This is a boolean value, which will allow our subscription to automatically resubscribe, when our props change. This is useful for when we're passing variables to our you subscription hub props that we know will change. </p>
<p>Additionally, we have a callback function called <code>onSubscriptionData</code>, which enables us to call a function whenever the subscription hook receives new data. Finally, we can set the <code>fetchPolicy</code>, which defaults to 'cache-first'.</p>
<h3 id="heading-manually-setting-the-fetch-policy">Manually Setting the Fetch Policy</h3>
<p>What can be very useful about Apollo is that it comes with its own cache, which it uses to manage the data that we query from our GraphQL endpoint. </p>
<p>Sometimes, however, we find that due to this cache, things aren't updated in the UI in the way that we want. </p>
<p>In many cases we don't, as in the example below, where we are editing a post on the edit page, and then after editing our post, we navigate to the home page to see it in a list of all posts, but we see the old data instead:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// route: /edit/:postId</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">EditPost</span>(<span class="hljs-params">{ id }</span>) </span>{
  <span class="hljs-keyword">const</span> { loading, data } = useQuery(GET_POST, { <span class="hljs-attr">variables</span>: { id } });
  <span class="hljs-keyword">const</span> [title, setTitle] = React.useState(loading ? data?.posts[<span class="hljs-number">0</span>].title : <span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [body, setBody] = React.useState(loading ? data?.posts[<span class="hljs-number">0</span>].body : <span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [updatePost] = useMutation(UPDATE_POST, {
    <span class="hljs-comment">// after updating the post, we go to the home page</span>
    <span class="hljs-attr">onCompleted</span>: <span class="hljs-function">() =&gt;</span> history.push(<span class="hljs-string">"/"</span>),
  });

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleUpdatePost</span>(<span class="hljs-params">event</span>) </span>{
    event.preventDefault();
    updatePost({ <span class="hljs-attr">variables</span>: { title, body, id } });
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleUpdatePost}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(event)</span> =&gt;</span> setTitle(event.target.value)}
        defaultValue={title}
      /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(event)</span> =&gt;</span> setBody(event.target.value)}
        defaultValue={body}
      /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// route: / (homepage)</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { loading, error, data } = useQuery(GET_POSTS, {
    <span class="hljs-attr">variables</span>: { <span class="hljs-attr">limit</span>: <span class="hljs-number">5</span> },
  });

  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
  <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Error!<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-comment">// updated post not displayed, still see old data</span>
  <span class="hljs-keyword">return</span> data.posts.map(<span class="hljs-function">(<span class="hljs-params">post</span>) =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Post</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{post.id}</span> <span class="hljs-attr">post</span>=<span class="hljs-string">{post}</span> /&gt;</span></span>);
}
</code></pre>
<p>This not only due to the Apollo cache, but also the instructions for what data the query should fetch. We can changed how the query is fetched by using the <code>fetchPolicy</code> property. </p>
<p>By default, the <code>fetchPolicy</code> is set to 'cache-first'. It's going to try to look at the cache to get our data instead of getting it from the network. </p>
<p>An easy way to fix this problem of not seeing new data is to change the fetch policy. However, this approach is not ideal from a performance standpoint, because it requires making an additional request (using the cache directly does not, because it is local data). </p>
<p> There are many different options for the fetch policy listed below:</p>
<pre><code class="lang-jsx">{
  <span class="hljs-attr">fetchPolicy</span>: <span class="hljs-string">"cache-first"</span>; <span class="hljs-comment">// default</span>
  <span class="hljs-comment">/* 
    cache-and-network
    cache-first
    cache-only
    network-only
    no-cache
    standby
  */</span>
}
</code></pre>
<p>I won't go into what each policy does exactly, but to solve our immediate problem, if you always want a query to get the latest data by requesting it from the network, we set <code>fetchPolicy</code> to 'network-first'.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> { loading, error, data } = useQuery(GET_POSTS, {
  <span class="hljs-attr">variables</span>: { <span class="hljs-attr">limit</span>: <span class="hljs-number">5</span> },
  <span class="hljs-attr">fetchPolicy</span>: <span class="hljs-string">"network-first"</span>
});
</code></pre>
<h3 id="heading-updating-the-cache-upon-a-mutation">Updating the cache upon a mutation</h3>
<p>Instead of bypassing the cache by changing the fetch policy of <code>useQuery</code>, let's attempt to fix this problem by manually updating the cache. </p>
<p>When performing a mutation with <code>useMutation</code>. We have access to another callback, known as <code>update</code>. </p>
<p><code>update</code> gives us direct access to the cache as well as the data that is returned from a successful mutation. This enables us to read a given query from the cache, take that new data and write the new data to the query, which will then update what the user sees. </p>
<p>Working with the cache manually is a tricky process that a lot of people tend to avoid, but it's very helpful because it saves some time and resources by not having to perform the same request multiple times to update the cache manually. </p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">EditPost</span>(<span class="hljs-params">{ id }</span>) </span>{
  <span class="hljs-keyword">const</span> [updatePost] = useMutation(UPDATE_POST, {
    <span class="hljs-attr">update</span>: <span class="hljs-function">(<span class="hljs-params">cache, data</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> { posts } = cache.readQuery(GET_POSTS);
      <span class="hljs-keyword">const</span> newPost = data.update_posts.returning;
      <span class="hljs-keyword">const</span> updatedPosts = posts.map(<span class="hljs-function">(<span class="hljs-params">post</span>) =&gt;</span>
        post.id === id ? newPost : post
      );
      cache.writeQuery({ <span class="hljs-attr">query</span>: GET_POSTS, <span class="hljs-attr">data</span>: { <span class="hljs-attr">posts</span>: updatedPosts } });
    },
    <span class="hljs-attr">onCompleted</span>: <span class="hljs-function">() =&gt;</span> history.push(<span class="hljs-string">"/"</span>),
  });

  <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>We first want to read the query and get the previous data from it. Then we need to take the new data. In this case, to find the post with a given id and replace it with <code>newPost</code> data, otherwise have it be the previous data, and then write that data back to the same query, making sure that it has the same data structure as before. </p>
<p>After all this, whenever we edit a post and are navigated back to the home page, we should see that new post data.</p>
<h3 id="heading-refetching-queries-with-usequery">Refetching queries with useQuery</h3>
<p>Let's say we display a list of posts using a <code>GET_POSTS</code> query and are deleting one of them with a <code>DELETE_POST</code> mutation.</p>
<p>When a user deletes a post, what do we want to happen?</p>
<p>Naturally, we want it to be removed from the list, both the data and what is displayed to the users. When a mutation is performed, however, the query doesn't know that the data is changed. </p>
<p>There are a few ways of updating what we see, but one approach is to reexecute the query. </p>
<p>We can do so by grabbing the <code>refetch</code> function which we can destructure from the object returned by the <code>useQuery</code> hook and pass it down to the mutation to be executed when it is completed, using the <code>onCompleted</code> callback function:</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Posts</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { loading, data, refetch } = useQuery(GET_POSTS);

  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;

  <span class="hljs-keyword">return</span> data.posts.map(<span class="hljs-function">(<span class="hljs-params">post</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Post</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{post.id}</span> <span class="hljs-attr">post</span>=<span class="hljs-string">{post}</span> <span class="hljs-attr">refetch</span>=<span class="hljs-string">{refetch}</span> /&gt;</span></span>
  ));
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Post</span>(<span class="hljs-params">{ post, refetch }</span>) </span>{
  <span class="hljs-keyword">const</span> [deletePost] = useMutation(DELETE_POST, {
    <span class="hljs-attr">onCompleted</span>: <span class="hljs-function">() =&gt;</span> refetch(),
  });

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleDeletePost</span>(<span class="hljs-params">id</span>) </span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">window</span>.confirm(<span class="hljs-string">"Are you sure you want to delete this post?"</span>)) {
      deletePost({ <span class="hljs-attr">variables</span>: { id } });
    }
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{post.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{post.body}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleDeletePost(post.id)}&gt;Delete<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-refetching-queries-with-usemutation">Refetching Queries with useMutation</h3>
<p>Note that we can also utilize the <code>useMutation</code> hook to reexecute our queries through an argument provided to the mutate function, called <code>refetchQueries</code>. </p>
<p>It accepts an array of queries that we want to refetch after a mutation is performed. Each queries is provided within an object, just like we would provide it to client.query(), and consists of a query property and a variables property. </p>
<p>Here is a minimal example to refetch our <code>GET_POSTS</code> query after a new post is created:</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">NewPost</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [createPost] = useMutation(CREATE_POST, {
    <span class="hljs-attr">refetchQueries</span>: [
      { 
        <span class="hljs-attr">query</span>: GET_POSTS, 
        <span class="hljs-attr">variables</span>: { <span class="hljs-attr">limit</span>: <span class="hljs-number">5</span> } 
      }
    ],
  });

  <span class="hljs-comment">// ...</span>
}
</code></pre>
<h3 id="heading-using-the-client-with-useapolloclient">Using the client with useApolloClient</h3>
<p>We can get access to the client across our components with the help of a special hook called use Apollo client. This execute the hook at the top of our function component and we get back the client itself. </p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Logout</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> client = useApolloClient();
  <span class="hljs-comment">// client is the same as what we created with new ApolloClient()</span>

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleLogout</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// handle logging out user, then clear stored data</span>
    logoutUser();
    client.resetStore().then(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"logged out!"</span>));
    <span class="hljs-comment">/* Be aware that .resetStore() is async */</span>
  }

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleLogout}</span>&gt;</span>Logout<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>;
}
</code></pre>
<p>And from there we can execute all the same queries, mutations, and subscriptions.</p>
<p>Note that there are a ton more features that come with methods that come with the client. Using the client, we can also write and read data to and from the cache that Apollo sets up (using <code>client.readData()</code> and <code>client.writeData()</code>). </p>
<p>Working with the Apollo cache deserves its own crash course in itself. A great benefit of working with Apollo is that we can also use it as a state management system to replace solutions like Redux for our global state. If you want to learn more about using Apollo to manage global app state you can <a target="_blank" href="https://www.apollographql.com/docs/react/data/local-state/">check out the following link</a>.</p>
<p>I attempted to make this cheatsheet as comprehensive as possible, though it still leaves out many Apollo features that are worth investigating. </p>
<p>If you want to more about Apollo, be sure to check out the <a target="_blank" href="https://www.apollographql.com/docs/react/">official Apollo documentation</a>.</p>
<h3 id="heading-download-the-cheatsheet">Download the cheatsheet</h3>
<p>Want a quick reference of all of these concepts?</p>
<p><a target="_blank" href="https://reedbarger.com/resources/react-apollo-2020/"><img src="https://dev-to-uploads.s3.amazonaws.com/i/7herw99hu78t8gspo88d.png" alt="React and Apollo 2020 Cheatsheet" width="762" height="500" loading="lazy"></a><em>Click to grab the complete PDF cheatsheet</em></p>
<h2 id="heading-become-a-professional-react-developer">Become a Professional React Developer</h2>
<p>React is hard. You shouldn't have to figure it out yourself.</p>
<p>I've put everything I know about React into a single course, to help you reach your goals in record time:</p>
<p><a target="_blank" href="https://www.thereactbootcamp.com"><strong>Introducing: The React Bootcamp</strong></a></p>
<p><strong>It’s the one course I wish I had when I started learning React.</strong></p>
<p>Click below to try the React Bootcamp for yourself:</p>
<p><a target="_blank" href="https://www.thereactbootcamp.com"><img src="https://reedbarger.nyc3.digitaloceanspaces.com/reactbootcamp/react-bootcamp-cta-alt.png" alt="Click to join the React Bootcamp" width="600" height="400" loading="lazy"></a>
<em>Click to get started</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The React + GraphQL 2020 Crash Course ]]>
                </title>
                <description>
                    <![CDATA[ Have you heard a lot about using React with GraphQL but don't know how to combine them to build amazing apps? In this crash course, you'll learn how to do just that by building a complete social blogging app.  Within an afternoon, you will gain the c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-react-graphql-2020-crash-course/</link>
                <guid isPermaLink="false">66d037fa386d35c4e3bb3c26</guid>
                
                    <category>
                        <![CDATA[ 2020 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Apollo GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ apollo client ]]>
                    </category>
                
                    <category>
                        <![CDATA[ beginner ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react hooks ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Reed ]]>
                </dc:creator>
                <pubDate>Tue, 30 Jun 2020 13:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/06/React---GraphQL-2020-Crash-Course-Cover--Large--1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you heard a lot about using React with GraphQL but don't know how to combine them to build amazing apps? In this crash course, you'll learn how to do just that by building a complete social blogging app. </p>
<p>Within an afternoon, you will gain the core skills to build your own React and GraphQL projects.</p>
<h2 id="heading-why-you-should-learn-react-with-graphql">Why you should learn React with GraphQL ?</h2>
<p>React is the go-to library for building amazing app experiences with JavaScript. GraphQL, on the other hand, is a tool that gives us a better, more straightforward means of getting and changing our data.</p>
<p>That data could be from a standard database (as we'll be using in our app) or as React frameworks like Gatsby have made possible, even from static files such as markdown files. Regardless of how it's stored, GraphQL makes working with data in our apps better.</p>
<p>We'll see how to leverage the powers of React and GraphQL by creating a social blogging app from start to finish, where you can create, read, edit and delete posts.</p>
<p><a target="_blank" href="https://bit.ly/2020-react-graphql"><img src="https://dev-to-uploads.s3.amazonaws.com/i/o51wpa2tgx9k85p8rse8.gif" alt="Click to access the course" width="1280" height="720" loading="lazy"></a></p>
<p>You can <a target="_blank" href="https://courses.reedbarger.com/p/2020-react-graphql">click here</a> to access the course.</p>
<h2 id="heading-what-tools-well-be-using">What tools we'll be using ?️</h2>
<p>The crash course is meant for developers who are somewhat familiar with React (including the core React Hooks, such as <code>useState</code> and <code>useEffect</code>), but aren't familiar with GraphQL yet.</p>
<p>Basic React knowledge is assumed, but GraphQL knowledge is not required. We'll cover all the core GraphQL concepts you need along the way.</p>
<p>Throughout the course, we'll utilize the following technologies to create our app:</p>
<ul>
<li><strong>React</strong> (to build our user interface)</li>
<li><strong>GraphQL</strong> (to get and change data in a declarative way)</li>
<li><strong>Apollo Client</strong> (to allow us to use React and GraphQL together)</li>
<li><strong>Hasura</strong> (to create and manage our GraphQL API + database)</li>
</ul>
<p>To top it off, we'll be using the online IDE CodeSandbox. This will allow us to code our entire application within the browser in realtime, without the need to create any files, folders, or install dependencies on our own.</p>
<h2 id="heading-creating-a-graphql-api-from-scratch">Creating a GraphQL API from scratch</h2>
<p>To get started working with GraphQL, we'll see how to make an entire GraphQL API from scratch that will communicate with our database. </p>
<p>Fortunately, using the (free) service <strong>Hasura</strong>, this process is very simple and straightforward. Within seconds, we'll see how to create and deploy a complete GraphQL API to the web, which is connected to a Postgres database that will take care of storing our app data.</p>
<p><a target="_blank" href="https://learn.codeartistry.io/courses/2020-react-graphql/lectures/19445637"><img src="https://dev-to-uploads.s3.amazonaws.com/i/ss4wp2tt4ernoe5ukea8.png" alt="Click to access the course" width="1104" height="731" loading="lazy"></a><em>Click to watch this lecture</em></p>
<h2 id="heading-getting-familiar-with-graphql">Getting familiar with GraphQL</h2>
<p>In the second lecture, we'll cover how to write in the GraphQL language using our API's built-in console called <strong>GraphiQL</strong>. </p>
<p>First, we will create a table in our database for all of our posts data. After which, Hasura will automatically create the <strong>queries</strong> and <strong>mutations</strong> we need, which are the names of GraphQL operations that allow us to get and change data in our database. </p>
<p>Throughout this lesson, we'll get very familiar performing queries and mutations in GraphiQL, which will enable us to get entire sets of posts and individual posts, as well as to create, update, and delete our individual post data. </p>
<p><a target="_blank" href="https://learn.codeartistry.io/courses/2020-react-graphql/lectures/19445640"><img src="https://dev-to-uploads.s3.amazonaws.com/i/bo5twcv0hhal7xtj1ksw.png" alt="Click to access the course" width="1280" height="800" loading="lazy"></a><em>Click to watch this lecture</em></p>
<h2 id="heading-connecting-react-with-our-graphql-api-using-apollo-client">Connecting React with our GraphQL API using Apollo Client</h2>
<p>Now that we're comfortable with using GraphQL and understand its core features, we'll see how to connect it with our React client. </p>
<p>The way that we connect our React app with the GraphQL API we created is through a library called <strong>Apollo</strong>. We'll see how to set up the Apollo client, by providing the GraphQL endpoint, which points to our API, like so:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> ApolloClient <span class="hljs-keyword">from</span> <span class="hljs-string">"apollo-boost"</span>;

<span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> ApolloClient({
  <span class="hljs-attr">uri</span>: <span class="hljs-string">"https://react-graphql.herokuapp.com/v1/graphql"</span>
});
</code></pre>
<p>With our newly created client, we have the ability to execute any GraphQL operation through React. To do this, however, we need to pass our client to our entire to all of our React components. We do that with the help of the Apollo provider, as you see below:</p>
<p><a target="_blank" href="https://learn.codeartistry.io/courses/2020-react-graphql/lectures/19445642"><img src="https://dev-to-uploads.s3.amazonaws.com/i/iplsbo37x2oujohn7ulc.png" alt="Click to access the course" width="1280" height="800" loading="lazy"></a><em>Click to watch this lecture</em></p>
<h3 id="heading-getting-posts-with-usequery">Getting posts with useQuery</h3>
<p>After setting up our client, we'll see how to execute different GraphQL operations with them, using some special React hooks that come with the package <code>@apollo/react-hooks</code>.</p>
<p>The hook that allows us to query for data with GraphQL is called <code>useQuery</code>. With it, we'll first see how to get and display all of our post data in our homepage.</p>
<p>Additionally, we'll learn how to write our GraphQL queries directly in our JavaScript files with the help of a special function called <code>gql</code>.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">"@apollo/react-hooks"</span>;
<span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">"apollo-boost"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> GET_POSTS = gql<span class="hljs-string">`
  query getPosts {
    posts {
      id
      title
      body
      createdAt
    }
  }
`</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { data, loading } = useQuery(GET_POSTS);

  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
  <span class="hljs-keyword">if</span> (data.posts.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Empty</span> /&gt;</span></span>;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{classes.header}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{classes.h2}</span>&gt;</span>All Posts<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/new"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{classes.newPost}</span>&gt;</span>
          New Post
        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
      {data.posts.map(post =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">Post</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{post.id}</span> <span class="hljs-attr">post</span>=<span class="hljs-string">{post}</span> /&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-creating-and-editing-new-posts-with-usemutation">Creating and editing new posts with useMutation</h2>
<p>After that, we'll see how to create new posts with the <code>useMutation</code> hook. In order to do this, we'll take a look at how to work with GraphQL variables to pass our mutation dynamic values that will change with each execution. </p>
<p>Following that we'll take a look at how to edit our posts. To do so, we'll need to fetch an individual post and display it within our form, so that our user can make changes to the data. Then we'll need to execute a mutation that will perform the update, based on the posts id. </p>
<p><a target="_blank" href="https://learn.codeartistry.io/courses/2020-react-graphql/lectures/19445643"><img src="https://dev-to-uploads.s3.amazonaws.com/i/n9swv8j0qr962spqxhkx.png" alt="Click to access the course" width="1280" height="800" loading="lazy"></a><em>Click to watch this lecture</em></p>
<h2 id="heading-handle-loading-and-errors">Handle loading and errors</h2>
<p>In the following lecture, we'll cover some essential patterns for handling the process of loading our data. </p>
<p>It's important to do so when we execute a mutation, to make sure we don't submit our forms multiple times as our mutation is being executed. We'll also take a look at how to handle errors in the event that our mutation is not executed correctly. </p>
<p><a target="_blank" href="https://learn.codeartistry.io/courses/2020-react-graphql/lectures/19445638"><img src="https://dev-to-uploads.s3.amazonaws.com/i/548ekws3psm3cbfpqy8e.png" alt="Click to access the course" width="1280" height="800" loading="lazy"></a><em>Click to watch this lecture</em></p>
<h2 id="heading-deleting-posts">Deleting posts</h2>
<p>Finally, we'll cover how to delete posts from our app. First, we'll confirm that the user wants to actually delete the post that they've made, then perform the mutation. </p>
<p>Additionally, we'll take a look at how to update our UI in response to mutations with  the helpful <code>refetch</code> function that Apollo gives us. It will enable us to re-execute a query on demand. In this case, we'll do it after the delete mutation has been successfully performed.</p>
<p><a target="_blank" href="https://learn.codeartistry.io/courses/2020-react-graphql/lectures/19445639"><img src="https://dev-to-uploads.s3.amazonaws.com/i/ojjd4jjxuh0h7p1048ck.png" alt="Click to access the course" width="1280" height="800" loading="lazy"></a><em>Click to watch this lecture</em></p>
<h2 id="heading-become-a-professional-react-developer">Become a Professional React Developer</h2>
<p>React is hard. You shouldn't have to figure it out yourself.</p>
<p>I've put everything I know about React into a single course, to help you reach your goals in record time:</p>
<p><a target="_blank" href="https://www.thereactbootcamp.com"><strong>Introducing: The React Bootcamp</strong></a></p>
<p><strong>It’s the one course I wish I had when I started learning React.</strong></p>
<p>Click below to try the React Bootcamp for yourself:</p>
<p><a target="_blank" href="https://www.thereactbootcamp.com"><img src="https://reedbarger.nyc3.digitaloceanspaces.com/reactbootcamp/react-bootcamp-cta-alt.png" alt="Click to join the React Bootcamp" width="600" height="400" loading="lazy"></a>
<em>Click to get started</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ We Created a Local Free Coding School Using the freeCodeCamp Curriculum. Here's What We Learned. ]]>
                </title>
                <description>
                    <![CDATA[ By Gwendolyn Faraday While this picture shows an in-person classroom, we have moved our school fully remote as a result of the COVID-19 situation. If you want to learn how to code, there are generally three options to choose from: You can teach your... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-we-created-a-free-coding-school-with-the-freecodecamp-curriculum/</link>
                <guid isPermaLink="false">66d45efa7df3a1f32ee7f863</guid>
                
                    <category>
                        <![CDATA[ 2020 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Coding Bootcamps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ education ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learn to code ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 09 Jun 2020 01:53:17 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9a6b740569d1a4ca2582.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Gwendolyn Faraday</p>
<p><em>While this picture shows an in-person classroom, we have moved our school fully remote as a result of the COVID-19 situation.</em></p>
<p>If you want to learn how to code, there are generally three options to choose from:</p>
<ol>
<li>You can teach yourself and find your own curriculum.</li>
<li>Go to college and get a computer science/IT degree.</li>
<li>Or attend a coding school. Coding schools are hands-on crash courses that are designed to get you up to speed quickly so you can find your first software development job within three months to one year.</li>
</ol>
<p>Option number one is the cheapest, but also the most frustrating and difficult. It's so easy to get stuck along the way and want to give up.</p>
<p>Options two and three could work out well, if you can afford to take time off work (or at least work fewer hours), pay the tuition plus living expenses while you are attending and looking for a job, and still be able to manage your family and personal life. Not everyone is able to do that.</p>
<p>This is why we created <a target="_blank" href="https://freecodeschoolindy.com/">freeCodeSchool Indy</a>. It's a free coding program based off of the freeCodeCamp curriculum where we guide students through part-time coding school programs for three months. </p>
<p>We have two two-hour classes per week - Monday and Wednesday from 6-8 pm, where we teach them everything from HTML basics to JavaScript and Intro to React. </p>
<p>The students are expected to spend at least 6 hours per week studying on their own, and can optionally attend office hours on Sundays that we hold from 1-5 pm. If they complete the first three months, then they are able to attend a second three month program, where they can learn about back-end web development in Node.js.</p>
<p>We started working on this idea over a year ago and it's exciting to be able to say that we completed our first cohort in May. Now we can share what we have learned in this article.</p>
<h2 id="heading-our-goal-in-building-a-free-coding-school">Our Goal in Building a Free Coding School</h2>
<p>Our goal from the beginning was to provide accessible, supportive education for everyone regardless of income or life circumstances (like ability to take time off work). </p>
<p>We are not trying to compete with bootcamps or regular coding schools – they also provide a valuable service for students. We are just trying to have another, more accessible option for people who need a more flexible schedule or cannot afford a paid coding school. </p>
<p>Students will receive guidance and direction from the staff, volunteers, and members of the community throughout the program, and as alumni afterward.</p>
<p>Of course, we want our students to be able to get jobs in the industry if that is their goal. But we do not have the resources to guarantee anything. We just want to provide as much support as we can for the students whether they decide to keep learning on their own, or go to a more formal program, like a coding school or college.</p>
<p>Like I mentioned before, it took us about a year to get everything set up - between finding the space and instructors, as well as deciding on the type of program and curriculum. Here is everything that went into our program preparation.</p>
<h2 id="heading-how-we-planned-the-program">How We Planned the Program</h2>
<p>The first things we did were choose the length of time and goals for the program. We landed on having three-month-long classes where the students would learn the basics of HTML, CSS, and JS, with some extras like Bootstrap and React Components.</p>
<p>If everything went well, our goal was to take a month off and host a level two course for the students who completed the first one. Level two would be another three months where we would build off of what we taught in level one and teach more about JavaScript frameworks and introduce Node.js.</p>
<p>Starting small with just a three month part-time program helped us to be able to learn and make adjustments as we went along. It also gave the students a short, time-based goal to be able to complete the program and have a small portfolio in just a few months.</p>
<p><a target="_blank" href="https://github.com/freecodeschoolindy">Here is our organization on Github</a>. We are in the process of updating and open-sourcing our material as we go along.</p>
<h2 id="heading-adopting-freecodecamps-curriculum">Adopting freeCodeCamp's Curriculum</h2>
<p>Curriculum development is time consuming and expensive. Fortunately, freeCodeCamp already has an awesome free curriculum that we can use and modify with no strings attached.</p>
<p>We took freeCodeCamp's curriculum and followed it as an outline for our lectures. We used the challenges as assignments for students to complete between classes. We also used freeCodeCamp's projects as individual and group assignments along the way. </p>
<p>Throughout the lessons, we also encouraged students to try to do a little bit of extra work to be able to get their freeCodeCamp certifications during, or after the end of, the program.</p>
<h2 id="heading-how-we-found-a-space-to-host-classes">How We Found a Space to Host Classes</h2>
<p>The Indianapolis Public Library generously agreed to host our classes and give us space for office hours as well. The size of the space in the computer lab was limited, so the maximum number of students we could take per class was 22.</p>
<p>We could have used a larger conference room in the library to accommodate a larger class, but then we wouldn't have been able to take students who didn't own a laptop – and that wouldn't have been very accessible for everyone.</p>
<p>We didn't plan to be a remote program, so we had to adjust our classes to use Discord for lectures and all student communication when COVID-19 happened. More on that later.</p>
<h2 id="heading-how-we-chose-technology-tools">How we Chose Technology Tools</h2>
<p>We prepared a Discourse forum (like the freeCodeCamp forum) before the classes started so students could log in, get announcements, ask questions, and post assignments. It also gave the admin staff some privileges to keep track of students and moderate student interactions.</p>
<h2 id="heading-how-we-administered-the-school">How we Administered the School</h2>
<h3 id="heading-finding-students">Finding Students</h3>
<p>When we were planning this program, our worry was that we would not get enough interest and all our planning would be for nothing. The reality was that we had way too much interest and could not accommodate every student. For 22 slots, we had over 140 people who wanted to participate! And that was without doing that much marketing.</p>
<p>It was very exciting to get so much interest in our program, but we also had to decide which students to take and how to choose in a fair way.</p>
<p>We decided to whittle down the field by requiring people to show up for three pre-screening activities where they would complete some basic challenges, like <a target="_blank" href="https://studio.code.org/flappy/1">Code.org's Flappy Game</a>. This let us know which students were dedicated to showing up and got the number of people in line down to around 80. That was still too way too many for the space we had so had to do a random lottery to select the final students.</p>
<h3 id="heading-teaching-students">Teaching Students</h3>
<p>Every student learns differently and has their own personality and preferences. It's unreasonable to expect that we can just lecture the students for an hour and they will all be able to pick up all that information and build the lab without issue. </p>
<p>We decided on a format for lectures where we start off every lecture by asking if anyone has questions – usually we don't get many. Then, we go into the slides, and pause every ~15 minutes to give the students guided 'labs' so they can try out coding on their own with the support of having instructions and still being able to ask questions in the classroom.</p>
<p>We also often leave the last 30+ minutes of the 2-hours classes for the students to be able to work on their class projects.</p>
<h3 id="heading-collecting-assignments">Collecting Assignments</h3>
<p>Some people don't turn in assignments. This could mean they are shy about sharing their code where other students can see, or that they just don't think it's necessary since it's a free coding school after all, and some of their classmates aren't doing it either. </p>
<p>If it's the former, then we encourage them to share assignments with just the staff and let them know that we have all been in their shoes before. </p>
<p>If they aren't turning in assignments because they don't want to... well, there isn't much we can do about that. We try to discourage students from joining the class who don't want to fully participate in the program.</p>
<p>The assignments were originally being turning in on the forum, but we were getting really low engagement on there. Students weren't logging in very often and they were never asking questions there. </p>
<p>Now assignments are turned in via a Discord channel on the server we have for our coding school. </p>
<p>Since we manage our whole program from the same Discord server – including hosting lectures, answering questions, and managing the program – we are seeing an increase in the number of assignments turned in. We are also getting more useful feedback that students are getting from staff and volunteers.</p>
<h3 id="heading-deadlines">Deadlines</h3>
<p>Should we have deadlines for turning in projects? Our opinion right now is no, we shouldn't. </p>
<p>Most of the first cohort got a bit behind and some of them finished the program weeks after the end. Should we punish people who finish, but just not on time? We don't think so and here is why: Everyone learns at their own pace. </p>
<p>If someone finishes in 3 months and another student in 4 months, then they both should be rewarded the same for completing the program. </p>
<p>Someday, we will be able to have rolling admissions for our coding and help students at a more granular level. Until then, the least we can do is stay flexible to accommodate them and let them turn in the rest of the projects whenever they can.</p>
<h3 id="heading-getting-students-to-ask-for-help">Getting Students to Ask for Help</h3>
<p>This has been one of our biggest problems! Some people fall behind and some students are confused but don't want to ask for help. Some students are so confused that they don't even know what kind of help to ask for. </p>
<p>You can't really force people to get help, but you can prompt them. The best way we have found to get them to ask questions is to do short review segments at the beginning of lectures and have scheduled study times where students can pop in and ask questions in a much smaller group setting. </p>
<p>If they prefer to type out the question, they can post it in the student chat or send a private message to one of the organizers.</p>
<p>We can only do so much. If students are lost or confused and don't want to ask for help, there is no way for us to fix that. We try hard to meet them where they are, but they also have to make some effort to come to us.</p>
<h3 id="heading-student-surveys">Student Surveys</h3>
<p>Performing regular student surveys is really helping us to get critical feedback for our program. </p>
<p>Our first time through, we collected information about student goals and background at the beginning, then took a student survey at the half-way point - around 6 weeks in – and then another survey at the end. </p>
<p>While we received a lot of good information, in hindsight, we should have taken more surveys and added a few more questions. This time, we will probably perform surveys to get student feedback every month. Here are some of the questions we are asking:</p>
<ol>
<li>What do you think about the program so far? Is it meeting your expectations?</li>
<li>Do you feel like the lectures are helpful for doing the assignments?</li>
<li>How can we better help you achieve your goals?</li>
<li>Do you have any other feedback for us?</li>
</ol>
<h3 id="heading-dealing-with-drop-outs">Dealing with Drop Outs</h3>
<p>Life happens, things change. We have to understand that students who fully intend to participate might have to drop out due to unavoidable circumstances. </p>
<p>If they communicate with us about the situation, we offer them a spot in the next cohort. </p>
<p>If they simply do not show up or communicate with us, then they are free to reapply in the future, but no spot will be saved for them.</p>
<h2 id="heading-staff-and-volunteers">Staff and Volunteers</h2>
<h3 id="heading-soliciting-volunteers">Soliciting Volunteers</h3>
<p>Without volunteers, it would be quite overwhelming to run a program like this. Here are some of the different types of volunteers you will need to be successful.</p>
<h3 id="heading-responsibilities">Responsibilities:</h3>
<ol>
<li><strong>Organizers –</strong> Yes, we are volunteers too. We are fortunate to have an amazing team of organizers who run the program. This includes myself, two other developers, and a computer lab supervisor from the library who also knows how to code. We chat several times per week in Discord to make sure the program is running smoothly and students are progressing. I think 3-5 is a pretty good number for an organizing team, but we might add more to do specific things, such as 'community manager' or 'volunteer coordinator.'</li>
<li><strong>Presenters –</strong> These people give lectures during class times or special help sessions held on weekends usually. This is the hardest type of volunteering to manage. In our program, the lectures are 1.5-2 hours long and there are only 24 of them, so every single one has to be on point and flow with the rest of the curriculum. Some well-meaning volunteers might not be the right fit for giving lectures for people who are brand new to development. It is <strong>very</strong> important to be clear about what you want them to cover in the lecture, down to the individual points and expected learning outcomes. We also made sure to give volunteers a boilerplate slide deck to work off of so it matched the rest of the curriculum.</li>
<li><strong>Mentors –</strong> Students will not only have coding questions, but also have questions about their careers, networking, etc. Mentorship is great for answering these types of questions. We are currently working on setting up our mentorship program where volunteer mentors will check in with students at least once per week to make sure they are on track and answer any questions they have. One of the reasons for the delay is we have been working on a system for how to handle any complaints of inappropriate language or behavior that might take place when students meet one on one with volunteers.</li>
<li><strong>Lab Assistants –</strong> Lab assistants are there to help out synchronously during live lab sessions, usually with problems running software or debugging. We utilized lab assistants much more when we held in-person classes. With things being remote, we can't see the students' screens so we have had to just have a few people available to answer questions in the chat if people get stuck.</li>
<li><strong>General Helpers –</strong> These people help answer students' questions in the chat and perform other tasks like reviewing projects and portfolios. They are also useful for students to rubber duck off of or for encouragement.</li>
</ol>
<h3 id="heading-volunteer-handbook">Volunteer Handbook</h3>
<p>We made a two-page handbook detailing expectations for volunteer behavior as well as requirements for participation in our program. It's pretty basic right now, but we will be building off of it as we go along I'm sure. </p>
<p>We also give them a link to the <a target="_blank" href="https://www.freecodecamp.org/news/code-of-conduct/">freeCodeCamp code of conduct</a> because it's short, sweet, and to the point: be kind, understanding, etc.</p>
<h3 id="heading-making-sure-staff-has-the-tools-to-succeed">Making Sure Staff has the Tools to Succeed</h3>
<p>We have definitely made a few mistakes, including letting a presenter make his own slides and then having to tell him at the last minute that they needed to change. It didn't go over well. We should have been much clearer with what we wanted from him. </p>
<p>Now, everyone receives a boilerplate slide deck from us as well as a list of topics to cover. We also connect with them several times to go over the progress in their presentation to make sure it's on the right track.</p>
<p>Right now, we have a volunteer handbook, lesson plans and slide decks for teaching, guidelines for mentoring, and google drive folder where we keep all of the documentation for the program, student progress, curriculum materials, and future plans. We recently re-organized all of these materials to make them easier to locate when we need them.</p>
<p>As this program grows, we are going to need to manage more volunteers and even paid staff. We are preparing for this by documenting our processes to make onboarding a little bit smoother each time.</p>
<h3 id="heading-community-partners">Community Partners</h3>
<p>We are currently trying to form community partnerships to get sponsors for funding as well as donations of tech equipment. </p>
<p>Some of our students don't have access to good computers or a fast internet connection. The library provided those things for us when we hosted in person classes, but it's been more difficult now that we are remote. </p>
<p>Also, libraries only have limited hours, and, for students who work multiple jobs or have other family obligations, it can be difficult to make the time to do all of the class work during the day. This is why the sponsorship of community partners is so important to making our program accessible.</p>
<p>In the future, we hope to be able to provide internet access and laptop computers for students who need them.</p>
<h2 id="heading-organizing">Organizing</h2>
<h3 id="heading-marketing">Marketing</h3>
<p>We don't have any marketing experts on our team. Our marketing efforts basically consist of making sure we keep our branding that we agreed upon - colors, verbiage, etc. - consistent and collectively sharing updates on social media.</p>
<p>Fortunately, I have a small following on <a target="_blank" href="https://www.youtube.com/c/FaradayAcademy">YouTube</a>, LinkedIn, and other platforms where I have been able to solicit volunteers and get some community interest in our program. </p>
<p>The public library has also been helpful with reaching out to many different communities and pulling in students that we might never have been able to reach otherwise.</p>
<p>As we grow, we might start expanding our social media reach, but with a limited budget right now, we are just gaining traction organically.</p>
<h3 id="heading-remote-livestreams">Remote Livestreams</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screen-Shot-2020-06-08-at-10.10.27-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Discord screen sharing interface.</em></p>
<p>Hosting remote livestreams has been challenging. Internet connections sometimes drop, plus there is a learning curve for students to be able to use the software.</p>
<p>Discord has been a great option for us, because we can host livestreams inside of the app where all of our chats and everything else are located. This way, we only have to explain how to use one piece of software. </p>
<p>In addition, Discord allows us to screen share with up to 50 people at a time in the voice chat rooms. And that's all for free! We looked into Zoom and some other tools, but we are going to stick with Discord until we need - and can afford - something with more features.</p>
<h3 id="heading-incorporating-amp-funding">Incorporating &amp; Funding</h3>
<p>We wanted to start asking companies and people for funding so we had to incorporate as a non-profit last year. In the US, this process takes about six months. We first had to register as a company with our state and then draw up business documents and apply for non-profit status with the federal government.</p>
<p>At the beginning of this year, we finally got confirmation that we are a 501c3 non-profit organization! Now we are trying to work out ways of getting funding and taking donations. We're going to add a 'donate' button to our website and we are also reaching out to companies to solicit larger donations. There have also been some internal discussions about whether or not crowdfunding is a good idea.</p>
<p>Do you have any suggestions for us in this area? Please leave a comment on this article or reach out to us at contact@freecodeschoolindy.com.</p>
<h2 id="heading-communication-tools">Communication Tools</h2>
<h3 id="heading-forum">Forum</h3>
<p>As previously mentioned, we started off using a Discourse forum, but found that it was hard to maintain and wasn't meeting our needs. People found it hard to use, especially on mobile. We also had trouble getting staff and students to login and check it often enough to make it worth the effort. That is why we got rid of the forum and moved our whole program over to Discord.</p>
<h3 id="heading-discord">Discord</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screen-Shot-2020-06-04-at-12.43.36-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We now have a Discord server set up for the whole coding school! We use it to host live lectures - we can have up to 50 people in the voice chat and screen share with them at the same time, manage students, organize volunteer activities, coach speakers, answer questions, do group projects, review portfolios, and perform administrative tasks.</p>
<p>Having everything in one place has been the best decision we have ever made. Not only are our costs lower, but it makes the program administration so much easier. Everyone we need to interact with is either already on Discord, or just needs to be invited to Discord :)</p>
<h2 id="heading-graduation">Graduation</h2>
<p>We had grand plans of doing our first in-person graduation for students this year. Unfortunately, due to COVID-19, those plans had to be scrapped. We had to make do with mailing out certificates to students who completed the program and giving everyone a (virtual) pat on the back for finishing.</p>
<p>Now that our classes are virtual, we would love to be able to do something fun for the graduation of our second cohort at the end of August. Do you have any ideas? Let us know if you do.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Putting this program together might have been the hardest thing I've ever done. It's a lot of work but very rewarding. It can be life-changing for students. </p>
<p>It wasn't just me though: There was a team of people helping out and none of this would have happened without them. </p>
<p>I want to give special thanks to <a target="_blank" href="https://thejaredwilcurt.com/">Jared Wilcurt</a>, Casssandra Bautista, Marianne Mckenzie, <a target="_blank" href="https://www.indypl.org/">The Indianapolis Public Library</a>, freeCodeCamp, and all of our wonderful volunteers – all of whom were crucial in putting this program together.</p>
<p>We are working on open-sourcing our curriculum we used – slides, projects, freeCodeCamp challenges, supplementary material, and so on. It's taking a little bit of time to put everything together in a nice format, but be patient, we will get it out to anyone who is interested soon :)</p>
<p>I'm interested in your thoughts. Do you have any ideas for things we can do better next time around? Please reach out to me and let me know.</p>
<p>My Twitter: <a target="_blank" href="https://twitter.com/gwen_faraday">@gwen_faraday</a></p>
<p>My YouTube: <a target="_blank" href="https://www.youtube.com/c/FaradayAcademy">Faraday Academy</a></p>
<p>Program Website: <a target="_blank" href="https://freecodeschoolindy.com/">freecodeschoolindy.com</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Todo API in Deno and Oak ]]>
                </title>
                <description>
                    <![CDATA[ By Adeel Imran I am a JavaScript/Node developer who secretly likes (actually, loves and adores) Deno. I have been a huge fan of Deno ever since it was announced and I've been wanting to play with it.  This tutorial focuses on creating a set of REST A... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-a-todo-api-in-deno-written-by-a-guy-coming-from-node/</link>
                <guid isPermaLink="false">66d45d5d51f567b42d9f8413</guid>
                
                    <category>
                        <![CDATA[ 2020 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Deno ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Middleware ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 29 May 2020 11:33:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9ab6740569d1a4ca273d.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Adeel Imran</p>
<p>I am a JavaScript/Node developer who secretly likes (actually, loves and adores) Deno. I have been a huge fan of Deno ever since it was announced and I've been wanting to play with it. </p>
<p>This tutorial focuses on creating a set of REST APIs for a Todo application. Keep in mind that I did not touch on the database here – I will cover that <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-mysql-in-deno-oak/">in another article</a>.</p>
<p>At any point if you feel lost or want to check a reference, here is the entire source code of this tutorial: <strong><a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">Chapter 1: Oak</a>.</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/image-171.png" alt="Image" width="600" height="400" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@bernardtheclerk?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Bernard de Clerk / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<h3 id="heading-things-we-will-cover">Things we will cover</h3>
<ul>
<li>Create a basic server</li>
<li>Create 5 APIs (routes/controller)</li>
<li>Create a middleware to log API requests as they are made in the console</li>
<li>Create a not found (404) middleware when the user tries to access an unknown API</li>
</ul>
<h3 id="heading-what-will-we-need">What will we need</h3>
<ul>
<li>An installed version of Deno (don't worry I'll walk you through it)</li>
<li>A tiny bit of knowledge of Typescript</li>
<li>Would be awesome if you have worked with Node/Express before (don't worry if you haven't — this tutorial is very basic)</li>
</ul>
<h2 id="heading-lets-get-started">Let's get started</h2>
<p>First things first let's install Deno. I am on a Mac computer so I am using brew. Simply open your terminal and type:</p>
<pre><code>$ brew install deno
</code></pre><p>But if you are using a different operating system, just head over to <a target="_blank" href="https://deno.land/#installation"><strong>deno.land installation</strong></a><strong>.</strong> They have a lot of ways you can easily install it on your machine.</p>
<p>Once you have it installed, close the terminal, open a new one, and type:</p>
<pre><code>$ deno --version
</code></pre><p>It should output something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-28-at-22.34.24.png" alt="Image" width="600" height="400" loading="lazy">
<em>running command "deno --version" to see which version of deno is installed</em></p>
<p>Awesome! With this we are almost done with 10% of this tutorial. </p>
<p>Let's move ahead and create the backend API for our Todo app.</p>
<h3 id="heading-setting-up-the-project">Setting up the project</h3>
<p>Before you move on, here is the entire source code of this tutorial: <strong><a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">Chapter 1: Oak</a>.</strong></p>
<p>Let's get started:</p>
<ul>
<li>Create a new folder and call it <strong>chapter_1:oak</strong> (but you can call it anything you want)</li>
<li>Once you create a folder simply <code>cd</code> into your new project. Create a file called <strong>server.ts</strong> and write the following code in it:</li>
</ul>
<pre><code class="lang-server.ts">import { Application } from "https://deno.land/x/oak/mod.ts";

const app = new Application();
const port: number = 8080;

console.log('running on port ', port);
await app.listen({ port });
</code></pre>
<p>Let's run this file. Open your terminal and in your project root folder type:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>I will talk about what the <code>--allow-net</code> flag does, but for now just bear with me ?.</p>
<p>You should get something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-28-at-22.33.28.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>What we have done so far is create a server which listens on port 8080. It doesn't do much right now besides being able to run on port 8080.</p>
<p>If you have used JavaScript before, one thing you might have noticed is we are importing packages in a different way. We have to do something like:</p>
<pre><code><span class="hljs-keyword">import</span> { Application } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/x/oak/mod.ts"</span>;
</code></pre><p>When you run <code>deno run ---allow-net &lt;file_name&gt;</code> in your terminal, Deno will look at all your imports and install them locally in your machine if they are not there. </p>
<p>The first time you run this it will go to this URL <code>https://deno.land/x/oak/mod.ts</code> and install the <code>oak</code> package. Oak is basically a Deno framework for writing API's. It will put it somewhere locally in your cache.</p>
<p>In the next line we do this:</p>
<pre><code><span class="hljs-keyword">const</span> app = <span class="hljs-keyword">new</span> Application();
</code></pre><p>This creates a new instance of our application, and it will be the basis of everything as you progress further in this tutorial. You can add routes to the application instance, attach middleware like API logging, write a 404 not found, and so on.</p>
<p>Then we write:</p>
<pre><code><span class="hljs-keyword">const</span> port: number = <span class="hljs-number">8080</span>;
<span class="hljs-comment">// const port = 8080; // =&gt; can also be written like this</span>
</code></pre><p>Both are the same and do the same thing. The only difference is writing <code>const port: number = 8080</code> tells Typescript that <code>port</code> variable is of type number.</p>
<p>If you were to write <code>const port: number = "8080"</code>, this would throw an error in your terminal, as port is of type <code>number</code>. But we are trying to assign it a <code>string</code> of value "8080". </p>
<p>If you want to learn more about different types of types (pun intended) check out this very easy and basic guide on <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/basic-types.html"><strong>Basic types by Typescript</strong></a>. Just give it a quick glance for 2-3 minutes and head back here.</p>
<p>And in the end we have:</p>
<pre><code><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'running on port '</span>, port);
<span class="hljs-keyword">await</span> app.listen({ port });
</code></pre><p>We simply console here the port number and tell Deno to listen to the port, which is 8080.</p>
<p>It isn't doing much right now. Let's make it do something basic like show a <em>JSON</em> message in your browser when you go to http:localhost:8080<em>.</em></p>
<p>Add the following to your <strong>server.ts</strong> file:</p>
<pre><code class="lang-server.ts">import { Application, Router } from "https://deno.land/x/oak/mod.ts";

const app = new Application();
const port: number = 8080;

const router = new Router();
router.get("/", ({ response }: { response: any }) =&gt; {
  response.body = {
    message: "hello world",
  };
});
app.use(router.routes());
app.use(router.allowedMethods());

console.log('running on port ', port);
await app.listen({ port });
</code></pre>
<p>The new thing added here is that we are now also importing <code>Router</code> along with <code>Application</code> from <code>oak</code> in line 1.</p>
<p>Next what we do is:</p>
<pre><code><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> Router();
router.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">{ response }: { response: any }</span>) =&gt;</span> {
  response.body = {
    <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world"</span>,
  };
});
app.use(router.routes());
app.use(router.allowedMethods());
</code></pre><p>We create a new router instance by doing <code>const router = new Router()</code> and then we create a new route called <code>/</code> which is of type <code>get</code>.</p>
<p>Let's break this down:</p>
<pre><code>router.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">{ response }: { response: any }</span>) =&gt;</span> {
  response.body = {
    <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world"</span>,
  };
});
</code></pre><p><code>router.get</code> takes 2 parameters. The first is route which we have set to <code>/</code> and the second is function. The function itself takes an argument which is an object. What I am doing here is <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">destructuring</a> the object and getting only <code>response</code>.</p>
<p>Next I am type checking <code>response</code> similar to how I did <code>const port: number = 8080;</code>. All I am doing is <code>{ response }: { response: any }</code> which is telling TypeScript here that the <code>response</code> which I have destructed can be of type <code>any</code>.</p>
<p><code>any</code> helps you avoid type checking in TypeScript. You can read more about it <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/basic-types.html#any">here</a>.</p>
<p>Then all I am doing is taking that <code>response</code> object and setting <code>response.body.message = "hello world";</code>.</p>
<pre><code>response.body = {
  <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world"</span>,
};
</code></pre><p>Last but not least, we just add these two lines:</p>
<pre><code>app.use(router.routes());
app.use(router.allowedMethods());
</code></pre><p>This tells Deno to include all routes by our router (currently we only have one) and the next line tells Deno to allow all methods for this route(s) like <code>GET, POST, PUT, DELETE</code>.</p>
<p>And now we are done. ✅ Let's run this and see what we have:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>The <code>---allow-net</code> property tells Deno that this app gives the user the permission to access its content via the port opened up.</p>
<p>Now open your favorite browser and go to <code>http://localhost:8080</code>. You will see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-28-at-23.11.08.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of running localhost:8080 on your browser</em></p>
<p>Honestly the hardest part is done. Conceptually we are 60% there.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/images.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Master Yoda approves</em></p>
<p>Awesome.</p>
<p>Just one last thing before we start with our Todo API. Let's replace:</p>
<pre><code><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'running on port '</span>, port);
<span class="hljs-keyword">await</span> app.listen({ port });
</code></pre><p>with:</p>
<pre><code class="lang-server.ts">app.addEventListener("listen", ({ secure, hostname, port }) =&gt; {
  const protocol = secure ? "https://" : "http://";
  const url = `${protocol}${hostname ?? "localhost"}:${port}`;
  console.log(`Listening on: ${port}`);
});

await app.listen({ port });
</code></pre>
<p>The code we had before was not very accurate, because we were simply console logging a message and then waiting for the app to start listening on a port.</p>
<p>With the later version we wait for the app to start listening on <code>port</code> and we can listen by adding an event listener to our <code>app</code> instance with the following: <code>app_.addEventListener_("listen", ({ secure, hostname, port }) =&gt; {}</code>. </p>
<p>The first param is the event we want to listen for (which is <code>listen</code> ?) and then the second param is an object which we destruct to <code>{ secure, hostname, port }</code>. Secure is a boolean, hostname is a string, and port is a number.</p>
<p>Now when we start our app, it will only console the message once the app actually starts listening on port.</p>
<p>We can just go one step ahead and make it more colorful. Let's add a new module to the top of the file in <code>server.ts</code>:</p>
<pre><code><span class="hljs-keyword">import</span> { green, yellow } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/std@0.53.0/fmt/colors.ts"</span>;
</code></pre><p>And then inside our event listener method we can replace:</p>
<pre><code><span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening on: <span class="hljs-subst">${port}</span>`</span>);
</code></pre><p>with:</p>
<pre><code><span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${yellow(<span class="hljs-string">"Listening on:"</span>)}</span> <span class="hljs-subst">${green(url)}</span>`</span>);
</code></pre><p>Now when we do:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>it will show this in our console:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-28-at-23.34.29.png" alt="Image" width="600" height="400" loading="lazy">
<em>Cool, now we have a colourful console.</em></p>
<p>If you get stuck anywhere you can simply go to the source code of this tutorial <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak"><strong>here</strong></a>.</p>
<p>Let's create our Todo API's routes next.</p>
<ul>
<li>Create a new folder in your root folder called <code>routes</code> and inside that folder create a file called <code>todo.ts</code></li>
<li>At the same time in your root folder create a new folder called <code>controllers</code> and inside that folder create a file called <code>todo.ts</code></li>
</ul>
<p>Let's first touch the <code>controllers/todo.ts</code> file:</p>
<pre><code class="lang-controllers/todo.ts">export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>We are simply exporting an object here with some named functions which are empty (for now).</p>
<p>Next go inside your file <code>routes/todo.ts</code> and type this:</p>
<pre><code class="lang-routes/todo.ts">import { Router } from "https://deno.land/x/oak/mod.ts";

const router = new Router();
// controller
import todoController from "../controllers/todo.ts";

router
  .get("/todos", todoController.getAllTodos)
  .post("/todos", todoController.createTodo)
  .get("/todos/:id", todoController.getTodoById)
  .put("/todos/:id", todoController.updateTodoById)
  .delete("/todos/:id", todoController.deleteTodoById);

export default router;
</code></pre>
<p>This might look familiar to people who have worked with Node and Express. </p>
<p>All we are doing here is importing <code>Route</code> from <code>oak</code> and then setting up a new instance of Router by doing <code>const router = new Router();</code>.</p>
<p>Next we import our controllers by doing:</p>
<pre><code><span class="hljs-keyword">import</span> todoController <span class="hljs-keyword">from</span> <span class="hljs-string">"../controllers/todo.ts"</span>;
</code></pre><p>One thing to notice here in Deno is every time we import a local file in our Deno project we have to provide the file extension. This is because Deno doesn't know whether the file being imported is a <code>.js</code> or <code>.ts</code> file.</p>
<p>Moving forward we simply set all of our routes according to REST conventions:</p>
<pre><code class="lang-routes/todo.ts">router
  .get("/todos", todoController.getAllTodos)
  .post("/todos", todoController.createTodo)
  .get("/todos/:id", todoController.getTodoById)
  .put("/todos/:id", todoController.updateTodoById)
  .delete("/todos/:id", todoController.deleteTodoById);
</code></pre>
<p>The code above will translate to our API definition like this:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>TYPE</td><td>API ROUTE</td><td></td><td></td><td></td></tr>
</thead>
<tbody>
<tr>
<td>GET</td><td>/todos</td><td></td><td></td><td></td></tr>
<tr>
<td>GET</td><td>/todos/:id</td><td></td><td></td><td></td></tr>
<tr>
<td>POST</td><td>/todos</td><td></td><td></td><td></td></tr>
<tr>
<td>PUT</td><td>/todos/:id</td><td></td><td></td><td></td></tr>
<tr>
<td>DELETE</td><td>/todos/:id</td><td></td><td></td></tr>
</tbody>
</table>
</div><p>and at the end we simply export our router by doing <code>_export_ _default_ router;</code>.</p>
<p>We are done with creating our routes structure. (Now, each route doesn't do anything because our controllers are empty, we will add functionality to them in a bit.)</p>
<p>Here's the last piece of the puzzle before we start adding functionality to each route controller. We need to attach this <code>router</code> to our <code>app</code> instance.</p>
<p>So head over to <code>server.ts</code> file and do the following:</p>
<ul>
<li>Add this to the very top:</li>
</ul>
<pre><code><span class="hljs-comment">// routes</span>
<span class="hljs-keyword">import</span> todoRouter <span class="hljs-keyword">from</span> <span class="hljs-string">"./routes/todo.ts"</span>;
</code></pre><ul>
<li>Remove this piece of code:</li>
</ul>
<pre><code><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> Router();
router.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">{ response }: { response: any }</span>) =&gt;</span> {
  response.body = {
    <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world"</span>,
  };
});
app.use(router.routes());
app.use(router.allowedMethods());
</code></pre><ul>
<li>Replace it with:</li>
</ul>
<pre><code>app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());
</code></pre><p>This is it – we are done. Your <code>server.ts</code> file should look like this now:</p>
<pre><code class="lang-server.ts">import { Application } from "https://deno.land/x/oak/mod.ts";
import { green, yellow } from "https://deno.land/std@0.53.0/fmt/colors.ts";

// routes
import todoRouter from "./routes/todo.ts";

const app = new Application();
const port: number = 8080;

app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());

app.addEventListener("listen", ({ secure, hostname, port }) =&gt; {
  const protocol = secure ? "https://" : "http://";
  const url = `${protocol}${hostname ?? "localhost"}:${port}`;
  console.log(
    `${yellow("Listening on:")} ${green(url)}`,
  );
});

await app.listen({ port });
</code></pre>
<p>If you got stuck anywhere while following this, simple head over to the source code of this tutorial <strong><a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">here</a>.</strong></p>
<p>Awesome, now we have our routes with no functionality at the moment. So let's add that functionality in our controllers.</p>
<p>But before we do that we have to create 2 more (tiny) files.</p>
<ul>
<li>In your root folder create a new folder called <code>interfaces</code> and inside that folder create a file called <code>Todo.ts</code> (make sure Todo is capitalized, as it won't give any syntax error here if you don't – these are just conventions.)</li>
<li>Also in your root folder create a new folder called <code>stubs</code> and inside that folder create a file called <code>todos.ts</code></li>
</ul>
<p>Let's create an interface in our <code>interfaces/Todo.ts</code> file. Simply add the following code:</p>
<pre><code class="lang-interfaces/todo.ts">export default interface Todo {
  id: string,
  todo: string,
  isCompleted: boolean,
}
</code></pre>
<p>What is an interface?</p>
<p>One of the core things in TypeScript is checking the shape that value has. Similar to <code>const port: number = 8080</code> or <code>{ response }: { response : any }</code>, we can also type check an object. </p>
<p>In TypeScript, interfaces fill the role of naming these types, and are a powerful way of <strong>defining contracts within</strong> your code as well as <strong>contracts with code outside</strong> of your project. </p>
<p>Here is an another example of an interface:</p>
<pre><code class="lang-ts"><span class="hljs-comment">// We have an interface</span>
<span class="hljs-keyword">interface</span> LabeledValue {
  label: <span class="hljs-built_in">string</span>;
}

<span class="hljs-comment">// the arg passed to this function labeledObj is </span>
<span class="hljs-comment">// of type LabeledValue (interface)</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">printLabel</span>(<span class="hljs-params">labeledObj: LabeledValue</span>) </span>{
  <span class="hljs-built_in">console</span>.log(labeledObj.label);
}

<span class="hljs-keyword">let</span> myObj = {label: <span class="hljs-string">"Size 10 Object"</span>};
printLabel(myObj);
</code></pre>
<p>Hopefully this example gives you a bit more insight into interfaces. If you want more detailed information check out the docs on <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/interfaces.html">interfaces here</a>.</p>
<p>Now that our interface is ready, let's mock some data (since we don't have an actual database for this tutorial).</p>
<p>Let's create a mock list of todos first in our <code>stubs/todos.ts</code> file. Simply add the following:</p>
<pre><code class="lang-stubs/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interface
import Todo from '../interfaces/Todo.ts';

let todos: Todo[] = [
  {
    id: v4.generate(),
    todo: 'walk dog',
    isCompleted: true,
  },
  {
    id: v4.generate(),
    todo: 'eat food',
    isCompleted: false,
  },
];

export default todos;
</code></pre>
<ul>
<li>Two things to notice here: we add a new package and use its method <code>v4</code> by doing <code>_import_ { v4 } _from_ "https://deno.land/std/uuid/mod.ts";</code>. Then every time we use <code>v4.generate()</code> it will create a new random string of <code>id</code>.  </li>
</ul>
<p>The <code>id</code> can not be a <code>number</code>, only a <code>string</code> because in our <code>Todo</code> interface we have defined <code>id</code> as a string.</p>
<ul>
<li>The other thing to focus on here is <code>let _todos_: _Todo_[]</code> = []. This basically tells Deno that our todos array is of type <code>Todo</code> (which is awesome, our compiler now <em>automagically</em> knows that each item in our array can only have <code>{**id**: _string_, **todo**: _string_ &amp; **isCompleted**: _boolean_}</code> it will not accept any other key).</li>
</ul>
<p>If you want to learn more about <code>interfaces</code> in TypeScript check out this amazing detailed documentation on interfaces <strong><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/interfaces.html">here</a>.</strong></p>
<p>Awesome. If you have come this far, give yourself a pat on the back. Good job everyone.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/download-1.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>The Rock appreciates all the effort you are doing</em></p>
<h2 id="heading-lets-work-on-our-controllers">Let's work on our controllers</h2>
<p>In your file <code>controllers/todo.ts</code>:</p>
<pre><code class="lang-controllers/todos.ts">export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Let's write the controller for <code>getAllTodos</code>:</p>
<pre><code class="lang-controllers/todos.ts">// stubs
import todos from "../stubs/todos.ts";

export default {
  /**
   * @description Get all todos
   * @route GET /todos
   */
  getAllTodos: ({ response }: { response: any }) =&gt; {
    response.status = 200;
    response.body = {
      success: true,
      data: todos,
    };
  },
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Before I begin on this block of code, let me explain that every controller has an argument – let's call it <code>context</code>.</p>
<p>So we can deconstruct <code>_getAllTodos_: (context) =&gt; {}</code> to:</p>
<pre><code>getAllTodos: <span class="hljs-function">(<span class="hljs-params">{ request, response, params }</span>) =&gt;</span> {}
</code></pre><p>And since we are using <code>typescript</code> we have to add type checking to all of these variables:</p>
<pre><code>getAllTodos: <span class="hljs-function">(<span class="hljs-params">
  { request, response, params }: { 
    request: any, 
    response: any, 
    params: { id: string },
  },
</span>) =&gt;</span> {}
</code></pre><p>So we have added type checks to all 3 <code>{ request, response, params }</code></p>
<ul>
<li><code>request</code> is what the user sends us (information like headers and JSON data)</li>
<li><code>response</code> is what we send the user back in the API response</li>
<li><code>params</code> is what we define in our router routes, that is:</li>
</ul>
<pre><code class="lang-ts">.get(<span class="hljs-string">"/todos/:id"</span>, <span class="hljs-function">(<span class="hljs-params">{ params}: { params: { id: <span class="hljs-built_in">string</span> } }</span>) =&gt;</span> {})
</code></pre>
<p>So the <code>:id</code> in <code>/todos/:id</code> is the param. Params are a way to get information from the URL. In this example we know that we have an <code>/:id</code> . So when the user tries to access this API (that is, <code>/todos/756</code>) <strong>756</strong> is basically the <strong>:id</strong> param. Since it is in the URL we know it is of type <code>string</code>.</p>
<p>Now that we have our basic definitions defined let's get back to our todos controller:</p>
<pre><code class="lang-controllers/todos.ts">// stubs
import todos from "../stubs/todos.ts";

export default {
  /**
   * @description Get all todos
   * @route GET /todos
   */
  getAllTodos: ({ response }: { response: any }) =&gt; {
    response.status = 200;
    response.body = {
      success: true,
      data: todos,
    };
  },
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>For <code>getAllTodos</code> we only need <code>response</code> . If you remember, <code>response</code> is what is needed to send data back to the user.</p>
<p>For people coming from a Node and Express background, one big thing that is different here is that we don't need to <code>return</code> the response object. Deno does this for us automatically.</p>
<p>All we have to do is set <code>response.status</code> which in this case is <code>200</code>.</p>
<p>More on response statuses <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"><strong>here</strong></a><strong>.</strong></p>
<p>The other thing we set is the <code>response.body</code> which in this case is an object:</p>
<pre><code class="lang-ts">{
  success: <span class="hljs-literal">true</span>,
  data: todos
}
</code></pre>
<p>I will go ahead and run my server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><blockquote>
<p><strong>Revision:</strong> The <code>---allow-net</code> property tells Deno that this app gives the user permission to access its content via the port opened up.</p>
</blockquote>
<p>Once your server is running, you can access the <code>GET /todos</code> API. I am using <code>postman</code> which is a Google Chrome extension and can be downloaded <a target="_blank" href="https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop//%40">here</a>.</p>
<p>You can use whatever rest client you like. I like using <code>postman</code> because I think it is very easy.</p>
<p>In Postman, open up a new tab. Set the request to type <code>GET</code> and in the <code>URL</code> bar type <code>http://localhost:8080/todos</code>. Hit <code>Send</code> and this is what you see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.01.11.png" alt="Image" width="600" height="400" loading="lazy">
<em>GET /todos API response</em></p>
<p>Cool! 1 API done, 4 more to go. ??</p>
<p>If you feel stuck anywhere just have sneak peak at the source code directly <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak"><strong>here</strong></a><strong>.</strong></p>
<p>Let's move on to our next controller:</p>
<pre><code class="lang-controllers/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interfaces
import Todo from "../interfaces/Todo.ts";
// stubs
import todos from "../stubs/todos.ts";

export default {
  getAllTodos: () =&gt; {},
  /**
   * @description Add a new todo
   * @route POST /todos
   */
  createTodo: async (
    { request, response }: { request: any; response: any },
  ) =&gt; {
    const body = await request.body();
    if (!request.hasBody) {
      response.status = 400;
      response.body = {
        success: false,
        message: "No data provided",
      };
      return;
    }

    // if everything is fine then perform
    // operation and return todos with the
    // new data added.
    let newTodo: Todo = {
      id: v4.generate(),
      todo: body.value.todo,
      isCompleted: false,
    };
    let data = [...todos, newTodo];
    response.body = {
      success: true,
      data,
    };
  },
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Since we are going to be adding a new Todo to our list, I have imported 2 modules in the controller file.</p>
<ul>
<li><code>import { v4 } from</code><a target="_blank" href="https://deno.land/std/uuid/mod.ts">https://deno.land/std/uuid/mod.ts</a><code>;</code> this will be used to create a new unique one for the todo being created</li>
<li><code>import Todo from "../interfaces/Todo.ts";</code> this will be used to ensure that the new todo that is being created follows the same structure.</li>
</ul>
<p>Our <code>createTodo</code> controller is <code>async</code> meaning there are some promises used inside the controller. </p>
<p>Let's break it into smaller parts:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body();
<span class="hljs-keyword">if</span> (!request.hasBody) {
      response.status = <span class="hljs-number">400</span>;
      response.body = {
        success: <span class="hljs-literal">false</span>,
        message: <span class="hljs-string">"No data provided"</span>,
      };
      <span class="hljs-keyword">return</span>;
}
</code></pre>
<p>First we get the content of the JSON body that the user has sent us. Then we use <code>oak's</code> built-in method called <code>request.hasBody</code> to check if the user has even sent any content. If not then we can do <code>if (!request_._hasBody) {}</code> inside this <code>if</code> block. </p>
<p>We set the status to <code>400</code> (400 means that the user did something they were not suppose to do) and the body is set to <code>{success: false, message: "no data provided }</code>. Then we simple add <code>return;</code> to ensure that no further code below is executed.</p>
<p>Next we do this:</p>
<pre><code><span class="hljs-comment">// if everything is fine then perform</span>
<span class="hljs-comment">// operation and return todos with the</span>
<span class="hljs-comment">// new data added.</span>
<span class="hljs-keyword">let</span> newTodo: Todo = {
  <span class="hljs-attr">id</span>: v4.generate(),
  <span class="hljs-attr">todo</span>: body.value.todo,
  <span class="hljs-attr">isCompleted</span>: <span class="hljs-literal">false</span>,
};
<span class="hljs-keyword">let</span> data = [...todos, newTodo];
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  data,
};
</code></pre><p>We create a new todo by doing this:</p>
<pre><code><span class="hljs-keyword">let</span> newTodo: Todo = {
  <span class="hljs-attr">id</span>: v4.generate(),
  <span class="hljs-attr">todo</span>: body.value.todo,
  <span class="hljs-attr">isCompleted</span>: <span class="hljs-literal">false</span>,
};
</code></pre><p><code>let newTodo: Todo = {}</code> ensures that <code>newTodo</code> follows the same structure as the rest of the todos. We then assign a random id by using <code>v4.generate()</code>, set todo to <code>body.value.todo</code> and <code>isCompleted</code> to  <code>false</code>.</p>
<p>The thing to notice here is all the data the user sends us we can access from <code>body.value</code> in <code>oak</code>.</p>
<p>Next we do the following:</p>
<pre><code><span class="hljs-keyword">let</span> data = [...todos, newTodo];
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  data,
};
</code></pre><p>Append the <code>newTodo</code> to our current list of todos and simply set the body to <code>{success: true &amp; data: data</code>.</p>
<p>And we are done ✅ with this controller as well.</p>
<p>Let's restart our server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>In my postman, I open up a new tab. Set the request to <code>POST</code> type and in the <code>URL</code> bar type <code>http://localhost:8080/todos</code>. Then hit <code>Send</code> and this is what you see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.24.00.png" alt="Image" width="600" height="400" loading="lazy">
<em>I send an empty request and get a 400 status error code along with an error message</em></p>
<p>Then I send some content in the body of the request payload and try again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.24.15.png" alt="Image" width="600" height="400" loading="lazy">
<em>Awesome, POST /todos with body content { todo: "eat a lamma" } is success &amp; we can see content appended to our current todo list</em></p>
<p>Cool, we can see that our API is working as expected.</p>
<p>Two APIs down, three more to go. </p>
<p>We are almost there. Most of the hard work is done. ☺️ ? ? ?</p>
<p>Let's move on to our third API:</p>
<pre><code class="lang-controllers/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interfaces
import Todo from "../interfaces/Todo.ts";
// stubs
import todos from "../stubs/todos.ts";

export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  /**
   * @description Get todo by id
   * @route GET todos/:id
   */
  getTodoById: (
    { params, response }: { params: { id: string }; response: any },
  ) =&gt; {
    const todo: Todo | undefined = todos.find((t) =&gt; {
      return t.id === params.id;
    });
    if (!todo) {
      response.status = 404;
      response.body = {
        success: false,
        message: "No todo found",
      };
      return;
    }

    // If todo is found
    response.status = 200;
    response.body = {
      success: true,
      data: todo,
    };
  },
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Let's talk about our controller for <code>GET todos/:id</code>. This will get us a todo by ID.</p>
<p>Let's break this down into smaller parts and discuss it:</p>
<pre><code><span class="hljs-keyword">const</span> todo: Todo | <span class="hljs-literal">undefined</span> = todos.find(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> t.id === params.id);
<span class="hljs-keyword">if</span> (!todo) {
  response.status = <span class="hljs-number">404</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
  };
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>In the first part we set a new <code>const todo</code> and set its type to either <code>Todo</code> or <code>undefined</code>. So <code>todo</code> will either be an object with the <code>Todo</code> interface shape or it will be <code>undefined</code> – it can not be anything else.</p>
<p>We then <code>_todos.find_((_t_)</code> =&gt; <em>t.id</em> === <em>params.id</em>); use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find">Array.find()</a> to find the <code>todo</code> with the id provided in <code>params.id</code>. If it matches we get a <code>Todo</code> with shape <code>todo</code>, otherwise <code>undefined</code>.</p>
<p>If <code>todo</code> is undefined, it means that this <code>if</code> block will run:</p>
<pre><code><span class="hljs-keyword">if</span> (!todo) {
  response.status = <span class="hljs-number">404</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
  };
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>Here we simply set the status to <code>404</code> which means <code>not found</code> along with our standard failure response or <code>{ status, message }</code></p>
<p>Cool, right? ?</p>
<p>Next we simply do this:</p>
<pre><code><span class="hljs-comment">// If todo is found</span>
response.status = <span class="hljs-number">200</span>;
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">data</span>: todo,
};
</code></pre><p>Set a <code>200</code> success response and in our response body we set <code>success: true &amp; data: todo</code>.</p>
<p>Let's run this in our postman.</p>
<p>Let's restart our server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>In my postman, I open up a new tab. Set the request to <code>GET</code> type and in the <code>URL</code> bar type <code>http://localhost:8080/todos/:id</code>, then hit <code>Send</code>.</p>
<p>Since we are generating ID's randomly, first get all todos by hitting theget all todos API. Then from any todo get one of its ID to test this newly created API.<br>Every time you restart this Deno application, new ID's will be generated.</p>
<p>Let's go:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.40.52.png" alt="Image" width="600" height="400" loading="lazy">
<em>404 status, no record found case</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.41.36.png" alt="Image" width="600" height="400" loading="lazy">
<em>Provided it a known ID and it returned the todo associated with that ID along with status 200</em></p>
<p>If you need to reference the original source code of this tutorial go <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak"><strong>here</strong></a>.</p>
<p>Great, 3 APIs done, 2 more to go.</p>
<pre><code class="lang-controllers/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interfaces
import Todo from "../interfaces/Todo.ts";
// stubs
import todos from "../stubs/todos.ts";

export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  /**
   * @description Update todo by id
   * @route PUT todos/:id
   */
  updateTodoById: async (
    { params, request, response }: {
      params: { id: string },
      request: any,
      response: any,
    },
  ) =&gt; {
    const todo: Todo | undefined = todos.find((t) =&gt; t.id === params.id);
    if (!todo) {
      response.status = 404;
      response.body = {
        success: false,
        message: "No todo found",
      };
      return;
    }

    // if todo found then update todo
    const body = await request.body();
    const updatedData: { todo?: string; isCompleted?: boolean } = body.value;
    let newTodos = todos.map((t) =&gt; {
      return t.id === params.id ? { ...t, ...updatedData } : t;
    });
    response.status = 200;
    response.body = {
      success: true,
      data: newTodos,
    };
  },
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Let's talk about our controller for <code>PUT todos/:id</code>. This will update a todo by ID.</p>
<p>Let's break this down into smaller bits:</p>
<pre><code><span class="hljs-keyword">const</span> todo: Todo | <span class="hljs-literal">undefined</span> = todos.find(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> t.id === params.id);
<span class="hljs-keyword">if</span> (!todo) {
  response.status = <span class="hljs-number">404</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
  };
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>This is something we did exactly the same with the previous controller as well, so I won't go into much detail here.</p>
<p>Pro tip here: You can if you want make this piece of code a generic code block and then use it in both controllers.</p>
<p>Next we do this:</p>
<pre><code><span class="hljs-comment">// if todo found then update todo</span>
<span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body();
<span class="hljs-keyword">const</span> updatedData: { todo?: string; isCompleted?: boolean } = body.value;
<span class="hljs-keyword">let</span> newTodos = todos.map(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> t.id === params.id ? { ...t, ...updatedData } : t;
});
response.status = <span class="hljs-number">200</span>;
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">data</span>: newTodos,
};
</code></pre><p>The piece of code I want to talk about here is the following:</p>
<pre><code><span class="hljs-keyword">const</span> updatedData: { todo?: string; isCompleted?: boolean } = body.value;
<span class="hljs-keyword">let</span> newTodos = todos.map(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> t.id === params.id ? { ...t, ...updatedData } : t;
});
</code></pre><p>First we do <code>const updatedData = body.value</code> and then add type checking to <code>updatedData</code> like the following:</p>
<pre><code>updatedData: { todo?: string; isCompleted?: boolean }
</code></pre><p>This piece of code is telling TS that <code>updatedData</code> is an object which can <code>have/not have</code> <em>todo: string and</em> also can <code>have/not have</code> <em>isCompleted: boolean.</em></p>
<p>Then we simply map over all todos like this:</p>
<pre><code><span class="hljs-keyword">let</span> newTodos = todos.map(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> t.id === params.id ? { ...t, ...updatedData } : t;
});
</code></pre><p>And where <code>params.id</code> match with <code>t.id</code> we simply append everything to that object we get from the user.</p>
<p>We are done with this API as well. </p>
<p>Let's restart our server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Open up a new tab in Postman. Set the request to <code>PUT</code> and in the <code>URL</code> bar type in <code>http://localhost:8080/todos/:id</code>, then hit <code>Send</code>:</p>
<p>Since we are generating ID's randomly,  first get all todos by hitting get all todos API. Then from any todo get one of its ID to test this newly created API.<br>Every time you restart this Deno application, new ID's will be generated.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.59.39.png" alt="Image" width="600" height="400" loading="lazy">
<em>404 status returned and no todo found error message given</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-03.00.21.png" alt="Image" width="600" height="400" loading="lazy">
<em>Provided a known ID, updated todo content in body. It returned the updated todo along with all the other todos</em></p>
<p>This is amazing – four APIs done and just one more to go.</p>
<pre><code class="lang-controllers/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interfaces
import Todo from "../interfaces/Todo.ts";
// stubs
import todos from "../stubs/todos.ts";

export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  /**
   * @description Delete todo by id
   * @route DELETE todos/:id
   */
  deleteTodoById: (
    { params, response }: { params: { id: string }; response: any },
  ) =&gt; {
    const allTodos = todos.filter((t) =&gt; t.id !== params.id);

    // remove the todo w.r.t id and return
    // remaining todos
    response.status = 200;
    response.body = {
      success: true,
      data: allTodos,
    };
  },
};
</code></pre>
<p>Let's talk about our controller for <code>Delete todos/:id</code> this will delete a todo by ID.</p>
<p>We simply run a filter on all todos:</p>
<pre><code><span class="hljs-keyword">const</span> allTodos = todos.filter(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> t.id !== params.id);
</code></pre><p>Remove the <code>todo.id</code> that matches with <code>params.id</code> and return the rest.</p>
<p>Then we do this:</p>
<pre><code><span class="hljs-comment">// remove the todo w.r.t id and return</span>
<span class="hljs-comment">// remaining todos</span>
response.status = <span class="hljs-number">200</span>;
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">data</span>: allTodos,
};
</code></pre><p>Simply return all the todos left which do not have the same todo.id.</p>
<p>Let's restart our server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Open up a new tab in Postman. This time set the request to <code>DELETE</code> and in the <code>URL</code> bar type <code>http://localhost:8080/todos/:id</code> and hit <code>Send</code>.</p>
<p>Since we are generating ID's randomly,  first get all todos by hitting get all todos API. Then from any todo get one of its ID to test this newly created API.<br>Every time you restart this Deno application, new ID's will be generated.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-03.07.54.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>With this we are all done with all five APIs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/75bdf06df3fd6ddd9d3311d8cb2be029.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<hr>
<p>Now we only have two things remaining:</p>
<ul>
<li>Add a not found route middleware so that when the user tries to access an unknown route it gives an error.</li>
<li>Add a logger API that consoles the response time it took to return data from one API endpoint.</li>
</ul>
<h2 id="heading-creating-a-route-middleware-for-routes-that-arent-found">Creating a route middleware for routes that aren't found</h2>
<p>In your root folder create a new folder called <code>middlewares</code>. Inside that folder create a file called <code>notFound.ts</code> and inside this file add this code:</p>
<pre><code class="lang-middlwares/notfound.ts">export default ({ response }: { response: any }) =&gt; {
  response.status = 404;
  response.body = {
    success: false,
    message: "404 - Not found.",
  };
};
</code></pre>
<p>Here we aren't doing anything new – it is very similar to our controllers structure. Just returning a status <code>404</code> (which means not found) along with a JSON object for <code>{ success, message }</code>.</p>
<p>Next go in your <code>server.ts</code> file and add the following content:</p>
<ul>
<li>Add this import somewhere at the top:</li>
</ul>
<pre><code class="lang-server.ts">// not found
import notFound from './middlewares/notFound.ts';
</code></pre>
<ul>
<li>And then just below your <code>app.use(todoRouter.allowedMethods())</code> add this line like this:</li>
</ul>
<pre><code class="lang-server.ts">app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());

// 404 page
app.use(notFound);
</code></pre>
<p>The order of execution is important here: every time we try to access an API end point it will first match/check routes from our <code>todoRouter</code>. If none are found, it will then execute <code>app_.use_(notFound);</code>. </p>
<p>Let's see if this works.</p>
<p>Restart the server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Open up a new tab in Postman. Set the request to <code>GET</code> and in the <code>URL</code> bar type <code>http://localhost:8080/something-unknown</code>, then hit <code>Send</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-12.28.10.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So we now have a route middleware that we put at the end of our routes in <code>server.ts</code> as <code>app_.use_(notFound);</code>. If no route matches this middleware it will execute and return a <code>404</code> status code (which means not found). Then we simply send a response message like always which is <code>{success, message}</code>.</p>
<p><strong>Pro tip:</strong> We have decided that <code>{success, message}</code> is what we return in failed scenarios and <code>{success, data}</code> is what we return to user in success scenarios. So we can even make these to object/shapes as interfaces and add them to our project to ensure consistency and safe type checking.</p>
<p>Cool, now we are done with one of our middlewares – let's add the other middleware for logging our APIs in the console.</p>
<p><strong>Reminder:</strong> If you get stuck anywhere you can use the <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">source code here</a>.</p>
<h2 id="heading-logging-apis-in-console">Logging APIs in console</h2>
<p>In your <code>middlewares</code> folder create a new file called <code>logger.ts</code> and enter the following code:</p>
<pre><code class="lang-middlewares/logger.ts">import {
  green,
  cyan,
  white,
  bgRed,
} from "https://deno.land/std@0.53.0/fmt/colors.ts";

const X_RESPONSE_TIME: string = "X-Response-Time";

export default {
  logger: async (
    { response, request }: { response: any, request: any },
    next: Function,
  ) =&gt; {
    await next();
    const responseTime = response.headers.get(X_RESPONSE_TIME);
    console.log(`${green(request.method)} ${cyan(request.url.pathname)}`);
    console.log(`${bgRed(white(String(responseTime)))}`);
  },
  responseTime: async (
    { response }: { response: any },
    next: Function,
  ) =&gt; {
    const start = Date.now();
    await next();
    const ms: number = Date.now() - start;
    response.headers.set(X_RESPONSE_TIME, `${ms}ms`)
  },
};
</code></pre>
<p>In your <code>server.ts</code> file add this code:</p>
<ul>
<li>Import this somewhere at the top:</li>
</ul>
<pre><code class="lang-server.ts">// logger
import logger from './middlewares/logger.ts';
</code></pre>
<ul>
<li>Just above your <code>todoRouter</code> code add these middlewares like this:</li>
</ul>
<pre><code><span class="hljs-comment">// order of execution is important;</span>
app.use(logger.logger);
app.use(logger.responseTime);

app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());
</code></pre><p>Now let's discuss what we just did.</p>
<p>Let's talk about the <code>logger.ts</code> file and break it down into bits:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> {
  green,
  cyan,
  white,
  bgRed,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/std@0.53.0/fmt/colors.ts"</span>;
</code></pre>
<p>I am importing some console colors and console background colors that I want to use in API logging.</p>
<p>This is similar to what we did in our <code>eventListener</code> in our <code>server.ts</code> file. We will use colors in our console to log API requests.</p>
<p>Next I set <code>const X_RESPONSE_TIME: string = "X-Response-Time";</code>. This is the header we will inject in our API requests as they come into our server. I am calling this <code>X_RESPONSE_TIME</code> and its value is <code>X-Response-Time</code>. I will demonstrate its usage in a bit.</p>
<p>Next we simply export an object like this:</p>
<pre><code class="lang-middlewares/logger.ts">export default {
    logger: async ({ response, request }, next) {}
    responseTime: async ({ response }, next) {}
};
</code></pre>
<p>And then we simply use it inside our <code>server.ts</code> file like this:</p>
<pre><code class="lang-server.ts">// order of execution is important;
app.use(logger.logger);
app.use(logger.responseTime);
</code></pre>
<p>Let's now discuss what is happening in our logger middleware code and discuss it execution style using <code>next()</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-12.51.36.png" alt="Image" width="600" height="400" loading="lazy">
<em>Execution of order of logging middleware when GET /todos API is called.</em></p>
<p>The only difference here and in the controllers we had before is the use of the <code>next()</code> function. This functions helps us jump from one controller to the other as shown in the image below.</p>
<p>So in:</p>
<pre><code class="lang-middlewares/logger.ts">export default {
  logger: async (
    { response, request }: { response: any, request: any },
    next: Function,
  ) =&gt; {
    await next();
    const responseTime = response.headers.get(X_RESPONSE_TIME);
    console.log(`${green(request.method)} ${cyan(request.url.pathname)}`);
    console.log(`${bgRed(white(String(responseTime)))}`);
  },
  responseTime: async (
    { response }: { response: any },
    next: Function,
  ) =&gt; {
    const start = Date.now();
    await next();
    const ms: number = Date.now() - start;
    response.headers.set(X_RESPONSE_TIME, `${ms}ms`)
  },
};
</code></pre>
<p>Keep in mind that this is what we have in our <code>server.ts</code> file:</p>
<pre><code class="lang-server.ts">// order of execution is important;
app.use(logger.logger);
app.use(logger.responseTime);

app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());
</code></pre>
<p>The order of execution is as follows:</p>
<ul>
<li>logger.logger middleware</li>
<li>logger.responseTime middleware</li>
<li>todoRouter controller (whatever path is called by the user, for the purpose of explanation I am assuming that the user called <code>GET /todos</code> API to get all todos.)</li>
</ul>
<p>So it will first execute logger.logger middleware which is this:</p>
<pre><code class="lang-middlewares/logger.ts">logger: async (
    { response, request }: { response: any, request: any },
    next: Function,
  ) =&gt; {
    await next();
    const responseTime = response.headers.get(X_RESPONSE_TIME);
    console.log(`${green(request.method)} ${cyan(request.url.pathname)}`);
    console.log(`${bgRed(white(String(responseTime)))}`);
  },
</code></pre>
<p>It will come inside this function and immediately as it reads <code>await next()</code> it quickly jumps to the next middleware which is <code>responseTime</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-12.51.36-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sharing the image above again for revision.</em></p>
<p>Inside <code>responseTime</code>, it only executes two lines which are (look at execution order 2 in image above):</p>
<pre><code class="lang-middlewares/logger.ts">const start = Date.now();
await next();
</code></pre>
<p>before jumping to the <code>getAllTodos</code> controller. Once it goes inside <code>getAllTodos</code> it will run the entire code inside that controller. </p>
<p>Since in that controller we are not using <code>next()</code> it will simply return the flow of logic back to <code>responseTime</code> controller. There it will run the following:</p>
<pre><code class="lang-middlewares/logger.ts">const ms: number = Date.now() - start;
response.headers.set(X_RESPONSE_TIME, `${ms}ms`)
</code></pre>
<p>Now keeping in perspective of the order of execution which is <code>2, 3, 4</code> (look at the image above).</p>
<p>This is what happens:</p>
<ul>
<li>We capture the data in <code>ms</code> by doing <code>const</code> <em><code>start</code></em> <code>=</code> <em><code>Date.now</code></em><code>();</code>. Then we immediately call <code>next()</code> which goes to <code>getAllTodos</code> controller and runs the entire code. Then it comes back in the <code>responseTime</code> controller.</li>
<li>We then subtract that <code>start</code> date with whatever the date is at that moment by doing <code>const _ms_: _number_ = _Date.now_()</code> - <em>start</em>; <code>ms</code>. Here it will return a number which is basically the difference in milliseconds that will tell us all the time it took Deno to execute our <code>getAllTodos</code> controller.</li>
</ul>
<p>Sharing the image once again for review:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-12.51.36-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ul>
<li>Next we simply set headers in our <code>response</code> like this:</li>
</ul>
<pre><code>response.headers.set(X_RESPONSE_TIME, <span class="hljs-string">`<span class="hljs-subst">${ms}</span>ms`</span>)
</code></pre><p>Which just sets the header value <code>X-Response-Time</code> to the milliseconds it took Deno to execute our API.</p>
<ul>
<li>Then from execution order <code>4</code> we move back to execution order <code>5</code> (have a look at the image above for reference).</li>
</ul>
<p>Here we simply do:</p>
<pre><code class="lang-middlwares/logger.ts">const responseTime = response.headers.get(X_RESPONSE_TIME);
console.log(`${green(request.method)} ${cyan(request.url.pathname)}`);
console.log(`${bgRed(white(String(responseTime)))}`);
</code></pre>
<ul>
<li>We get the time we passed in the <code>X-Response-Time</code></li>
<li>Then we take that time and simply console it colourfully in the console.</li>
</ul>
<p><code>request.method</code> tells us the method used to call our API, that is  <code>GET, PUT etc</code> while <code>request.url.pathname</code> will tell the API which path the user used i.e, <code>/todos</code></p>
<p>Let's see if this works.</p>
<p>Restart the server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Open up a new tab in Postman. Set the request to <code>GET</code>, type in <code>http://localhost:8080/todos</code>, and hit <code>Send</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-13.17.13.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Hit the API a couple of times in Postman. Then when you go back to the console, you should see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-13.21.03.png" alt="Image" width="600" height="400" loading="lazy">
<em>API being logged in our console</em></p>
<p>This is it – we are done.</p>
<p>If you still feel stuck, take a look at the entire source code for this tutorial here: <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">github.com/adeelibr/deno-playground/tree/master/chapter_1:oak</a></p>
<p>I hope that you found this article useful and that it was able to help you learn something today.</p>
<p>If you liked it, please do share it on social media. If you want to have a discussion about it, reach out to me on <a target="_blank" href="https://twitter.com/adeelibr">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
