<?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" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Morse Wall]]></title><description><![CDATA[Software development, tech and side projects inside.]]></description><link>https://morsewall.com/</link><image><url>https://morsewall.com/favicon.png</url><title>Morse Wall</title><link>https://morsewall.com/</link></image><generator>Ghost 5.31</generator><lastBuildDate>Fri, 24 Jul 2026 00:18:04 GMT</lastBuildDate><atom:link href="https://morsewall.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[How to Build a Random Quote Machine – Part 11 – React Hooks, React Redux and Redux Thunk: Using various front end stacks]]></title><description><![CDATA[11 ways - How to build a random quote machine. Using Redux Thunk to call asynchronous endpoints in a React app with Hooks.]]></description><link>https://morsewall.com/random-quote-part-11-react-hooks-react-redux-and-redux-thunk-using-various-front-end-stacks/</link><guid isPermaLink="false">6383e2a825c4380210dd3e0c</guid><category><![CDATA[Redux Thunk]]></category><category><![CDATA[Redux]]></category><category><![CDATA[React]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Side Project]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[JSON]]></category><dc:creator><![CDATA[Pat Eskinasy]]></dc:creator><pubDate>Wed, 22 Sep 2021 18:26:00 GMT</pubDate><media:content url="https://morsewall.com/content/images/2022/11/what_happens_redux_store_asynch_case.png" medium="image"/><content:encoded><![CDATA[<h3 id="building-a-random-quote-machine-with-react-hooks-redux-and-redux-thunk">Building a random quote machine with React Hooks, Redux and Redux Thunk</h3><img src="https://morsewall.com/content/images/2022/11/what_happens_redux_store_asynch_case.png" alt="How to Build a Random Quote Machine &#x2013; Part 11 &#x2013; React Hooks, React Redux and Redux Thunk: Using various front end stacks"><p></p><p>This is part 11 (the last part!) of the <em>Making a random quote machine in a few different flavors</em> series.</p><p><em>You can read more about this project&#x2019;s background <a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">on the project&#x2019;s page</a>. Or start from the beginning with <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">part 1 of this series</a>.</em></p><p>In <a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/#flavor-10-html-css-react-hooks-react-redux-quotes-array">flavor #10</a>, I&#x2019;m using global state management (with Redux) to help me update the different components with the current application state using React to build the UI.</p><p>In this flavor, I continue using Redux to help me update the different components with the current application state, but the app is calling an asynchronous endpoint as the data (quotes) is requested from an external resource (a JSON stored in a public content delivery network (CDN)) (like in <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#flavor-5-html-css-redux-json-with-quotes">flavor #5</a>). This time, however, I&#x2019;m using React to build the UI (not manually building the UI with HTML, like previously in <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#flavor-5-html-css-redux-json-with-quotes">flavor #5</a>).</p><p>These are the different flavors that are part of this series: </p><!--kg-card-begin: html--><ol id="list-of-flavors">
    <li><a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-3-vanilla-javascript-and-rest-api-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes REST API</a></li>
    <li><strike>HTML + Vanilla JS + SAAS + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about SASS)</em></li>
    <li><strike>HTML + Vanilla JS + Bootstrap + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about Bootstrap)</em></li>
    <li><strike>HTML + CSS + JQuery + JSON with quotes</strike><em> (nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/">HTML + CSS + Redux + quotes array</a></li>
    <li><strike>HTML + CSS + Redux + JQuery + JSON with quotes</strike> <em>(nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/">HTML + CSS + Redux + Redux Thunk + JSON with quotes</a></li>
    <li><a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/"> HTML + CSS + React + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/">HTML + CSS + React + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-8-react-hooks-using-various-front-end-stacks/">HTML + CSS + React Hooks + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/">HTML + CSS + React Hooks + JSON with quotes</a> (members-only post)</li>
    <li><strike>HTML + CSS + React + React Redux + quotes array</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><strike>HTML + CSS + React + React Redux + Redux Thunk + JSON with quotes</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + quotes array</a></li>
    <li>HTML + CSS + React Hooks + React Redux + Redux Thunk + JSON with quotes (this flavor)</li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + Redux Thunk + JSON with quote</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
</ol> <!--kg-card-end: html--><p>If you are new here, you may wonder why I am overcomplicating a really simple application that can be shipped in 3 lines of functional Vanilla JavaScript. And the reason is: Shipping a simple app in a simple environment with fewer moving parts = great way to practice a new way to solve a problem. This is the spirit behind the <em><em><a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">Making a random quote machine in a few different flavors</a></em></em> series. Enjoy!</p><hr><p><em>If you&#x2019;re curious about what comes up next in Morse Wall and would like to make a writer very happy today, you should </em><a href="https://morsewall.com/signup/"><strong><em>subscribe to Morse Wall</em></strong></a><strong><em>.</em></strong></p><hr><h3 id="flavor-11-html-css-react-hooks-react-redux-redux-thunk-json-with-quotes">Flavor #11: HTML + CSS + React Hooks + React Redux + Redux Thunk + JSON with quotes</h3><p></p><p>Much like in <a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/#flavor-10-html-css-react-hooks-react-redux-quotes-array">flavor #10</a>, I&#x2019;m creating a Redux store that manages the state of the entire app. The React components can then subscribe to the pieces of data in the store that are relevant to them. <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#action-events-events-triggering-actions">Actions</a> are dispatched directly from React components. These dispatched actions then ultimately trigger store updates (for more on state, check <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#what-is-state">&#x201C;What is <code>state</code>?&#x201D; in flavor #4</a>).</p><p>Much of the Redux and Redux Thunk code in this flavor remains the same as in <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#flavor-5-html-css-redux-json-with-quotes">flavor #5</a>, so it may be helpful to give that writing a quick read. Similarly, reading <a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/#flavor-10-html-css-react-hooks-react-redux-quotes-array">flavor #10</a> may be helpful, given most of the React components used in this flavor have been detailed there. Also, much of the React Redux code here remains the same as in <a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/#flavor-10-html-css-react-hooks-react-redux-quotes-array">flavor #10</a>.</p><p>Like previously in <a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/#flavor-9-html-css-react-hooks-json-with-quotes">flavor #9</a>, I&#x2019;m storing the quotes in a separate JSON file in <a href="https://www.jsdelivr.com/?ref=morsewall.com">jsDelivr</a>, a public CDN.</p><h3 id="calling-asynchronous-endpoints-in-redux">Calling asynchronous endpoints in Redux</h3><p></p><p>I am using the <a href="https://github.com/reduxjs/redux-thunk/?ref=morsewall.com">Redux Thunk</a> middleware between the actions being dispatched and the actions reaching the reducer (for more on actions and reducers, check <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#flavor-4-html-css-redux-quotes-array-in-js-module">flavor #4</a>).</p><p>Redux Thunk helps me handle the challenge in that, by default, actions in Redux are dispatched synchronously. For more on Redux Thunk, check <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#calling-asynchronous-endpoints-in-redux">flavor #5 - Calling asynchronous endpoints in Redux</a> as well as <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#adding-the-redux-thunk-library">flavor #5 - Adding the Redux Thunk library</a> and <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#creating-the-redux-store-when-using-the-redux-thunk-middleware">flavor #5 - Creating the Redux store when using the Redux Thunk middleware </a>.</p><p>The design of doing one batch endpoint call versus multiple endpoint calls is detailed in <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#designing-for-one-batch-endpoint-call-versus-multiple-endpoint-calls">flavor #5 - Designing for one batch endpoint call versus multiple endpoint calls</a>. The same thinking applies to this flavor.</p><h2 id="working-through-the-user-stories">Working through the user stories</h2><p><br>From the <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user stories</a>, I want to be welcomed by a quote when I first load the app. In other words, I want to be able to read the quote from the Redux store on first &#x201C;content&#x201D; page load. For the first user story, I&#x2019;ll be calling an asynchronous function (<code>handleAsync</code>) through the <a href="https://reactjs.org/docs/hooks-effect.html?ref=morsewall.com"><code>useEffect</code> Hook</a> in my React component.</p><p>By using <code>useEffect</code>, I&#x2019;m effectively telling React that the component needs to do this &#x201C;effect&#x201D; after the browser has painted. React will call the function passed to <code>useEffect</code> later, after performing the DOM updates. For more on <code>useEffect</code>, check <a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/#controlling-asynchronous-code-in-react-with-hooks">flavor #9 - Controlling asynchronous code in React with Hooks</a>.</p><p>Then, I need to ship <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user story #2</a>: I want to be able to click a UI element (a button) to get a new quote. To achieve this, I&#x2019;ll be dispatching another action from my React component with the help of <code>chosenRandomQuoteToState</code> (defined in my React component further down).</p><h3 id="redux-and-initial-stateshow-me-the-code-already">Redux and initial state - Show me the code already!</h3><p></p><p>Defining actions, action creators and the reducer in full:</p><pre><code class="language-js">//script.js
// defining action types for the special asynch action creator-type function
const REQUESTING_API_DATA = &quot;REQUESTING_API_DATA&quot;;
const RECEIVED_API_DATA = &quot;RECEIVED_API_DATA&quot;;

// defining action creators related to the asynch function. Action creator is  a function that returns an action (object that contains information about an action-event that has occurred). The action creator gets called by `dispatch()`
const requestingApiData = () =&gt; {
  return {
    type: REQUESTING_API_DATA,
  };
};

const receivedApiData = (apiData) =&gt; {
  return {
    type: RECEIVED_API_DATA,
    payloadQuotes: apiData,
  };
};

//defining an action type
const NEW_QUOTE = &quot;NEW_QUOTE&quot;;

//defining an action creator, which creates the action to select a new quote.  The action creator is a function that returns an action (object that contains information about an action-event that has occurred). It creates the action to add a new quote.
const newQuoteActionCreator = (chosenQuoteInput) =&gt; {
  return {
    type: NEW_QUOTE,
    payloadQuote: chosenQuoteInput,
  };
};

// defining initial state
const initialState = {
  status: &quot;&quot;,
  quotesData: [],
};

//defining reducer functions to allow the Redux store to know how to respond to the action created
const getNextQuoteReducer = (state = initialState, action) =&gt; {
  switch (action.type) {
    case REQUESTING_API_DATA:
      return {
        ...state,
        status: &quot;waiting&quot;,
        quotesData: [],
      };
    case RECEIVED_API_DATA:
      return {
        ...state,
        status: &quot;received&quot;,
        quotesData: action.payloadQuotes,
      };
    case NEW_QUOTE:
      return {
        ...state,
        status: &quot;new quote&quot;,
        data: action.payloadQuote,
      };
    default:
      return state;
  }
};
</code></pre><p></p><!--kg-card-begin: html--><div class="notice" style="position:relative;min-height: 1em;margin-top: 1.45rem;margin-bottom: 1.45rem;padding: 1em 1.5em 1.5em;border: 2px solid;-webkit-box-shadow: 0.25em 0.25em 0 #000;box-shadow: 0.25em 0.25em 0 #000;">
    <h3 id="disclaimer-react-hooks" style="display: block;margin-bottom: 1.25em;padding-bottom: 0.25em;border-bottom: 2px solid">Disclaimer: Use of switch...case in reducers</h3>
    <div>
        <p>
            switch...case statements are great to show how the internals work but aren&apos;t typically used in production. You can <a href="https://redux-toolkit.js.org/usage/usage-guide/?ref=morsewall.com/#writing-reducers">use any conditional logic you want</a> to write a reducer.
        </p>
    </div>
</div>   <!--kg-card-end: html--><p></p><p>Pretty much all code in the snippet above follows the Redux logic implemented in <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#a-new-action-creator">part 5 of this series - A new action creator</a>. So, check that writing out for a deeper dive down.</p><p>With the above in place, I can define the asynchronous function that allows me to create an asynchronous action (hit an asynchronous endpoint). For this, I return a function in an action creator that takes <code>dispatch</code> as an argument. Within this function, I can dispatch actions and perform asynchronous requests.</p><pre><code class="language-js">//script.js
// defining a special action creator that returns a function. The returned function takes dispatch as an argument. Within this function, I can dispatch actions and perform asynchronous requests. It&apos;s common to dispatch an action before initiating any asynchronous behavior so that the application state knows that some data is being requested (this state could display a loading icon, for instance). Then, once the application receives the data, another action is dispatched, an action that carries the data as a payload along with information that the action is completed.
const handleAsync = () =&gt; {
  return function (dispatch) {
    // dispatch request action here
    store.dispatch(requestingApiData());
    const makeRequest = async () =&gt; {
      const responseJSON = await fetch(
        &quot;https://cdn.jsdelivr.net/gh/morsewall/jsondb@master/db.json&quot;
      );
      const responseObject = await responseJSON.json();
      const quotesArray = responseObject.quotes;
      // dispatch received data action here
      store.dispatch(receivedApiData(quotesArray));
      let initialQuote =
        quotesArray[Math.floor(Math.random() * quotesArray.length)];
      store.dispatch(newQuoteActionCreator(initialQuote));
    };
    makeRequest();
  };
};
</code></pre><p></p><p>Nearly all the code in the above snippet is covered in <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#calling-asynchronous-endpoints-in-redux">flavor #5 - Calling asynchronous endpoints in Redux</a>. The difference here is that I&#x2019;ve decided to follow a slightly different approach and dispatch a new random quote to the Redux store as soon as I&#x2019;ve fetched the quotes from JSON file (previously, in flavor #5, I&#x2019;ve used a Redux selector that would take state as an argument and return a randomly selected quote object).</p><p>As <code>handleAsync</code> is dispatched (more on dispatching <code>handleAsync</code>, with the help of <code>useEffect</code>, further down), an update of the state in the Redux store is triggered with the help of the reducer. The Redux store will then keep the full JSON contents stored in the state as well as a first randomly selected quote.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-2.cloudinary.com/hnhggca76/image/upload/q_auto/v1/ghost-blog-images/state_holding_quotes_status_currentquote.png" class="kg-image" alt="How to Build a Random Quote Machine &#x2013; Part 11 &#x2013; React Hooks, React Redux and Redux Thunk: Using various front end stacks" loading="lazy" width="1080" height="1080"><figcaption>State holding quotes status currentQuote</figcaption></figure><p></p><h3 id="no-javascript-modules-here-again">No JavaScript modules here (again)</h3><p></p><p>For the reasons I&#x2019;ve detailed in <a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/#no-javascript-modules-here">flavor #6</a>, I&#x2019;m not dividing this flavor&#x2019;s code into modules. This can be noted when comparing this flavor&#x2019;s code with <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#flavor-5-html-css-redux-json-with-quotes">flavor #5</a>&#x2019;s source code, which is modularized.</p><h3 id="a-visual-look-into-the-application%E2%80%99s-execution-flow">A visual look into the application&#x2019;s execution flow</h3><p></p><p>In summary, I&#x2019;m changing the state in the Redux store with the contents of a full JSON file and random quotes that get selected as the application runs. Redux updates the store with help from action creators, the Redux Thunk middleware, a reducer and the React Redux API.</p><p>On high-level, data flows in a similar way to <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#a-visual-look-into-the-applications-execution-flow">part 5 of this series - A visual look into the application&#x2019;s execution flow </a>: Different React components, such as the <em>Get New Quote</em> button, trigger state changes in the Redux store (with a new random quote) and a React component next updates the UI with the new state.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-2.cloudinary.com/hnhggca76/image/upload/q_auto/v1/ghost-blog-images/react_redux_redux_thunk_execution_flow.png" class="kg-image" alt="How to Build a Random Quote Machine &#x2013; Part 11 &#x2013; React Hooks, React Redux and Redux Thunk: Using various front end stacks" loading="lazy" width="2516" height="2152"><figcaption>React Redux Redux Thunk Execution Flow</figcaption></figure><p></p><h3 id="react-reduxspecifying-state-and-actions-to-react">React Redux - specifying state and actions to React</h3><p></p><p>By now I have the Redux code in place but still need to provide React (React code further down) access to the Redux store and the actions it needs to dispatch updates. I&#x2019;m getting this done with the <a href="https://react-redux.js.org/?ref=morsewall.com">React Redux package</a>. For more on React Redux, including the code for <code>&lt;Provider /&gt;</code> and <code>connect()</code>, check <a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/#react-redux-api">flavor #10 - React Redux API</a>.</p><!--kg-card-begin: html--><div class="notice" style="position:relative;min-height: 1em;margin-top: 1.45rem;margin-bottom: 1.45rem;padding: 1em 1.5em 1.5em;border: 2px solid;-webkit-box-shadow: 0.25em 0.25em 0 #000;box-shadow: 0.25em 0.25em 0 #000;">
    <h3 id="disclaimer-react-hooks" style="display: block;margin-bottom: 1.25em;padding-bottom: 0.25em;border-bottom: 2px solid">Disclaimer: React-Redux Hooks API and <code>connect()</code></h3>
    <div>
        <p>
           You may have noticed that flavors using React-Redux hooks have been crossed out from the <a href="#list-of-flavors">list of flavors covered in this 11-part series</a>. This is mainly due to me (at time of writing), being opinionated about React-Redux hooks since code becomes harder to test given the tighter coupling between the React component and Redux.
        </p>
        <p>
			(Update 2021: The recommendation is now that using the React-Redux hooks API should be the <a href="https://react-redux.js.org/api/hooks/?ref=morsewall.com">default approach in your React components</a>).
        </p>
        <p>
            The existing <code>connect</code> API, however, still works and will continue to be supported.
        </p>
        <p>
             (Update 2021 II: The intention with this series is to get very incremental progress from one stack to another. Making it all as much bare bones as possible in order to get concepts adequately explored and explained. For this reason, I&apos;ve covered the Redux core library (unopinionated - let&apos;s you decide how to handle everything) in the flavors covered in this series. That said, <a href="https://redux.js.org/redux-toolkit/overview/?ref=morsewall.com">Redux Toolkit</a> is now intended to be the standard way to write Redux logic and the recommendation is for it to be used).
        </p>
    </div>
</div>    <!--kg-card-end: html--><h3 id="mapstatetoprops"><br><code>mapStateToProps</code></h3><p></p><pre><code class="language-js">//script.js
//mapping state to props. Allows me to specify exactly what pieces of the state should the React component have access to. Taking state as argument, it returns an object which maps that state to specific property names. These properties will become accessible to the React component via props
const mapStateToProps = (state) =&gt; {
  return {
    currentQuote: state.data,
    stateQuotes: state.quotesData,
    stateStatus: state.status,
  };
};
</code></pre><p></p><p><code>mapStateToProps</code> is called every time the store state changes. It maps state to specific property names (in this case <code>currentQuote</code> for <code>data</code> - check the <a href="#redux-and-initial-stateshow-me-the-code-already">reducer above</a>, <code>stateQuotes</code> for <code>quotesData</code> and <code>stateStatus</code> for <code>status</code>). These properties are then accessible to my React component via props (with the help of <code>connect()</code> - check <a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/#react-redux-api">flavor #10 - React Redux API</a> for more on it).</p><h3 id="mapdispatchtoprops"><code>mapDispatchToProps</code></h3><p></p><p><code>mapDispatchToProps</code> receives <code>dispatch</code> and returns an object that maps dispatch actions to specific property names (in this case <code>selectNewQuote</code>, which I will be calling inside my React component further down and <code>handleAsyncFx</code>, which I&#x2019;m calling with <code>useEffect</code> in the React component).</p><p>These properties are then accessible to my React component via props (through <code>connect()</code>). Each property returns a function that calls <code>dispatch</code> with an action creator (in this case<code>newQuoteActionCreator</code> and <code>handleAsync</code> - check <a href="https://morsewall.com/random-quote-part-11-react-hooks-react-redux-and-redux-thunk-using-various-front-end-stacks/#redux-and-initial-stateshow-me-the-code-already">action creators above</a>) and any relevant action data (a randomly selected quote in the case of <code>newQuoteActionCreator</code>).</p><pre><code class="language-js">//script.js
//mapping dispatch to props. Specifying what actions should the React component have access to. Allows me to specify which action creators I need to be able to dispatch. It is used to provide specific action creators to the React components so they can dispatch actions against the Redux store. It returns an object that maps dispatch actions to property names, which become component props. As opposed to mapStateToProps (that returns a piece of state), here each property returns a function that calls dispatch with an action creator and any relevant action data. I have access to this dispatch because it&apos;s passed in to mapDispatchToProps() as a parameter when I define the function, just like I&apos;ve passed state to mapStateToProps(). The object should have a property selectNewQuote set to the dispatch function, which takes a parameter for the new quote to add when it dispatches newQuoteActionCreator(). It should also have a property handleAsyncFX set to a dispatch function that dispatches handleAsync().
const mapDispatchToProps = (dispatch) =&gt; {
  return {
    selectNewQuote: function (quoteToBeNewQuote) {
      dispatch(newQuoteActionCreator(quoteToBeNewQuote));
    },
    handleAsyncFX: function () {
      dispatch(handleAsync());
    },
  };
};
</code></pre><h3 id="the-loading-component">The loading component</h3><p></p><p>Since I&#x2019;m hitting an asynchronous endpoint in this flavor, I&#x2019;m adjusting my code to make sure that the application will only try to render the quote when I have the data available.</p><p>As part of this &#x201C;code adjustment&#x201D;, I&#x2019;m creating a React component (a loading spinner) that renders before the quotes data is available to be rendered, i.e. before I&#x2019;ve finished fetching the data from the JSON file.</p><pre><code class="language-js">// script.js
//defining a component for the loading spinner
const Loading = () =&gt; {
  return (
    &lt;div className=&quot;loading-container&quot;&gt;
      &lt;div className=&quot;loader-dzg&quot; /&gt;
    &lt;/div&gt;
  );
};
</code></pre><p></p><h3 id="react-dispatching-actions">React Dispatching Actions</h3><p></p><p>I now have all the Redux, Redux Thunk and React Redux bits in place. The bit missing is to define the React function component that will build the UI.</p><p>The async/await function (<code>props.handleAsyncFX</code>) passed to <code>useEffect</code> will run after the render is committed to the screen. This is great since I don&#x2019;t want to stop the <code>App</code> component from mounting. For more on <code>useEffect</code>, check <a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/#controlling-asynchronous-code-in-react-with-hooks">flavor #9 - Controlling asynchronous code in React with Hooks</a>.</p><p>I want the component to go ahead, render the <code>Loading</code> component and only re-render when <code>fetch()</code> has finished fetching the requested resource from the network (data from the JSON file).</p><p>By default, effects run after every completed render and since I&#x2019;m setting the state after every data fetch, the component would update and the effect would run again. It would fetch the data again and again. To avoid this, and only fetch data when the component mounts, I provide an empty array (<code>[]</code>) as second argument to <code>useEffect</code> to avoid activating it on component updates. This tells React that the effect doesn&#x2019;t depend on any values from props or state, so it never needs to re-run.</p><!--kg-card-begin: html--><div class="notice" style="position:relative;min-height: 1em;margin-top: 1.45rem;margin-bottom: 1.45rem;padding: 1em 1.5em 1.5em;border: 2px solid;-webkit-box-shadow: 0.25em 0.25em 0 #000;box-shadow: 0.25em 0.25em 0 #000;">
    <h3 id="disclaimer-react-hooks" style="display: block;margin-bottom: 1.25em;padding-bottom: 0.25em;border-bottom: 2px solid">Disclaimer: React Suspense</h3>
    <div>
        <p>
            A new way to fetch data is in the works with <a href="https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#react-16x-mid-2019-the-one-with-suspense-for-data-fetching?ref=morsewall.com">React Suspense</a> and in the longer term, the React core team will recommend using Suspense for data fetching (Update 2021: Suspense for Data Fetching is available on an <a href="https://reactjs.org/docs/concurrent-mode-suspense.html?ref=morsewall.com"> experimental release</a>).
        </p>
    </div>
</div>   <!--kg-card-end: html--><p></p><pre><code class="language-js">//script.js
// defining the function component. Redux state and dispatch are passed to the component as props
const App = (props) =&gt; {
  React.useEffect(() =&gt; {
    props.handleAsyncFX();
  }, []);

  const random = (array) =&gt; {
    return Math.floor(Math.random() * array.length);
  };

  const randomQuoteFunction = (array) =&gt; {
    return array[random(array)];
  };

  //defining a function to (ultimately) update the Redux state with a new quote. Passing a randomly selected quote via props. Dispatching selectNewQuote() from props and passing in the randomly selected new quote as an argument
  const chosenRandomQuoteToState = () =&gt; {
    //selecting a random quote from the array
    let chosenQuote = randomQuoteFunction(props.stateQuotes);
    props.selectNewQuote(chosenQuote);
  };

  //the component returns JSX, and as per code snippet below, JSX clearly represents HTML, composing the UI.
  //as a React component can only return one single element, I&#x2019;m using &lt;React.Fragment&gt; to add a parent tag to my JSX elements without adding an extra node to the DOM.
  return (
    &lt;React.Fragment&gt;
      {(() =&gt; {
        switch (props.stateStatus) {
          case &quot;waiting&quot;:
            return &lt;Loading /&gt;;
          case &quot;received&quot;:
            return &lt;Loading /&gt;;
          case &quot;new quote&quot;:
            return (
              &lt;React.Fragment&gt;
                &lt;div className=&quot;container&quot;&gt;
                  &lt;div id=&quot;quote-box&quot;&gt;
                    {/* //passing data via props to QuoteBox component */}
                    &lt;QuoteBox
                      text={props.currentQuote.quoteText}
                      author={props.currentQuote.quoteAuthor}
                    /&gt;
                    &lt;div className=&quot;actions&quot;&gt;
                      &lt;Button
                        id=&quot;new-quote&quot;
                        title=&quot;Get New Quote&quot;
                        onClick={chosenRandomQuoteToState}
                      /&gt;
                      &lt;TwitterShare link={twitterLink} /&gt;
                    &lt;/div&gt;
                  &lt;/div&gt;
                &lt;/div&gt;
                &lt;footer&gt;
                  &lt;ul className=&quot;footer-options&quot;&gt;
                    &lt;li className=&quot;footer-link&quot;&gt;
                      &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
                        Legal
                      &lt;/a&gt;
                    &lt;/li&gt;
                    &lt;li className=&quot;footer-link&quot;&gt;
                      &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
                        Contact Us
                      &lt;/a&gt;
                    &lt;/li&gt;
                  &lt;/ul&gt;
                  &lt;span&gt;
                    &#xA9; 2019 Developed by Pat Eskinasy. All Rights Reserved.
                  &lt;/span&gt;
                &lt;/footer&gt;
              &lt;/React.Fragment&gt;
            );
        }
      })()}
    &lt;/React.Fragment&gt;
  );
};
</code></pre><p></p><p><code>App</code> reads state from the Redux store (given Redux is passing state to <code>App</code> via <code>props</code>) and the newly selected random quote will render on the screen (for more on passing props, check <a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/#passing-props-to-components">flavor #10 - Passing props to components</a>).</p><p>Then, when the <em>Get New Quote</em> button is clicked, React calls <code>chosenRandomQuoteToState</code>, which calls <code>selectNewQuote</code> (see <code><a href="#mapdispatchtoprops">mapDispatchToProps</a></code> above), as it has been passed as <code>props</code> to <code>App</code>. Now, provided the specific action creator (<code>newQuoteActionCreator</code>, coming from <code>mapDispatchToProps</code>), the React component can dispatch actions against the Redux store and update the state with a new quote.</p><h3 id="action-what-happens-in-the-redux-store">Action! What happens in the Redux store</h3><p></p><p>As I use <a href="https://github.com/zalmoxisus/redux-devtools-extension/?ref=morsewall.com">Redux DevTools Extension</a> to time travel in the application&#x2019;s state, I can check the state of the Redux store at every point in time.</p><p>Illustrated below in the extension is the <code>data</code> object (holding the <strong>current</strong> randomly selected quote).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-2.cloudinary.com/hnhggca76/image/upload/q_auto/v1/ghost-blog-images/what_happens_redux_store_asynch_case.png" class="kg-image" alt="How to Build a Random Quote Machine &#x2013; Part 11 &#x2013; React Hooks, React Redux and Redux Thunk: Using various front end stacks" loading="lazy" width="4652" height="2936"><figcaption>What happens in the Redux store</figcaption></figure><h3 id="making-the-machine-tweet-and-voil%C3%A0"><br>Making the machine tweet and voil&#xE0;</h3><p></p><p>Defining <code>App</code>, the function component, now in full:</p><pre><code class="language-js">//script.js
// defining the function component. Redux state and dispatch are passed to the component as props
const App = (props) =&gt; {
  React.useEffect(() =&gt; {
    props.handleAsyncFX();
  }, []);

  //making the machine tweet
  let twitterLink;

  if (props.currentQuote) {
    let quoteTextElem = props.currentQuote.quoteText;
    let quoteAuthorElem = &quot; - &quot; + props.currentQuote.quoteAuthor;
    let contentQuote = quoteTextElem + quoteAuthorElem;
    if (contentQuote.length &gt; 280) {
      let charCountAuthor = quoteAuthorElem.length;
      const extraStylingChar = &quot;...&quot; + &apos;&quot;&apos;;
      let extraCharCount = extraStylingChar.length;
      let subString =
        quoteTextElem.substring(0, 280 - extraCharCount - charCountAuthor) +
        extraStylingChar +
        quoteAuthorElem;
      //generate url available for Twitter intent and inject url on HTML
      twitterLink = &quot;https://twitter.com/intent/tweet?text=&quot; + subString;
    } else {
      //generate url available for Twitter intent and inject url on HTML
      twitterLink = &quot;https://twitter.com/intent/tweet?text=&quot; + contentQuote;
    }
  }

  const random = (array) =&gt; {
    return Math.floor(Math.random() * array.length);
  };

  const randomQuoteFunction = (array) =&gt; {
    return array[random(array)];
  };

  //defining a function to (ultimately) update the Redux state with a new quote. Passing a randomly selected quote via props. Dispatching selectNewQuote() from props and passing in the randomly selected new quote as an argument
  const chosenRandomQuoteToState = () =&gt; {
    //selecting a random quote from the array
    let chosenQuote = randomQuoteFunction(props.stateQuotes);
    props.selectNewQuote(chosenQuote);
  };

  //the component returns JSX, and as per code snippet below, JSX clearly represents HTML, composing the UI.
  //as a React component can only return one single element, I&#x2019;m using &lt;React.Fragment&gt; to add a parent tag to my JSX elements without adding an extra node to the DOM.
  return (
    &lt;React.Fragment&gt;
      {(() =&gt; {
        switch (props.stateStatus) {
          case &quot;waiting&quot;:
            return &lt;Loading /&gt;;
          case &quot;received&quot;:
            return &lt;Loading /&gt;;
          case &quot;new quote&quot;:
            return (
              &lt;React.Fragment&gt;
                &lt;div className=&quot;container&quot;&gt;
                  &lt;div id=&quot;quote-box&quot;&gt;
                    {/* //passing data via props to QuoteBox component */}
                    &lt;QuoteBox
                      text={props.currentQuote.quoteText}
                      author={props.currentQuote.quoteAuthor}
                    /&gt;
                    &lt;div className=&quot;actions&quot;&gt;
                      &lt;Button
                        id=&quot;new-quote&quot;
                        title=&quot;Get New Quote&quot;
                        onClick={chosenRandomQuoteToState}
                      /&gt;
                      &lt;TwitterShare link={twitterLink} /&gt;
                    &lt;/div&gt;
                  &lt;/div&gt;
                &lt;/div&gt;
                &lt;footer&gt;
                  &lt;ul className=&quot;footer-options&quot;&gt;
                    &lt;li className=&quot;footer-link&quot;&gt;
                      &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
                        Legal
                      &lt;/a&gt;
                    &lt;/li&gt;
                    &lt;li className=&quot;footer-link&quot;&gt;
                      &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
                        Contact Us
                      &lt;/a&gt;
                    &lt;/li&gt;
                  &lt;/ul&gt;
                  &lt;span&gt;
                    &#xA9; 2019 Developed by Pat Eskinasy. All Rights Reserved.
                  &lt;/span&gt;
                &lt;/footer&gt;
              &lt;/React.Fragment&gt;
            );
        }
      })()}
    &lt;/React.Fragment&gt;
  );
};
</code></pre><p></p><p>The code to make the machine tweet (in snippet above inside <code>App</code>) is very much in line with what has been implemented in all previous flavors of this project. In other words, the code here follows the logic implemented in <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#making-the-machine-tweet">part 1 of this series</a>.</p><p>The conditional check for <code>props.currentQuote</code> helps me handle the readiness of the application. This is because I can only access <code>props.currentQuote.quoteText</code> or <code>props.currentQuote.quoteAuthor</code> when <code>props.currentQuote</code> exists (i.e. I can only access properties of the randomly selected quote object when the object has been selected, not before that).</p><p>Done. The last <a href="https://morsewall.github.io/random-quote-react-hooks-react-redux-json/">random quote machine</a> is shipped. Source code for <a href="https://github.com/morsewall/random-quote-react-hooks-react-redux-json">flavor #11 in Github</a>.</p><p>It was fun making this whole series!</p><!--kg-card-begin: html--><div class="button-set">
    <button style="border-radius:8px;background-color:#000000;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://morsewall.github.io/random-quote-react-hooks-react-redux-json/" style="margin:1rem;" class="button-in-post">Live Project</a></button>
    <button style="border-radius:8px;background-color:#000000;color:#ffffff;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://github.com/morsewall/random-quote-react-hooks-react-redux-json" style="margin:1rem;" class="button-in-post">Source code</a></button>
</div><!--kg-card-end: html--><hr><h3 id="acknowledgement">Acknowledgement</h3><p></p><p>The following goes without saying, but here it comes anyways: Please note that in this ever changing world of technology, I am writing this article in July 2019 (hello, summer!) and alternate solutions might have become available as you read this writing.</p><hr><p>This was part 11 (the last part!) of the <em>Making a random quote machine in a few different flavors</em> series.</p><p><em><em>You can read more about this project&#x2019;s background <a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">on the project&#x2019;s page</a>. Or start from the beginning with <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">part 1 of this series</a>.</em></em></p><p><em>If you&#x2019;re curious about what is next with Morse Wall, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><hr><p><em>So, what did you like about this post? <a href="https://twitter.com/celue">Come say hello on Twitter!</a></em></p><!--kg-card-begin: html--><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Vanilla Js &#x2192; Redux &#x2192; React &#x2192; React Redux<br><br>This tiny project was redone 11 times, 11 different ways. <br><br>This was really fun to do. Fun little project. All 11 parts of this 11-part series now shipped. <a href="https://t.co/MY2oG5jJGb">pic.twitter.com/MY2oG5jJGb</a></p>&#x2014; Pat&apos;s Morse Wall (@morsewall) <a href="https://twitter.com/morsewall/status/1440755028357115907?ref_src=twsrc%5Etfw">September 22, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script><!--kg-card-end: html--><p></p><p><em>Also, if you have built a random quote machine after reading this post, share it as comment to the tweet above on Twitter. Really excited to see what you create!</em></p><p><em>Happy coding!</em></p><hr><h3 id="where-to-find-me">Where to find me:</h3><p>Follow me on Twitter:</p><!--kg-card-begin: markdown--><p><a href="https://twitter.com/celue"><img src="https://i.ibb.co/pZ016N6/Follow-Pat-Eskinasy.png" alt="How to Build a Random Quote Machine &#x2013; Part 11 &#x2013; React Hooks, React Redux and Redux Thunk: Using various front end stacks" style="width:100%"></a></p>
<!--kg-card-end: markdown--><p></p><p>You can always get my latest writings directly to your email address by <a href="https://morsewall.com/signup/"><strong>subscribing to Morse Wall</strong></a><strong>.</strong></p>]]></content:encoded></item><item><title><![CDATA[How to Build a Random Quote Machine – Part 10 – React Hooks and React Redux: Using various front end stacks]]></title><description><![CDATA[11 ways - How to build a random quote machine. Adding global state management with React Redux in a React app with Hooks.]]></description><link>https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/</link><guid isPermaLink="false">6383e22325c4380210dd3d6b</guid><category><![CDATA[Redux]]></category><category><![CDATA[React]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Side Project]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Pat Eskinasy]]></dc:creator><pubDate>Wed, 15 Sep 2021 16:46:00 GMT</pubDate><media:content url="https://morsewall.com/content/images/2022/11/cover_react_redux.png" medium="image"/><content:encoded><![CDATA[<h3 id="building-a-random-quote-machine-with-react-hooks-and-redux">Building a random quote machine with React Hooks and Redux</h3><img src="https://morsewall.com/content/images/2022/11/cover_react_redux.png" alt="How to Build a Random Quote Machine &#x2013; Part 10 &#x2013; React Hooks and React Redux: Using various front end stacks"><p></p><p>Part 10 (one before last) of the <em>Making a random quote machine in a few different flavors</em> series in ON.</p><p><em>You can read more about this project&#x2019;s background <a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">on the project&#x2019;s page</a>. Or start from the beginning with <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">part 1 of this series</a>.</em></p><p><em><em>If you&#x2019;re curious about the next flavors, you should <strong><strong><em><em><em><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em></em></em></em>.</strong></strong> I think you&#x2019;ll like it a lot!</em></em></p><p>In <a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/#flavor-9-html-css-react-hooks-json-with-quotes">flavor #9</a>, I&#x2019;m creating function components in a React app with Hooks and I have the data (quotes) inside a JSON file. In this flavor, I&#x2019;m using global state management (with Redux) to help me update the different components with the current application state (like in <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#flavor-4-html-css-redux-quotes-array-in-js-module">flavor #4</a>), but here I&#x2019;m using React to build the UI (not manually building the UI with HTML like previously).</p><p>These are the different flavors that are part of this series: </p><!--kg-card-begin: html--><ol id="list-of-flavors">
    <li><a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-3-vanilla-javascript-and-rest-api-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes REST API</a></li>
    <li><strike>HTML + Vanilla JS + SAAS + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about SASS)</em></li>
    <li><strike>HTML + Vanilla JS + Bootstrap + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about Bootstrap)</em></li>
    <li><strike>HTML + CSS + JQuery + JSON with quotes</strike><em> (nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/">HTML + CSS + Redux + quotes array</a></li>
    <li><strike>HTML + CSS + Redux + JQuery + JSON with quotes</strike> <em>(nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/">HTML + CSS + Redux + Redux Thunk + JSON with quotes</a></li>
    <li><a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/"> HTML + CSS + React + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/">HTML + CSS + React + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-8-react-hooks-using-various-front-end-stacks/">HTML + CSS + React Hooks + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/">HTML + CSS + React Hooks + JSON with quotes</a> (members-only post)</li>
    <li><strike>HTML + CSS + React + React Redux + quotes array</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><strike>HTML + CSS + React + React Redux + Redux Thunk + JSON with quotes</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li>HTML + CSS + React Hooks + React Redux + quotes array (this flavor)</li>
    <li><a href="https://morsewall.com/random-quote-part-11-react-hooks-react-redux-and-redux-thunk-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + Redux Thunk + JSON with quotes</a></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + Redux Thunk + JSON with quote</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
</ol> <!--kg-card-end: html--><p>If you are new here, you may wonder why I am overcomplicating a really simple application that can be shipped in 3 lines of functional Vanilla JavaScript. And the reason is: Shipping a simple app in a simple environment with fewer moving parts = great way to practice a new way to solve a problem. This is the spirit behind the <em><em><a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">Making a random quote machine in a few different flavors</a></em></em> series. Enjoy!</p><hr><p><em>In Part 11 (to be posted next week - the last part of this series), I will cover an eleventh flavor and will be using Redux Thunk to call an asynchronous endpoint to request the data (quotes) from an external resource (all while still building the UI with React Hooks).</em></p><p><em>If you&#x2019;re curious about the next flavors and would like to make a writer very happy today, you should </em><strong><em><strong><a href="https://morsewall.com/signup/">subscribe to Morse Wall</a>.</strong></em></strong></p><hr><h3 id="why-redux-in-a-react-application">Why Redux in a React application?</h3><p></p><p>With <a href="https://redux.js.org/?ref=morsewall.com">Redux</a>, I can simplify the management of the application&#x2019;s state in a complex app. Simplicity comes out specially from being able to have all app state centralized in a single location (the <a href="https://redux.js.org/api/store/?ref=morsewall.com">Redux store</a>).</p><p>Although React components can manage their own state locally, without the need of an external library (like in <a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/#flavor-6-html-css-react-quotes-array">flavor #6</a> and <a href="https://morsewall.com/random-quote-part-8-react-hooks-using-various-front-end-stacks/#flavor-8-html-css-react-hooks-quotes-array">flavor #8</a>), as applications grow bigger, with several components, managing state that is shared across components becomes a difficult and messy task.</p><p>Having said that, as mentioned previously, this app is simple enough that it can be done solely in React. Actually, it is so simple that it can be shipped with essentially <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#flavor-1-html-css-vanilla-js-quotes-array">3 lines of functional Vanilla JavaScript code (flavor #1)</a>.</p><hr><h3 id="adding-the-react-redux-library">Adding the React Redux library</h3><p></p><p>Since Redux is not designed to work with React out of the box, I&#x2019;m adding the <a href="https://react-redux.js.org/?ref=morsewall.com">React Redux</a> package to let my React components read data from the Redux store, and dispatch actions to the store to update data.</p><p>The React Redux library is available from a <a href="https://redux.js.org/basics/usage-with-react?ref=morsewall.com#installing-react-redux">precompiled UMD package</a>, so I can simply add it as <code>script</code> to my HTML.</p><p>Like previously in <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#adding-the-redux-library">flavor #4</a>, I&#x2019;m adding Redux to the project via a UMD build. The snippet below shows the bottom of my HTML.</p><pre><code class="language-js">&lt;!-- index.html --&gt;
	&lt;!-- adding the React library from a precompiled UMD packages. React is the global variable to call React. --&gt;
	&lt;script src=&quot;https://unpkg.com/react@16/umd/react.production.min.js&quot; crossorigin&gt;&lt;/script&gt;
	&lt;script src=&quot;https://unpkg.com/react-dom@16/umd/react-dom.production.min.js&quot; crossorigin&gt;&lt;/script&gt;
	&lt;!-- Loading the Babel compiler. When loaded in a browser, @babel/standalone will automatically compile and execute all script tags with type text/babel or text/jsx: --&gt;
	&lt;script src=&quot;https://unpkg.com/@babel/standalone/babel.min.js&quot;&gt;&lt;/script&gt;
	&lt;!-- adding the Redux library from a precompiled UMD package. window.Redux is the global variable to call Redux. --&gt;
	&lt;script src=&quot;https://unpkg.com/redux@4.0.4/dist/redux.js&quot;&gt;&lt;/script&gt;
	&lt;!-- adding the React Redux library from a precompiled UMD package. ReactRedux is the global variable to call React Redux. --&gt;
	&lt;script src=&quot;https://unpkg.com/react-redux@7.1.1/dist/react-redux.min.js&quot;&gt;&lt;/script&gt;
	&lt;!-- special text/babel MIME type --&gt;
	&lt;script type=&quot;text/babel&quot; src=&quot;src/script.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p></p><p>The React Redux UMD build makes React Redux available as a <code>ReactRedux</code> global variable.</p><h3 id="no-javascript-modules-here-again">No JavaScript modules here (again)</h3><p></p><p>For the reasons I&#x2019;ve detailed in <a href="http://localhost:4000/notes/random-quote-machine-part6/#no-javascript-modules-here">flavor #6</a>, I&#x2019;m not dividing this flavor&#x2019;s code into modules.</p><p>In other words, this flavor has a long JS file.</p><h3 id="flavor-10-html-css-react-hooks-react-redux-quotes-array">Flavor #10: HTML + CSS + React Hooks + React Redux + quotes array</h3><p></p><p>In this flavor, I&#x2019;m creating a Redux store that manages the state of the entire app. The React components can then subscribe to the pieces of data in the store that are relevant to them. <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#action-events-events-triggering-actions">Actions</a> are dispatched directly from React components. These dispatched actions then ultimately trigger store updates (for more on state, check <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#what-is-state">&#x201C;What is <code>state</code>?&#x201D; in flavor #4</a>).</p><p>Actually, since much of the Redux code in this flavor remains the same as in <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#flavor-4-html-css-redux-quotes-array-in-js-module">flavor #4</a>, it may be helpful to give that writing a quick read.</p><p>I have the data (quotes) in an array inside my <code>script.js</code> like previously in <a href="http://localhost:4000/notes/random-quote-machine-part8/#flavor-8-html--css--react-hooks--quotes-array">flavor #8</a>.</p><h3 id="restructuring-the-react-components">Restructuring the React Components</h3><p></p><p>Before I get into state management, I&#x2019;m breaking down my large React component into smaller components. Such restructuring makes the application easier to read, maintain and grow [sic] (Because this application has so much growth potential, right?). So, I&#x2019;m splitting the previously monolithic <code>App</code> React Component (which was large and contained a lot of functionality) into 4 components instead.</p><p>Once again, this is a simple app, but for more complex applications, not breaking down large components would make them hard to test and would easily lead to non-<a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself?ref=morsewall.com">DRY</a> code.</p><h3 id="reusable-quote-box">Reusable Quote Box</h3><p></p><p>I&#x2019;m creating a reusable quote box to handle a potential &#x201C;future case&#x201D; in which I&#x2019;m scaling the app [sic] and want to add more screens/routes to it. I&#x2019;d then reuse the same quote box, but with different text (data). I&#x2019;m getting <code>author</code> and <code>text</code> values from the <code>App</code> component via <a href="https://reactjs.org/docs/components-and-props.html/?ref=morsewall.com"><code>props</code></a></p><pre><code class="language-JS">//script.js
const QuoteBox = ({ text, author }) =&gt; {
  //destructuring
  return (
    &lt;React.Fragment&gt;
      &lt;div className=&quot;quotable-square&quot;&gt;
        &lt;div className=&quot;content&quot;&gt;
          &lt;div id=&quot;text&quot;&gt;{text}&lt;/div&gt;
          &lt;div id=&quot;author&quot; className=&quot;author&quot;&gt;
            {author}
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/React.Fragment&gt;
  );
};</code></pre><h3 id="passing-props-to-components"><br>Passing props to components</h3><p></p><p>Components can be customized when they are created with different parameters. These parameters are called <code>props</code> (or properties) and they are used in a React application to send data from one React component to another React component. <code>props</code> can be considered as arguments to a function which returns JSX. The value of this &#x201C;argument&#x201D; can then be accessed in the function body (variable name within curly braces).</p><p>As per code snippet above, I&#x2019;m getting <code>author</code> and <code>text</code> values from a parent component component. Note that I&#x2019;m destructuring props by using the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment/?ref=morsewall.com"><code>destructuring assignment</code> syntax</a> above. This allows me to clearly define my <code>props</code> as they get passed from a parent to a child component and get rid of the <code>props</code> word in the component&#x2019;s definition.</p><p>The parent component (<code>App</code>), as per below code snippet, passes <code>text</code> and <code>author</code> values to the <code>Quotebox</code> component.</p><p>In this specific case (of a React Redux application), there is obviously some more to it, since the parent component (<code>App</code>) is having <code>props</code> passed to it. This is because Redux is passing state to <code>App</code> via <code>props</code> (more on this further down). That said, the dynamics of passing data from a parent component to a child component are as simple as per snippet above and below.</p><pre><code class="language-js">//script.js
//defining the function component. Redux state and dispatch are passed to the component as props
const App = props =&gt; {
  ...
  //the component returns JSX, and as per code snippet below, JSX clearly represents HTML, composing the UI. As a React component can only return one single element, I&#x2019;m using &lt;React.Fragment&gt; to add a parent tag to my JSX elements without adding an extra node to the DOM.
  return (
    &lt;React.Fragment&gt;
      &lt;div className=&quot;container&quot;&gt;
        &lt;div id=&quot;quote-box&quot;&gt;
          {/* passing data via props to QuoteBox component */}
          &lt;QuoteBox
            text={props.currentQuote.data.quoteText}
            author={props.currentQuote.data.quoteAuthor}
          /&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;footer&gt;
        &lt;ul className=&quot;footer-options&quot;&gt;
          &lt;li className=&quot;footer-link&quot;&gt;
            &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
              Legal
            &lt;/a&gt;
          &lt;/li&gt;
          &lt;li className=&quot;footer-link&quot;&gt;
            &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
              Contact Us
            &lt;/a&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
        &lt;span&gt;&#xA9; 2019 Developed by Pat Eskinasy. All Rights Reserved.&lt;/span&gt;
      &lt;/footer&gt;
    &lt;/React.Fragment&gt;
  );
};
</code></pre><p></p><h3 id="reusable-button">Reusable Button</h3><p></p><p>I&#x2019;m creating a reusable button to handle a potential &#x201C;future case&#x201D; in which I want to have two buttons, instead of having only one &#x201C;New Quote&#x201D; button. For instance: one for Next Quote and one for Previous Quote.</p><pre><code class="language-js">// script.js
const Button = ({ onClick, title }) =&gt; {
  return (
    &lt;button className=&quot;new-quote&quot; onClick={onClick}&gt;
      {title}
    &lt;/button&gt;
  );
};
</code></pre><p></p><h3 id="reusable-share-button">Reusable Share Button</h3><p></p><p>Finally, I&#x2019;m creating a reusable share button to handle a potential &#x201C;future case&#x201D; in which I want to add additional social share buttons, instead of only one &#x201C;Tweet Quote&#x201D; button. These buttons would then share the same styling, but receive different props.</p><pre><code class="language-js">//script.js
const TwitterShare = ({ link }) =&gt; {
  return (
    &lt;React.Fragment&gt;
      &lt;button className=&quot;tweet-quote&quot;&gt;
        &lt;a
          href={link}
          target=&quot;_blank&quot;
          title=&quot;Tweet this on Twitter&quot;
          id=&quot;tweet-quote&quot;
        &gt;
          &lt;em className=&quot;fab fa-twitter&quot;&gt;&lt;/em&gt;Tweet Quote
        &lt;/a&gt;
      &lt;/button&gt;
    &lt;/React.Fragment&gt;
  );
};
</code></pre><p></p><h3 id="redux-and-initial-state">Redux and initial state</h3><p></p><p>From the <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user stories</a>, I want to be welcomed by a quote when I first load the app. In other words, I want to be able to read the quote from the Redux store on first page load.</p><p>So far, however, I haven&#x2019;t even set up the Redux store yet.</p><pre><code class="language-js">// script.js
// The UMD build makes Redux available as a window.Redux global variable
const Redux = window.Redux;

//defining initial state
const initialState = {
  data: quotes[Math.floor(Math.random() * quotes.length)],
};

//defining an action type
const NEW_QUOTE = &quot;NEW_QUOTE&quot;;

//defining an action creator, which creates the action to select a new quote.  The action creator is a function that returns an action (object that contains information about an action-event that has occurred). It creates the action to add a new quote.
const newQuoteActionCreator = (quoteObject) =&gt; {
  return {
    type: NEW_QUOTE,
    payload: quoteObject,
  };
};

//creating a reducer that handles the state for quotes. The redux state is initially set to an empty object. The reducer adds a quote to the object of quotes held in state or return the current state.
const getNextQuoteReducer = (state = initialState, action) =&gt; {
  switch (action.type) {
    case NEW_QUOTE:
      return {
        ...state,
        data: action.payload,
      };
    default:
      return state;
  }
};

//creating the Redux store and passing the reducer to it
const store = Redux.createStore(getNextQuoteReducer);
</code></pre><p></p><!--kg-card-begin: html--><div class="notice" style="position:relative;min-height: 1em;margin-top: 1.45rem;margin-bottom: 1.45rem;padding: 1em 1.5em 1.5em;border: 2px solid;-webkit-box-shadow: 0.25em 0.25em 0 #000;box-shadow: 0.25em 0.25em 0 #000;">
    <h3 id="disclaimer-react-hooks" style="display: block;margin-bottom: 1.25em;padding-bottom: 0.25em;border-bottom: 2px solid">Disclaimer: Use of switch...case in reducers</h3>
    <div>
        <p>
            switch...case statements are great to show how the internals work but aren&apos;t typically used in production. You can <a href="https://redux-toolkit.js.org/usage/usage-guide/?ref=morsewall.com/#writing-reducers">use any conditional logic you want</a> to write a reducer.
        </p>
    </div>
</div>    <!--kg-card-end: html--><p>Nearly all code in the snippet above follows the Redux logic implemented in <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#action-events-events-triggering-actions">part 4 of this series - action events section</a> and just like previously, I&#x2019;m making the initial state (<code>initialState</code>) a selected random quote.</p><p><code>App</code> still can&#x2019;t read state from the Redux store though. This is because Redux still hasn&#x2019;t been connected to React and no <code>props</code> are being passed to <code>App</code> yet.</p><p>In a Redux application, I&#x2019;d normally create UI listeners that would dispatch actions to the Redux store. Then, I&#x2019;d create store listeners which would be called whenever a new state is set in the Redux store. Once again, it may be helpful to give <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#flavor-4-html-css-redux-quotes-array-in-js-module">flavor #4</a> a quick read.</p><p>In a React Redux application, however, the execution flow is a bit different.</p><h3 id="a-visual-look-into-the-application%E2%80%99s-execution-flow">A visual look into the application&#x2019;s execution flow</h3><p></p><p>In summary, I&#x2019;m changing the state in the Redux store with random quotes that get selected as the application runs. Redux updates the store with help from an action creator, a reducer and the React Redux API.</p><p>On high-level, data flows in a similar way to <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#a-visual-look-into-the-application%E2%80%99s-execution-flow">part 4 of this series - Execution flow in a Redux application</a>: Different React components, such as the <em>Get New Quote</em> button, trigger state changes in the Redux store (with a new random quote) and a React component next updates the UI with the new state.</p><p>In a diagram (more on the React Redux methods further down):</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-2.cloudinary.com/hnhggca76/image/upload/q_auto/v1/ghost-blog-images/react_redux_execution_flow.png" class="kg-image" alt="How to Build a Random Quote Machine &#x2013; Part 10 &#x2013; React Hooks and React Redux: Using various front end stacks" loading="lazy" width="2088" height="1920"><figcaption>React Redux Execution Flow</figcaption></figure><h3 id="react-redux-api"><br>React Redux API</h3><p></p><p>The <a href="https://react-redux.js.org/?ref=morsewall.com">React Redux package</a> provides an API that allows me to provide React access to the Redux store and the actions it needs to dispatch updates. This API offers two key features: <a href="https://react-redux.js.org/api/provider?ref=morsewall.com"><code>&lt;Provider /&gt;</code></a> and <a href="https://react-redux.js.org/api/connect?ref=morsewall.com"><code>connect()</code></a>.</p><p>I, however, need to specify what state and what actions I want. This is to make sure that each React component will only access the state it needs and actions it should have access to. To achieve this, I&#x2019;m defining two functions: <a href="https://react-redux.js.org/using-react-redux/connect-mapstate?ref=morsewall.com"><code>mapStateToProps</code></a> and <a href="https://react-redux.js.org/using-react-redux/connect-mapdispatch?ref=morsewall.com"><code>mapDispatchToProps</code></a>.</p><!--kg-card-begin: html--><div class="notice" style="position:relative;min-height: 1em;margin-top: 1.45rem;margin-bottom: 1.45rem;padding: 1em 1.5em 1.5em;border: 2px solid;-webkit-box-shadow: 0.25em 0.25em 0 #000;box-shadow: 0.25em 0.25em 0 #000;">
    <h3 id="disclaimer-react-hooks" style="display: block;margin-bottom: 1.25em;padding-bottom: 0.25em;border-bottom: 2px solid">Disclaimer: React-Redux Hooks API and <code>connect()</code></h3>
    <div>
        <p>
           You may have noticed that flavors using React-Redux hooks have been crossed out from the <a href="#list-of-flavors">list of flavors covered in this 11-part series</a>. This is mainly due to me (at time of writing), being opinionated about React-Redux hooks since code becomes harder to test given the tighter coupling between the React component and Redux.
        </p>
        <p>
			(Update 2021 I: The recommendation is now that using the React-Redux hooks API should be the <a href="https://react-redux.js.org/api/hooks/?ref=morsewall.com">default approach in your React components</a>).
        </p>
        <p>
            The existing <code>connect</code> API, however, still works and will continue to be supported.
        </p>
        <p>
             (Update 2021 II: The intention with this series is to get very incremental progress from one stack to another. Making it all as much bare bones as possible in order to get concepts adequately explored and explained. For this reason, I&apos;ve covered the Redux core library (unopinionated - let&apos;s you decide how to handle everything) in the flavors covered in this series. That said, <a href="https://redux.js.org/redux-toolkit/overview/?ref=morsewall.com">Redux Toolkit</a> is now intended to be the standard way to write Redux logic and the recommendation is for it to be used).
        </p>
    </div>
</div>    <!--kg-card-end: html--><p></p><h3 id="mapstatetoprops"><code>mapStateToProps</code></h3><p></p><p>Defining <code>mapStateToProps</code>:</p><pre><code class="language-js">//script.js
//mapping state to props. Allows me to specify exactly what pieces of the state should the React component have access to. Taking state as argument, it returns an object which maps that state to specific property names. These properties will become accessible to the React component via props
const mapStateToProps = (state) =&gt; {
  return {
    currentQuote: state,
  };
};
</code></pre><p></p><p><code>mapStateToProps</code> is called every time the store state changes. It receives the entire store state and returns an object of data the component needs. It maps that state to specific property names (in this case <code>currentQuote</code>). These properties are then accessible to my React component via props (with the help of <code>connect()</code>).</p><h3 id="mapdispatchtoprops"><br><code>mapDispatchToProps</code></h3><p><br>Defining <code>mapDispatchToProps</code>:</p><pre><code class="language-js">//script.js
//mapping dispatch to props. Specifying what actions should the React component have access to. Allows me to specify which action creators I need to be able to dispatch. It is used to provide specific action creators to the React components so they can dispatch actions against the Redux store. It returns an object that maps dispatch actions to property names, which become component props. As opposed to mapStateToProps (that returns a piece of state), here each property returns a function that calls dispatch with an action creator and any relevant action data. I have access to this dispatch because it&apos;s passed in to mapDispatchToProps() as a parameter when I define the function, just like I&apos;ve passed state to mapStateToProps(). The object should have a property selectNewQuote set to the dispatch function, which takes a parameter for the new quote to add when it dispatches newQuoteActionCreator().
const mapDispatchToProps = (dispatch) =&gt; {
  return {
    selectNewQuote: function (quoteToBeNewQuote) {
      dispatch(newQuoteActionCreator(quoteToBeNewQuote));
    },
  };
};
</code></pre><p></p><p><code>dispatch</code> is a function of the Redux store. In Redux, I&#x2019;d call <code>store.dispatch</code> to dispatch an action. This would be, in the Redux case, the only way to trigger a state change.</p><p>With React Redux, <code>mapDispatchToProps</code> lets me create functions that dispatch when called. Then, with the help of <code>connect()</code>, I can pass those functions as props to my React component.</p><p><code>mapDispatchToProps</code> receives <code>dispatch</code> and returns an object that maps dispatch actions to specific property names (in this case <code>selectNewQuote</code>, which I will be calling inside my React component further down). These properties are then accessible to my React component via props (through <code>connect()</code>). Each property returns a function that calls <code>dispatch</code> with an action creator (in this case<code>newQuoteActionCreator</code>) and any relevant action data (here, a randomly selected quote).</p><h3 id="connect"><br><code>connect()</code></h3><p></p><p>The <code>connect()</code> method from React Redux allows me to map <code>state</code> and <code>dispatch</code> to the props of a React component. It connects a React component to the Redux store. It provides its connected component with the pieces of the data it needs from the store, and the functions it can use to dispatch actions to the store (with the help of <code>mapStateToProps</code> and <code>mapDispatchToProps</code>).</p><pre><code class="language-js">//script.js
//setting React Redux connect to a constant.
const connect = ReactRedux.connect;

//connecting Redux to React. Mapping state and dispatch to the props of the React component. Container then represents the connected component.
const Container = connect(mapStateToProps, mapDispatchToProps)(App);
</code></pre><p></p><h3 id="provider"><code>&lt;Provider /&gt;</code></h3><p></p><p>In React Redux, <code>connect</code> attempts to get the store from the <code>&lt;Provider /&gt;</code>. The <code>&lt;Provider /&gt;</code> wraps my React application. It allows my React app to access the Redux store (providing <code>state</code>) and <code>dispatch</code> function throughout my React component. The Redux store is passed as a prop to <code>&lt;Provider /&gt;</code>.</p><pre><code class="language-js">//script.js
//using Provider to connect redux to react. Allows me to provide state and dispatch to React components. Setting React Redux Provider to a constant.
const Provider = ReactRedux.Provider;

//defining the Provider wrapper. Allows me to access the Redux store and dispatch functions. Finalizing connecting the Redux store with the React component, thereby extracting the local state into the Redux store. Provider wraps the React app and allows me to access the Redux store and dispatch actions throughout the React component. The Redux store is passed as a prop to the Provider.
const AppWrapper = () =&gt; {
  return (
    &lt;Provider store={store}&gt;
      &lt;Container /&gt;
    &lt;/Provider&gt;
  );
};
</code></pre><p></p><p>With the above in place, <code>App</code> can now read state from the Redux store and it now becomes clearer why <a href="#passing-props-to-components">I&#x2019;ve mentioned further above</a> that the parent component (<code>App</code>) needs <code>props</code> passed to it (because Redux is passing state - and dispatch - to <code>App</code> via <code>props</code>).</p><p>By now, my application can render a random quote on the screen upon first page load. And with this, I have shipped the first <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user story</a>.</p><h3 id="react-dispatching-actions">React Dispatching Actions</h3><p></p><p>I still need to ship <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user story #2</a>: I want to be able to click a UI element (a button) to get a new quote. To achieve this, I&#x2019;ll need to dispatch an action from my React component.</p><p>When the <em>Get New Quote</em> button is clicked, React calls <code>chosenRandomQuoteToState</code>, which calls <code>selectNewQuote</code> (see <a href="http://localhost:4000/notes/random-quote-machine-part10/#mapdispatchtoprops"><code>mapDispatchToProps</code></a> above), as it has been passed as <code>props</code> to <code>App</code>. Now, provided the specific action creator (<code>newQuoteActionCreator</code>, coming from <code>mapDispatchToProps</code>), the React component can dispatch actions against the Redux store and update the state.</p><pre><code class="language-js">//script.js
const App = props =&gt; {
  ...
  const random = array =&gt; {
    return Math.floor(Math.random() * array.length);
  };

  const randomQuoteFunction = array =&gt; {
    return array[random(array)];
  };

  //defining a function to (ultimately) update the Redux state with a new quote. Passing a randomly selected quote via props. Dispatching selectNewQuote() from props and passing in the randomly selected new quote as an argument
  const chosenRandomQuoteToState = () =&gt; {
    //selecting a random quote from the array
    let chosenQuote = randomQuoteFunction(quotes);
    props.selectNewQuote(chosenQuote);
  };

  //the component returns JSX, and as per code snippet below, JSX clearly represents HTML, composing the UI. As a React component can only return one single element, I&#x2019;m using &lt;React.Fragment&gt; to add a parent tag to my JSX elements without adding an extra node to the DOM.
  return (
    &lt;React.Fragment&gt;
      &lt;div className=&quot;container&quot;&gt;
        &lt;div id=&quot;quote-box&quot;&gt;
          {/* passing data via props to QuoteBox component */}
          &lt;QuoteBox
            text={props.currentQuote.data.quoteText}
            author={props.currentQuote.data.quoteAuthor}
          /&gt;
          &lt;div className=&quot;actions&quot;&gt;
            &lt;Button
              id=&quot;new-quote&quot;
              title=&quot;Get New Quote&quot;
              onClick={chosenRandomQuoteToState}
            /&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;footer&gt;
        &lt;ul className=&quot;footer-options&quot;&gt;
          &lt;li className=&quot;footer-link&quot;&gt;
            &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
              Legal
            &lt;/a&gt;
          &lt;/li&gt;
          &lt;li className=&quot;footer-link&quot;&gt;
            &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
              Contact Us
            &lt;/a&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
        &lt;span&gt;&#xA9; 2019 Developed by Pat Eskinasy. All Rights Reserved.&lt;/span&gt;
      &lt;/footer&gt;
    &lt;/React.Fragment&gt;
  );
};
</code></pre><p></p><p>And just like previously (in the case of first page load), <code>App</code> reads state from the Redux store (given Redux is passing state to <code>App</code> via <code>props</code>) and the newly selected random quote will render on the screen.</p><p>The GIF below shows state changing in the application as I request a new quote with the <em>Get New Quote</em> button.</p><!--kg-card-begin: markdown--><p><img src="https://i.ibb.co/kDnXS2b/track-state-chages-redux.gif" alt="How to Build a Random Quote Machine &#x2013; Part 10 &#x2013; React Hooks and React Redux: Using various front end stacks" loading="lazy"></p>
<!--kg-card-end: markdown--><p></p><p>As a note, to track state (as per gif above), and as previously done in <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#what-is-state">flavor #4</a>, I use <a href="https://github.com/zalmoxisus/redux-devtools-extension/?ref=morsewall.com">Redux DevTools Extension</a> to time travel in the application&#x2019;s state. The extension records dispatched actions (more on dispatched actions below in the article) and the state of the Redux store (more on the store further down) at every point in time. This allows me to inspect the state and travel back in time to a previous application state without reloading the page.</p><h3 id="building-the-uithe-parent-function-component">Building the UI - The Parent Function Component</h3><p></p><p>Defining <code>App</code>, the function component, now in full:</p><pre><code class="language-js">//script.js
// defining the function component. Redux state and dispatch are passed to the component as props
const App = (props) =&gt; {
  //making the machine tweet
  let twitterLink;

  let quoteTextElem = props.currentQuote.data.quoteText;
  let quoteAuthorElem = &quot; - &quot; + props.currentQuote.data.quoteAuthor;
  let contentQuote = quoteTextElem + quoteAuthorElem;
  if (contentQuote.length &gt; 280) {
    let charCountAuthor = quoteAuthorElem.length;
    const extraStylingChar = &quot;...&quot; + &apos;&quot;&apos;;
    let extraCharCount = extraStylingChar.length;
    let subString =
      quoteTextElem.substring(0, 280 - extraCharCount - charCountAuthor) +
      extraStylingChar +
      quoteAuthorElem;
    //generate url available for Twitter intent and inject url on HTML
    twitterLink = &quot;https://twitter.com/intent/tweet?text=&quot; + subString;
  } else {
    //generate url available for Twitter intent and inject url on HTML
    twitterLink = &quot;https://twitter.com/intent/tweet?text=&quot; + contentQuote;
  }

  const random = (array) =&gt; {
    return Math.floor(Math.random() * array.length);
  };

  const randomQuoteFunction = (array) =&gt; {
    return array[random(array)];
  };

  //defining a function to (ultimately) update the Redux state with a new quote. Passing a randomly selected quote via props. Dispatching selectNewQuote() from props and passing in the randomly selected new quote as an argument
  const chosenRandomQuoteToState = () =&gt; {
    //selecting a random quote from the array
    let chosenQuote = randomQuoteFunction(quotes);
    props.selectNewQuote(chosenQuote);
  };

  //the component returns JSX, and as per code snippet below, JSX clearly represents HTML, composing the UI. As a React component can only return one single element, I&#x2019;m using &lt;React.Fragment&gt; to add a parent tag to my JSX elements without adding an extra node to the DOM.
  return (
    &lt;React.Fragment&gt;
      &lt;div className=&quot;container&quot;&gt;
        &lt;div id=&quot;quote-box&quot;&gt;
          {/* passing data via props to QuoteBox component */}
          &lt;QuoteBox
            text={props.currentQuote.data.quoteText}
            author={props.currentQuote.data.quoteAuthor}
          /&gt;
          &lt;div className=&quot;actions&quot;&gt;
            &lt;Button
              id=&quot;new-quote&quot;
              title=&quot;Get New Quote&quot;
              onClick={chosenRandomQuoteToState}
            /&gt;
            &lt;TwitterShare link={twitterLink} /&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;footer&gt;
        &lt;ul className=&quot;footer-options&quot;&gt;
          &lt;li className=&quot;footer-link&quot;&gt;
            &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
              Legal
            &lt;/a&gt;
          &lt;/li&gt;
          &lt;li className=&quot;footer-link&quot;&gt;
            &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
              Contact Us
            &lt;/a&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
        &lt;span&gt;&#xA9; 2019 Developed by Pat Eskinasy. All Rights Reserved.&lt;/span&gt;
      &lt;/footer&gt;
    &lt;/React.Fragment&gt;
  );
};
</code></pre><p>The code to make the machine tweet (in snippet above inside <code>App</code>) is very much in line with what has been implemented in all previous flavors of this project. In other words, the code here follows the logic implemented in <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#making-the-machine-tweet">part 1 of this series</a>.</p><p>So now the random quote machine ships all the required user stories!</p><p>You can <a href="https://morsewall.github.io/random-quote-react-hooks-react-redux/">check the project live</a>. Source code for <a href="https://github.com/morsewall/random-quote-react-hooks-react-redux">flavor #10 in Github</a>.</p><!--kg-card-begin: html--><div class="button-set">
    <button style="border-radius:8px;background-color:#000000;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://morsewall.github.io/random-quote-react-hooks-react-redux/" style="margin:1rem;" class="button-in-post">Live Project</a></button>
    <button style="border-radius:8px;background-color:#000000;color:#ffffff;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://github.com/morsewall/random-quote-react-hooks-react-redux" style="margin:1rem;" class="button-in-post">Source code</a></button>
</div><!--kg-card-end: html--><hr><h3 id="acknowledgement">Acknowledgement</h3><p></p><p>The following goes without saying, but here it comes anyways: Please note that in this ever changing world of technology, I am writing this article in July 2019 (hello, summer!) and alternate solutions might have become available as you read this writing.</p><hr><p><em>In Part 11 (to be posted next week - the last part of this series), I will cover an eleventh flavor and will be using Redux Thunk to call an asynchronous endpoint to request the data (quotes) from an external resource (all while still building the UI with React Hooks).</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><hr><p><em>So, what did you like about this post? <a href="https://twitter.com/celue">Come say hello on Twitter!</a></em></p><!--kg-card-begin: html--><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Why I am overcomplicating a really simple application that can be shipped in 3 lines of functional Vanilla JavaScript. Reason: Shipping a simple app in a simple environment with fewer moving parts=great way to practice a new way to solve a problem<br><br>Part 10 of a 11-part series out <a href="https://t.co/WL6hVSOJDE">pic.twitter.com/WL6hVSOJDE</a></p>&#x2014; Pat&apos;s Morse Wall (@morsewall) <a href="https://twitter.com/morsewall/status/1438199857290829830?ref_src=twsrc%5Etfw">September 15, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script><!--kg-card-end: html--><p></p><p><em>Also, if you have built a random quote machine after reading this post, share it as comment to the tweet above on Twitter. Really excited to see what you create!</em></p><p><em>Happy coding!</em></p><hr><h3 id="where-to-find-me">Where to find me:</h3><p></p><p>Follow me on Twitter:</p><!--kg-card-begin: markdown--><p><a href="https://twitter.com/celue"><img src="https://i.ibb.co/pZ016N6/Follow-Pat-Eskinasy.png" alt="How to Build a Random Quote Machine &#x2013; Part 10 &#x2013; React Hooks and React Redux: Using various front end stacks" style="width:100%"></a></p>
<!--kg-card-end: markdown--><p>You can always get my latest writings directly to your email address by <a href="https://morsewall.com/signup/"><strong>subscribing to Morse Wall</strong></a><strong>.</strong></p><p></p><hr><h3 id="update">UPDATE</h3><p></p><p>Part 11 of this series has now been published. <a href="https://morsewall.com/random-quote-part-11-react-hooks-react-redux-and-redux-thunk-using-various-front-end-stacks/">Go check it out!</a>. I continue using Redux to help me update the different components with the current application state, but the app is using Redux Thunk to call an asynchronous endpoint as the data (quotes) is requested from an external resource (a JSON stored in a public content delivery network (CDN)) (like in <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#flavor-5-html-css-redux-json-with-quotes">flavor #5</a>). This time, however, I&#x2019;m using React to build the UI (not manually building the UI with HTML, like previously) in the eleventh (and last) flavor.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Random Quote Machine – Part 9 – React Hooks and JSON: Using various front end stacks]]></title><description><![CDATA[11 ways - How to build a random quote machine. Calling asynchronous endpoints in a React app with Hooks.]]></description><link>https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/</link><guid isPermaLink="false">6383e1b825c4380210dd3d53</guid><category><![CDATA[React]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Side Project]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[JSON]]></category><dc:creator><![CDATA[Pat Eskinasy]]></dc:creator><pubDate>Wed, 08 Sep 2021 10:40:00 GMT</pubDate><media:content url="https://morsewall.com/content/images/2022/11/useeffect.png" medium="image"/><content:encoded><![CDATA[<h3 id="building-a-random-quote-machine-with-react-hooks-and-json">Building a random quote machine with React Hooks and JSON</h3><img src="https://morsewall.com/content/images/2022/11/useeffect.png" alt="How to Build a Random Quote Machine &#x2013; Part 9 &#x2013; React Hooks and JSON: Using various front end stacks"><p></p><p>This is Part 9 of the <em>Making a random quote machine in a few different flavors</em> series.</p><p><em>You can read more about this project&#x2019;s background <a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">on the project&#x2019;s page</a>. Or start from the beginning with <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">part 1 of this series</a>.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><p>In <a href="https://morsewall.com/random-quote-part-8-react-hooks-using-various-front-end-stacks/#flavor-8-html-css-react-hooks-quotes-array">flavor #8</a>, I&#x2019;m creating function components in a React app with Hooks and I have the data (quotes) inside an array. In this flavor, the data is inside a JSON file (like in <a href="https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/#flavor-7-html-css-react-json-with-quotes">flavor #7</a>), but here I&#x2019;m creating function components in a React app with Hooks (not using React classes like previously).</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Random Quote Machine – Part 8 – React Hooks: Using various front end stacks]]></title><description><![CDATA[11 ways - How to build a random quote machine. Creating function components in a React app with Hooks.]]></description><link>https://morsewall.com/random-quote-part-8-react-hooks-using-various-front-end-stacks/</link><guid isPermaLink="false">6383e13f25c4380210dd3ccf</guid><category><![CDATA[React]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Side Project]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Pat Eskinasy]]></dc:creator><pubDate>Wed, 01 Sep 2021 14:20:00 GMT</pubDate><media:content url="https://morsewall.com/content/images/2022/11/reacthooks.png" medium="image"/><content:encoded><![CDATA[<h3 id="building-a-random-quote-machine-with-react-hooks">Building a random quote machine with React Hooks</h3><img src="https://morsewall.com/content/images/2022/11/reacthooks.png" alt="How to Build a Random Quote Machine &#x2013; Part 8 &#x2013; React Hooks: Using various front end stacks"><p></p><p>This is Part 8 of the <em>Making a random quote machine in a few different flavors</em> series.</p><p><em>You can read more about this project&#x2019;s background <a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">on the project&#x2019;s page</a>. Or start from the beginning with <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">part 1 of this series</a>.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><p>In <a href="https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/#flavor-7-html-css-react-json-with-quotes">flavor #7</a>, the app&#x2019;s UI is built using a User Interface Library (React) and I have the data (quotes) inside a JSON file. In this flavor, the data is inside an array (like in <a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/#flavor-6-html-css-react-quotes-array">flavor #6</a>), but here I&#x2019;m creating function components in a React app with Hooks (not using React classes like previously).</p><p>These are the different flavors that are part of this series: </p><!--kg-card-begin: html--><ol>
    <li><a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-3-vanilla-javascript-and-rest-api-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes REST API</a></li>
    <li><strike>HTML + Vanilla JS + SAAS + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about SASS)</em></li>
    <li><strike>HTML + Vanilla JS + Bootstrap + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about Bootstrap)</em></li>
    <li><strike>HTML + CSS + JQuery + JSON with quotes</strike><em> (nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/">HTML + CSS + Redux + quotes array</a></li>
    <li><strike>HTML + CSS + Redux + JQuery + JSON with quotes</strike> <em>(nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/">HTML + CSS + Redux + Redux Thunk + JSON with quotes</a></li>
    <li><a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/"> HTML + CSS + React + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/">HTML + CSS + React + JSON with quotes</a> (members-only post)</li>
    <li>HTML + CSS + React Hooks + quotes array (this flavor)</li>
    <li><a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/">HTML + CSS + React Hooks + JSON with quotes</a> (members-only post)</li>
    <li><strike>HTML + CSS + React + React Redux + quotes array</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><strike>HTML + CSS + React + React Redux + Redux Thunk + JSON with quotes</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-11-react-hooks-react-redux-and-redux-thunk-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + Redux Thunk + JSON with quotes</a></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + Redux Thunk + JSON with quote</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
</ol> <!--kg-card-end: html--><p>If you are new here, you may wonder why I am overcomplicating a really simple application that can be shipped in 3 lines of functional Vanilla JavaScript. And the reason is: Shipping a simple app in a simple environment with fewer moving parts = great way to practice a new way to solve a problem. This is the spirit behind the <em><em><a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">Making a random quote machine in a few different flavors</a></em></em> series. Enjoy!</p><hr><p><em>In Part 9 (to be posted next week), I will cover a ninth flavor and will be calling an asynchronous endpoint to request the data, while still using React Hooks.</em></p><p><br><em>If you&#x2019;re curious about the next flavors and would like to make a writer very happy today, you should <strong><a href="https://morsewall.com/signup/">subscribe to Morse Wall</a>.</strong></em></p><hr><h2 id="flavor-8-html-css-react-hooks-quotes-array">Flavor #8: HTML + CSS + React Hooks + quotes array</h2><p></p><p>I have the data (quotes) in an array inside my <code>script.js</code> like previously in <a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/#flavor-6-html-css-react-quotes-array">flavor #6</a>.</p><p>Actually, since much of the code in this flavor remains the same as in <a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/#flavor-6-html-css-react-quotes-array">flavor #6</a>, it may be helpful to give that writing a quick read.</p><p></p><h3 id="why-react-hooks">Why React Hooks?</h3><p></p><p>React Hooks do not add new features to React, they are a different way of doing the same (not being facetious though, there is obviously strong <a href="https://reactjs.org/docs/hooks-intro.html?ref=morsewall.com#motivation">motivation behind React Hooks</a>).</p><p>But if the TLDR according to the React core team is: <a href="https://reactjs.org/docs/hooks-intro.html?ref=morsewall.com#gradual-adoption-strategy">&#x201C;There are no plans to remove classes from React&#x201D;</a>, why make a flavor with React Hooks? Because:</p><blockquote>True that&#x2026;</blockquote><blockquote>There are always (at least) two ways to solve a problem. One is faster, the other you just don&#x2019;t know yet.</blockquote><p>The above is the spirit behind the <em><a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">Making a random quote machine in a few different flavors</a></em> series. And with that in mind, there is no better way to practice a new way to solve a problem than to ship a simple app in a simpler environment with fewer moving parts. Enjoy!</p><p><strong>Quick note</strong>: React is moving on. It is possible that in the future, class support might move into a separate package.</p><h3 id="one-function-component">One function component</h3><p></p><p>I&#x2019;ll be incrementally expanding one <a href="https://reactjs.org/docs/hooks-state.html?ref=morsewall.com#hooks-and-function-components">function component</a> throughout this write-up. This component selects a quote from the quotes array, it then sets this quote in the component&#x2019;s internal state (for more on state, check <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#what-is-state">&#x201C;What is <code>state</code>?&#x201D; in flavor #4</a>) and lastly, renders the quote in the HTML.</p><p>&#x201C;Function components&#x201D; in React come with <a href="https://reactjs.org/docs/hooks-intro.html/?ref=morsewall.com">React Hooks</a> and were previously known as &#x201C;stateless functional components&#x201D;. These components did not contain their own state previously, but with React Hooks they are now able to have their own state.</p><p>Defining <code>App</code>, the function component:</p><pre><code class="language-js">// script.js
//defining the function component.
const App = () =&gt; {};</code></pre><p><br>I&#x2019;m designing <code>App</code> to select a random quote, set the quote in the component&#x2019;s internal state and lastly render the quote in the HTML.</p><p>Firstly, I&#x2019;m <a href="https://reactjs.org/docs/hooks-reference.html?ref=morsewall.com#lazy-initial-state">lazily initializing</a> the <code>quote</code> state variable to the value returned by <code>quotes[Math.floor(Math.random() * quotes.length)]</code>. I do this by calling the <code>useState</code> Hook (more on what&#x2019;s a Hook further down) inside the component.</p><p>This initial state is used during the initial render. In subsequent renders, it is disregarded. The function I&#x2019;m passing to <code>useState</code> will be executed only on the initial render.</p><pre><code class="language-js">// script.js
//defining the function component.
const App = () =&gt; {
  const quoteState = useState(() =&gt; {
    return quotes[Math.floor(Math.random() * quotes.length)];
  });
  const quote = quoteState[0]; // Contains the value returned by function passed to `useState`
  const setQuote = quoteState[1]; // It&#x2019;s a function
};
</code></pre><p></p><p>Simplifying the above with <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment?ref=morsewall.com#Array_destructuring"><code>array destructuring</code></a>:</p><pre><code>// script.js
//defining the function component.
const App = () =&gt; {
  //using a function to lazy initialize the initial state
  const [quote, setQuote] = React.useState(() =&gt; {
    return quotes[Math.floor(Math.random() * quotes.length)];
  });
};
</code></pre><p></p><p>The <code>useState</code> Hook returns two values (an array with two items): the first item is the current state and the second is a function that allows me to update the state.</p><p>A Hook is a special function that allows me to &#x201C;hook into&#x201D; React features. <code>useState</code> is a Hook that lets me add React state to function components.</p><p>Previously, whenever I had to add state to a stateless functional component, I had to convert it to a class. Now I can simply use a Hook inside the component.</p><h3 id="the-component%E2%80%99s-state"><br>The component&#x2019;s state</h3><p></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-4.cloudinary.com/hnhggca76/image/upload/q_auto/v1/ghost-blog-images/reactstatehooks.png" class="kg-image" alt="How to Build a Random Quote Machine &#x2013; Part 8 &#x2013; React Hooks: Using various front end stacks" loading="lazy" width="1080" height="1080"><figcaption>React state hooks</figcaption></figure><p></p><p>With the code so far, I&#x2019;m setting the initial random quote in the component&#x2019;s state, but have not fully shipped the full <em>&#x201C;I want to be welcomed by a quote when I first load the app&#x201D;</em> <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user story</a> since I have not made the component render yet. My page is still empty.</p><h3 id="updating-the-state"><br>Updating the state</h3><p><br>Before I move into rendering, I&#x2019;m defining a function (<code>chosenRandomQuoteToState</code>) to update the state with a new quote. This will allow me to handle the second <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user stories</a>: <em>&#x201C;I want to be able to click a UI element (a button) to get a new quote&#x201D;.</em></p><pre><code class="language-js">// index.js
const App = () =&gt; {
  //using a function to lazy initialize the initial state
  const [quote, setQuote] = React.useState(() =&gt; {
    return quotes[Math.floor(Math.random() * quotes.length)];
  });

  const random = (array) =&gt; {
    return Math.floor(Math.random() * array.length);
  };

  const randomQuoteFunction = (array) =&gt; {
    return array[random(array)];
  };

  //defining a function to update the state with a new quote
  const chosenRandomQuoteToState = () =&gt; {
    //selecting a random quote from the array
    let chosenQuote = randomQuoteFunction(quotes);
    setQuote(chosenQuote);
  };
};
</code></pre><p></p><p>I&#x2019;ve made the decision to write the non-<a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself?ref=morsewall.com">DRY</a> code above (I&#x2019;m repeating myself when defining <code>random</code> and <code>randomQuoteFunction</code> as these functions had already been written when passed to <code>useState</code> as lazy initial state) since, as per the <a href="https://reactjs.org/docs/hooks-rules.html?ref=morsewall.com">Rules of Hooks</a>, I should only call Hooks <a href="https://reactjs.org/docs/hooks-rules.html?ref=morsewall.com?ref=morsewall.com#only-call-hooks-at-the-top-level">at the top level</a> of a React function component.</p><p>The nice thing with this rule, is that it ensures (beyond other things) that all stateful logic in a component is clearly visible when one reads the code.</p><p>As per code snippet above, I&#x2019;m updating the state by calling <code>setQuote</code>, the function that allows me to update the state.</p><p>My page is still empty though, the component does not return any JSX yet. Time to build the UI and attach the necessary event handlers.</p><h3 id="building-the-ui"><br>Building the UI</h3><p></p><p>The <code>button</code> element below has an <code>onClick()</code> handler. This handler is triggered when the button receives a click event in the browser and runs the <code>chosenRandomQuoteToState</code> function defined previously.</p><p><code>chosenRandomQuoteToState</code> then updates the state with a new random quote by calling <code>setCount</code>. React will then re-render the <code>App</code> component, passing the new <code>quote</code> value to it (rendering <code>quote.quoteText</code> and <code>quote.quoteAuthor</code> as the quote text and the quote author respectively).</p><pre><code class="language-js">//defining the function component.
const App = () =&gt; {
  const [quote, setQuote] = React.useState(&quot;&quot;);

  const random = (array) =&gt; {
    return Math.floor(Math.random() * array.length);
  };

  const randomQuoteFunction = (array) =&gt; {
    return array[random(array)];
  };

  //defining a function to update the state with a new quote
  const chosenRandomQuoteToState = () =&gt; {
    //selecting a random quote from the array
    let chosenQuote = randomQuoteFunction(quotes);
    setQuote(chosenQuote);
  };

  //the component returns JSX, and as per code snippet below, JSX clearly represents HTML, composing the UI.
  return (
    //as a React component can only return one single element, I&#x2019;m using &lt;React.Fragment&gt; to add a parent tag to my JSX elements without adding an extra node to the DOM.
    &lt;React.Fragment&gt;
      &lt;div className=&quot;container&quot;&gt;
        &lt;div id=&quot;quote-box&quot;&gt;
          &lt;div className=&quot;quotable-square&quot;&gt;
            &lt;div className=&quot;content&quot;&gt;
              &lt;div id=&quot;text&quot;&gt;{quote.quoteText}&lt;/div&gt;
              &lt;div id=&quot;author&quot; className=&quot;author&quot;&gt;
                {quote.quoteAuthor}
              &lt;/div&gt;
            &lt;/div&gt;
          &lt;/div&gt;
          &lt;div className=&quot;actions&quot;&gt;
            &lt;button
              id=&quot;new-quote&quot;
              className=&quot;new-quote&quot;
              onClick={chosenRandomQuoteToState}
            &gt;
              Get New Quote
            &lt;/button&gt;
            &lt;button className=&quot;tweet-quote&quot;&gt;
              &lt;a id=&quot;tweet-quote&quot; href={twitterLink} target=&quot;_blank&quot;&gt;
                &lt;em className=&quot;fab fa-twitter&quot;&gt;&lt;/em&gt;Tweet Quote
              &lt;/a&gt;
            &lt;/button&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;footer&gt;
        &lt;ul className=&quot;footer-options&quot;&gt;
          &lt;li className=&quot;footer-link&quot;&gt;
            &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
              Legal
            &lt;/a&gt;
          &lt;/li&gt;
          &lt;li className=&quot;footer-link&quot;&gt;
            &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
              Contact Us
            &lt;/a&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
        &lt;span&gt;&#xA9; 2019 Developed by Pat Eskinasy. All Rights Reserved.&lt;/span&gt;
      &lt;/footer&gt;
    &lt;/React.Fragment&gt;
  );
};</code></pre><p></p><p>With the code so far I&#x2019;m shipping both the first and the second <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user stories</a>!</p><h3 id="making-the-machine-tweet"><br>Making the machine tweet</h3><p></p><p>The logic to invoke <a href="https://developer.twitter.com/en/docs/twitter-for-websites/web-intents/overview.html?ref=morsewall.com">Twitter Web Intents</a> is, however, still missing (allowing me to ship the last <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user story</a>: <em>&#x201C;I want to be able to share on Twitter the quote the random quote machine gives me so that I can share my source of inspiration with the world&#x201D;</em>), so here it comes:</p><pre><code class="language-js">// script.js

//defining the function component.
const App = () =&gt; {
  ...
//making the machine tweet
  let twitterLink;
  let quoteTextElem = quote.quoteText;
  let quoteAuthorElem = &quot; - &quot; + quote.quoteAuthor;
  let contentQuote = quoteTextElem + quoteAuthorElem;
  if (contentQuote.length &gt; 280) {
    let charCountAuthor = quoteAuthorElem.length;
    const extraStylingChar = &quot;...&quot; + &apos;&quot;&apos;;
    let extraCharCount = extraStylingChar.length;
    let subString =
      quoteTextElem.substring(0, 280 - extraCharCount - charCountAuthor) +
      extraStylingChar +
      quoteAuthorElem;
    //generate url available for Twitter intent and inject url on HTML
    twitterLink = &quot;https://twitter.com/intent/tweet?text=&quot; + subString;
  } else {
    //generate url available for Twitter intent and inject url on HTML
    twitterLink = &quot;https://twitter.com/intent/tweet?text=&quot; + contentQuote;
  }
  return (
  ...
  )
}
</code></pre><p></p><p>The above code to make the machine tweet is very much in line with what has been implemented in all previous flavors of this project. In other words, the code here follows the logic implemented in <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#making-the-machine-tweet">part 1 of this series</a>.</p><p>This is pretty much it. The rest of the code remains the same as in <a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/#flavor-6-html-css-react-quotes-array">flavor #6</a>.</p><p>You can <a href="https://morsewall.github.io/random-quote-react-hooks/">check the project live</a>. Source code for <a href="https://github.com/morsewall/random-quote-react-hooks">flavor #8 in Github</a>.</p><!--kg-card-begin: html--><div class="button-set">
    <button style="border-radius:8px;background-color:#000000;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://morsewall.github.io/random-quote-react-hooks/" style="margin:1rem;" class="button-in-post">Live Project</a></button>
    <button style="border-radius:8px;background-color:#000000;color:#ffffff;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://github.com/morsewall/random-quote-react-hooks" style="margin:1rem;" class="button-in-post">Source code</a></button>
</div><!--kg-card-end: html--><hr><h3 id="acknowledgement">Acknowledgement</h3><p></p><p>The following goes without saying, but here it comes anyways: Please note that in this ever changing world of technology, I am writing this article in July 2019 (hello, summer!) and alternate solutions might have become available as you read this writing.</p><hr><p><em>In Part 9 (to be posted next week), I will cover a ninth flavor and will be calling an asynchronous endpoint to request the data, while still using React Hooks.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><hr><p><em>So, what did you like about this post? <a href="https://twitter.com/celue">Come say hello on Twitter!</a></em></p><!--kg-card-begin: html--><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Whoop Whoop! You can now follow the write up on how to rewrite your React-powered random quote machine with React Hooks <a href="https://t.co/fDCQaa1pDA">pic.twitter.com/fDCQaa1pDA</a></p>&#x2014; Pat&apos;s Morse Wall (@morsewall) <a href="https://twitter.com/morsewall/status/1433093205898186755?ref_src=twsrc%5Etfw">September 1, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script><!--kg-card-end: html--><p></p><p><em>Also, if you have built a random quote machine after reading this post, share it as comment to the tweet above on Twitter. Really excited to see what you create!</em></p><p><em>Happy coding!</em></p><hr><h3 id="where-to-find-me">Where to find me:</h3><p></p><p>Follow me on Twitter:</p><!--kg-card-begin: markdown--><p><a href="https://twitter.com/celue"><img src="https://i.ibb.co/pZ016N6/Follow-Pat-Eskinasy.png" alt="How to Build a Random Quote Machine &#x2013; Part 8 &#x2013; React Hooks: Using various front end stacks" style="width:100%"></a></p>
<!--kg-card-end: markdown--><p>You can always get my latest writings directly to your email address by<strong> <a href="https://morsewall.com/signup/">subscribing to Morse Wall</a>.</strong></p><hr><h3 id="update">UPDATE</h3><p></p><p>Part 9 of this series has now been published. <a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/">Go check it out!</a> The data is inside a JSON file (like in <a href="https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/#flavor-7-html-css-react-json-with-quotes">flavor #7</a>) but I&#x2019;m creating function components in a React app with Hooks (not using React classes like previously) in the ninth flavor.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Random Quote Machine – Part 7 – React and JSON: Using various front end stacks]]></title><description><![CDATA[11 ways - How to build a random quote machine. Calling asynchronous endpoints in a React app.]]></description><link>https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/</link><guid isPermaLink="false">6383e0ac25c4380210dd3cb7</guid><category><![CDATA[React]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Side Project]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[JSON]]></category><dc:creator><![CDATA[Pat Eskinasy]]></dc:creator><pubDate>Wed, 25 Aug 2021 10:36:00 GMT</pubDate><media:content url="https://morsewall.com/content/images/2022/11/componentDidMount.png" medium="image"/><content:encoded><![CDATA[<h3 id="building-a-random-quote-machine-with-react-and-json">Building a random quote machine with React and JSON</h3><img src="https://morsewall.com/content/images/2022/11/componentDidMount.png" alt="How to Build a Random Quote Machine &#x2013; Part 7 &#x2013; React and JSON: Using various front end stacks"><p></p><p>This is Part 7 of the <em>Making a random quote machine in a few different flavors</em> series.</p><p><em>You can read more about this project&#x2019;s background <a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">on the project&#x2019;s page</a>. Or start from the beginning with <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">part 1 of this series</a>.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><p>In <a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/#flavor-6-html-css-react-quotes-array">flavor #6</a>, the app&#x2019;s UI is built using a User Interface Library (React) and I have the data (quotes) inside an array. In this flavor, I&#x2019;m still using React but the app calls an asynchronous endpoint to request the data.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Random Quote Machine – Part 6 – React: Using various front end stacks]]></title><description><![CDATA[11 ways - How to build a random quote machine. Using React to build the UI.]]></description><link>https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/</link><guid isPermaLink="false">6383dfcf3345310210bdc015</guid><category><![CDATA[React]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Side Project]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Pat Eskinasy]]></dc:creator><pubDate>Wed, 18 Aug 2021 11:47:00 GMT</pubDate><media:content url="https://morsewall.com/content/images/2022/11/react_snippet.png" medium="image"/><content:encoded><![CDATA[<h3 id="building-a-random-quote-machine-with-react">Building a random quote machine with React</h3><img src="https://morsewall.com/content/images/2022/11/react_snippet.png" alt="How to Build a Random Quote Machine &#x2013; Part 6 &#x2013; React: Using various front end stacks"><p></p><p>This is Part 6 of the <em>Making a random quote machine in a few different flavors</em> series.</p><p><em>You can read more about this project&#x2019;s background <a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">on the project&#x2019;s page</a>. Or start from the beginning with <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">part 1 of this series</a>.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><p>In <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#flavor-5-html--css--redux--json-with-quotes">flavor #5</a>, the different UI elements are updated using state management with Redux using a middleware as the app calls an asynchronous endpoint.</p><p>In this flavor, I use a User Interface Javascript library (React) to build the app&#x2019;s UI.</p><p>These are the different flavors that are part of this series:</p><!--kg-card-begin: html--><ol>
    <li><a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-3-vanilla-javascript-and-rest-api-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes REST API</a></li>
    <li><strike>HTML + Vanilla JS + SAAS + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about SASS)</em></li>
    <li><strike>HTML + Vanilla JS + Bootstrap + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about Bootstrap)</em></li>
    <li><strike>HTML + CSS + JQuery + JSON with quotes</strike><em> (nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/">HTML + CSS + Redux + quotes array</a></li>
    <li><strike>HTML + CSS + Redux + JQuery + JSON with quotes</strike> <em>(nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/">HTML + CSS + Redux + Redux Thunk + JSON with quotes</a></li>
    <li>HTML + CSS + React + quotes array (this flavor)</li>
    <li><a href="https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/">HTML + CSS + React + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-8-react-hooks-using-various-front-end-stacks/">HTML + CSS + React Hooks + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/">HTML + CSS + React Hooks + JSON with quotes</a> (members-only post)</li>
    <li><strike>HTML + CSS + React + React Redux + quotes array</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><strike>HTML + CSS + React + React Redux + Redux Thunk + JSON with quotes</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-11-react-hooks-react-redux-and-redux-thunk-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + Redux Thunk + JSON with quotes</a></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + Redux Thunk + JSON with quote</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
</ol> <!--kg-card-end: html--><p>If you are new here, you may wonder why I am overcomplicating a really simple application that can be shipped in 3 lines of functional Vanilla JavaScript. And the reason is: Shipping a simple app in a simple environment with fewer moving parts = great way to practice a new way to solve a problem. This is the spirit behind the <em><em><a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">Making a random quote machine in a few different flavors</a></em></em> series. Enjoy!</p><hr><p><em>In Part 7 (to be posted next week), I will cover a seventh flavor and will be calling an asynchronous endpoint to request the data, while still using React.</em></p><p><em>If you&#x2019;re curious about the next flavors and would like to make a writer very happy today, you should <strong><a href="https://morsewall.com/signup/">subscribe to Morse Wall</a>.</strong></em></p><hr><h3 id="adding-the-react-library">Adding the React library</h3><p></p><p>The React library is available from a <a href="https://reactjs.org/docs/add-react-to-a-website.html?ref=morsewall.com#tip-minify-javascript-for-production">precompiled UMD package</a>, so I can simply add it as <code>script</code> to my HTML. The snippet below shows the bottom of my HTML.</p><pre><code class="language-html">&lt;!-- index.html --&gt;
	&lt;!-- adding the React library from a precompiled UMD packages. React is the global variable to call React. --&gt;
	&lt;script src=&quot;https://unpkg.com/react@16/umd/react.production.min.js&quot; crossorigin&gt;&lt;/script&gt;
	&lt;script src=&quot;https://unpkg.com/react-dom@16/umd/react-dom.production.min.js&quot; crossorigin&gt;&lt;/script&gt;
	&lt;!-- Loading the Babel compiler. When loaded in a browser, @babel/standalone will automatically compile and execute all script tags with type text/babel or text/jsx: --&gt;
	&lt;script src=&quot;https://unpkg.com/@babel/standalone/babel.min.js&quot;&gt;&lt;/script&gt;
	&lt;!-- special text/babel MIME type --&gt;
	&lt;script type=&quot;text/babel&quot; src=&quot;src/script.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p></p><p>As normal <code>script</code> elements pass minimal information for scripts served from CDNs, I&#x2019;m passing <code>crossorigin</code> as an attribute to <code>&lt;script&gt;</code> to allow me to get real error logging.</p><p>I&#x2019;m also adding the <a href="https://reactjs.org/docs/react-dom.html?ref=morsewall.com#overview"><code>ReactDOM</code></a> library as it adds specific methods that allow me to use React for web development, i.e. render to the browser (React is, otherwise, independent from the browser and can be used outside of it, e.g. on mobile devices with React Native).</p><p>With React I&#x2019;m essentially writing HTML in JavaScript. React uses a syntax extension called JSX to enable that (React without JSX is, in my opinion, <a href="https://reactjs.org/docs/react-without-jsx.html?ref=morsewall.com">less readable</a>). But because JSX is not valid JavaScript, JSX code must be compiled into JavaScript. I&#x2019;m setting up compilation with <a href="https://babeljs.io/?ref=morsewall.com">Babel</a> (served from a CDN as per my code snippet above).</p><p>Babel automatically compiles and executes all <code>script</code> tags with type <code>text/babel</code> or <code>text/jsx</code>. So, as per snippet above, I&#x2019;m loading <code>script.js</code> with type <code>text/babel</code>.</p><h3 id="no-javascript-modules-here">No JavaScript modules here</h3><p></p><p>Babel does not, however, perform client-side transpiling of modules. In fact, unless I&#x2019;d use a plugin, Babel transforms <code>import</code> into <code>require()</code>, which means that at some point I&#x2019;d get <code>require is not defined</code> on my browser console should I try to use <code>import</code> statements inside Babel-transpiled scripts.</p><p>I&#x2019;d be able to work around this with <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules?ref=morsewall.com">JavaScript modules</a> applied via script tag <code>&lt;script type=&quot;module&quot;&gt;</code> (like <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#module">I&#x2019;ve done previously</a>), but for the following reasons I&#x2019;m not dividing this code into modules like I&#x2019;ve done previously in <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#flavor-4-html-css-redux-quotes-array-in-js-module">flavor #4</a> and <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/#flavor-5-html-css-redux-json-with-quotes">flavor #5</a>:</p><ul><li>I cannot add a second type (<code>type=module</code>) attribute to the <code>script</code> tag</li><li>I cannot use another script tag attribute (e.g. <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs?ref=morsewall.com"><code>data</code> attribute</a>) to tell Babel to compile my script (hello, @<a href="https://babeljs.io/?ref=morsewall.com">Babel</a>?)</li><li>I&#x2019;m not willing to use a pre-compiled module bundler like <a href="https://webpack.js.org/?ref=morsewall.com">webpack</a> (this is a simple project)</li></ul><p>In other words, this flavor has a long JS file.</p><h3 id="flavor-6-html-css-react-quotes-array"><br>Flavor #6: HTML + CSS + React + quotes array</h3><p><br>Like previously in <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#flavor-1-html-css-vanilla-js-quotes-array">flavor #1</a>, I have the data (quotes) in an array inside my <code>script.js</code>. There are only 3 quotes in the code snippet below (so I can illustrate the point), but many more quotes in the array in production.</p><pre><code class="language-js">/ script.js
//defining an array for the quotes
const quotes = [
  {
    quoteText:
      &apos;&quot;Many of you appear concerned that we are wasting valuable lesson time, but I assure you we will go back to school the moment you start listening to science and give us a future.&quot;&apos;,
    quoteAuthor: &quot;@GretaThunberg&quot;,
  },
  {
    quoteText:
      &apos;&quot;I was fortunate to be born in a time and place where everyone told us to dream big. I could become whatever I wanted to. I could live wherever I wanted to. People like me had everything we needed and more. Things our grandparents could not even dream of. We had everything we could ever wish for and yet now we may have nothing. Now we probably don&#x2019;t even have a future any more.&quot;&apos;,
    quoteAuthor: &quot;@GretaThunberg&quot;,
  },
  {
    quoteText:
      &apos;&quot;That future was sold so that a small number of people could make unimaginable amounts of money. It was stolen from us every time you said that the sky was the limit, and that you only live once. You lied to us. You gave us false hope. You told us that the future was something to look forward to.&quot;&apos;,
    quoteAuthor: &quot;@GretaThunberg&quot;,
  },
];</code></pre><p></p><h3 id="one-stateful-component">One stateful component</h3><p></p><p>I&#x2019;ll be incrementally expanding one stateful component throughout this write-up. This component selects a quote from the quotes array, it then sets this quote in the component&#x2019;s internal state (for more on state, check <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#what-is-state">&#x201C;What is <code>state</code>?&#x201D; in flavor #4</a>) and lastly, renders the quote in the HTML.</p><p>Covering what is on my HTML, this is all there is to it now when it comes to <code>&lt;div&gt;</code>s (as always, you can check the <a href="https://github.com/morsewall/random-quote-react">full source code in the repo</a>. Also linked at the bottom of this write-up):</p><pre><code class="language-html">&lt;!-- index.html --&gt;
&lt;div id=&quot;app&quot;&gt;&lt;/div&gt;</code></pre><p></p><p>I&#x2019;m adding an empty <code>&lt;div&gt;</code> tag to mark the spot where I want to display with React.</p><p>I&#x2019;m giving the <code>&lt;div&gt;</code> a unique <code>id</code> HTML attribute. This allows me to find it from the JavaScript code and display a React component inside of it.</p><p>React has it&#x2019;s own representation of the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction?ref=morsewall.com">DOM</a>. React then uses snapshots of <a href="https://reactjs.org/docs/faq-internals.html?ref=morsewall.com">its own DOM</a> to update only specific parts of the DOM. This helps the browser use less resources when changes need to be done on a page.</p><p>Back to JavaScript, <code>ReactDOM.render(componentToRender, targetNode)</code> places the JSX into React&#x2019;s own DOM. In this project (the snippet below shows the bottom of my <code>script.js</code>):</p><pre><code class="language-js">// script.js
ReactDOM.render(&lt;App /&gt;, document.getElementById(&quot;app&quot;));</code></pre><p></p><p><code>componentToRender</code> here is <code>App</code>, the React component to be rendered (when React encounters a custom HMTL tag that references a component - a component name wrapped in <code>&lt; /&gt;</code> in this case - , it renders the markup for the component in the location of the tag) and <code>targetNode</code> is the DOM node that the component shall be rendered to.</p><p>Before that though, I need to define <code>App</code> (the stateful component):</p><pre><code class="language-js">// script.js
class App extends React.Component {
  constructor(props) {
    super(props);
  }
}</code></pre><p></p><p>This creates the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes?ref=morsewall.com">JavaScript class</a> <code>App</code> that extends the <code>React.Component</code> class. With this, <code>App</code> can now access React features.</p><p>The <code>App</code> class has a constructor defined within it that calls <code>super()</code>. It uses <code>super()</code> to call the constructor of the parent class, in this case <code>React.Component</code>. The constructor is a special method used during the initialization of objects that are created with the <code>class</code> keyword. It is best practice to call a component&#x2019;s constructor with super, and pass <a href="https://reactjs.org/docs/components-and-props.html?ref=morsewall.com"><code>props</code></a> to both. This makes sure the component is initialized properly.</p><p>As per my <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user stories</a>: &#x201C;I want to be welcomed by a quote when I first load the app&#x201D;. So far, however, I haven&#x2019;t even selected the random quote yet. So, doing that now:</p><pre><code class="language-js">// index.js
class App extends React.Component {
  constructor(props) {
    super(props);
    let quote = this.randomQuoteFunction(quotes);
    this.state = {
      quoteTextChosen: quote.quoteText,
      quoteAuthorChosen: quote.quoteAuthor,
    };
  }
  random(array) {
    return Math.floor(Math.random() * array.length);
  }

  randomQuoteFunction(array) {
    return array[this.random(array)];
  }
}</code></pre><p></p><p>From the above, I&#x2019;m defining the <a href="https://reactjs.org/docs/state-and-lifecycle.html?ref=morsewall.com#using-state-correctly">component initial state</a>, allowing the app to display any part of it in the UI that is rendered (more on rendering further down).</p><!--kg-card-begin: html--><div class="notice" style="position:relative;min-height: 1em;margin-top: 1.45rem;margin-bottom: 1.45rem;padding: 1em 1.5em 1.5em;border: 2px solid;-webkit-box-shadow: 0.25em 0.25em 0 #000;box-shadow: 0.25em 0.25em 0 #000;">
    <h3 id="disclaimer-react-hooks" style="display: block;margin-bottom: 1.25em;padding-bottom: 0.25em;border-bottom: 2px solid">Disclaimer: React Hooks</h3>
    <div>
        <p>
            I should also mention that React is changing fast and and the method exposed here could be already obsolete by the time you&#x2019;ll read this article. At the time of writing, <a href="https://reactjs.org/docs/hooks-intro.html/?ref=morsewall.com"> React Hooks</a> is available on a stable release and can be used to ship this application under a slightly different structure (for a React Hooks flavor, make sure to check flavor #8 of this series).
        </p>
        <p>
            All in all, the recommendation here is: <a href="https://reactjs.org/docs/hooks-faq.html?ref=morsewall.com#should-i-use-hooks-classes-or-a-mix-of-both">Don&#x2019;t go rewriting all your class components</a>. Also, while there are <a href="https://reactjs.org/docs/hooks-intro.html?ref=morsewall.com#gradual-adoption-strategy">no plans</a> to remove classes from React, do try hooks if you are writing new code.
        </p>
    </div>
</div>    <!--kg-card-end: html--><p></p><h2 id="the-component%E2%80%99s-state">The component&#x2019;s state</h2><p></p><p>As mentioned <a href="#one-stateful-component">above</a>, <code>App</code>, the React component is designed to select a random quote, set the quote in the component&#x2019;s internal state and lastly render the quote in the HTML.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-5.cloudinary.com/hnhggca76/image/upload/q_auto/v1/ghost-blog-images/state.png" class="kg-image" alt="How to Build a Random Quote Machine &#x2013; Part 6 &#x2013; React: Using various front end stacks" loading="lazy" width="1080" height="1080"><figcaption>React component state</figcaption></figure><p></p><p>I still need to <a href="https://reactjs.org/docs/faq-functions.html?ref=morsewall.com">bind <code>this</code></a> to the two class methods previously defined (<code>random</code> and <code>randomQuoteFunction</code>) in the constructor. This way the class methods can use <code>this</code> to access properties on the class (such as <code>state</code>) inside the scope of the method and I won&#x2019;t get <code>undefined</code> on my browser console when calling functions like <code>this.randomQuotes(quotes)</code>.</p><pre><code class="language-js">// script.js
class App extends React.Component {
  constructor(props) {
    super(props);
    this.random = this.random.bind(this);
    this.randomQuoteFunction = this.randomQuoteFunction.bind(this);
    let quote = this.randomQuoteFunction(quotes);
    this.state = {
      quoteTextChosen: quote.quoteText,
      quoteAuthorChosen: quote.quoteAuthor,
    };
  }
  random(array) {
    return Math.floor(Math.random() * array.length);
  }

  randomQuoteFunction(array) {
    return array[this.random(array)];
  }
}</code></pre><p></p><p>With the code so far I&#x2019;m setting the random quote in the component&#x2019;s state, but have not fully shipped the full <em>&#x201C;I want to be welcomed by a quote when I first load the app&#x201D;</em> user story since I have not made the component render yet. My page is still empty.</p><p></p><h3 id="updating-the-state">Updating the state</h3><p></p><p></p><p>Before I move into rendering, I&#x2019;m defining a new class method (<code>chosenRandomQuoteToState</code>) to update the state with a new quote. This will allow me to handle the second <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user story</a>: <em>&#x201C;I want to be able to click a UI element (a button) to get a new quote&#x201D;</em>.</p><pre><code class="language-js">// script.js
class App extends React.Component {
  constructor(props) {
    super(props);
    this.random = this.random.bind(this);
    this.randomQuoteFunction = this.randomQuoteFunction.bind(this);
    this.chosenRandomQuoteToState = this.chosenRandomQuoteToState.bind(this);
    let quote = this.randomQuoteFunction(quotes);
    this.state = {
      quoteTextChosen: quote.quoteText,
      quoteAuthorChosen: quote.quoteAuthor,
    };
  }
  random(array) {
    return Math.floor(Math.random() * array.length);
  }

  randomQuoteFunction(array) {
    return array[this.random(array)];
  }

  chosenRandomQuoteToState() {
    let newQuote = this.randomQuoteFunction(quotes);
    this.setState({
      quoteTextChosen: newQuote.quoteText,
      quoteAuthorChosen: newQuote.quoteAuthor,
    });
  }
}</code></pre><p></p><p>Like I&#x2019;ve done with the previously defined class methods, I&#x2019;m binding <code>this</code> to <code>chosenRandomQuoteToState</code> in the constructor.</p><p>From above, when defining <code>chosenRandomQuoteToState</code>, I&#x2019;m updating the component&#x2019;s state with React&#x2019;s <a href="https://reactjs.org/docs/react-component.html?ref=morsewall.com#setstate"><code>setState</code></a> method. To update the state I pass in an object with key-value pairs to <code>this.setState()</code>. They keys are the state properties and the values are the updated state data.</p><h3 id="rendering-the-component"><br>Rendering the component</h3><p></p><p>Time to render the component. The component returns <a href="https://reactjs.org/docs/introducing-jsx.html?ref=morsewall.com">JSX</a>, and as per code snippet below, JSX clearly represents HTML, composing the UI.</p><p>In JSX I can no longer use the world <code>class</code> to define HTML classes since <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes?ref=morsewall.com"><code>class</code> is a reserved word in JavaScript</a>. JSX uses <code>className</code> instead. Furthermore, the naming convention for HTML attributes and event references in JSX <a href="https://reactjs.org/docs/handling-events.html?ref=morsewall.com">become camelCase</a>, so a click event is <code>onClick</code>, instead of <code>onclick</code>.</p><p>The <code>button</code> element has an <code>onClick()</code> handler. This handler is triggered when the button receives a click event in the browser and runs the <code>chosenRandomQuoteToState</code> method defined previously.</p><pre><code class="language-js">class App extends React.Component {
  constructor(props) {
    super(props);
    this.random = this.random.bind(this);
    this.randomQuoteFunction = this.randomQuoteFunction.bind(this);
    this.chosenRandomQuoteToState = this.chosenRandomQuoteToState.bind(this);
    let quote = this.randomQuoteFunction(quotes);
    this.state = {
      quoteTextChosen: quote.quoteText,
      quoteAuthorChosen: quote.quoteAuthor,
    };
  }
  random(array) {
    return Math.floor(Math.random() * array.length);
  }

  randomQuoteFunction(array) {
    return array[this.random(array)];
  }

  chosenRandomQuoteToState() {
    let newQuote = this.randomQuoteFunction(quotes);
    this.setState({
      quoteTextChosen: newQuote.quoteText,
      quoteAuthorChosen: newQuote.quoteAuthor,
    });
  }

  render() {
    let twitterLink;
    return (
      &lt;React.Fragment&gt;
        &lt;div className=&quot;container&quot;&gt;
          &lt;div id=&quot;quote-box&quot;&gt;
            &lt;div className=&quot;quotable-square&quot;&gt;
              &lt;div className=&quot;content&quot;&gt;
                &lt;div id=&quot;text&quot;&gt;{this.state.quoteTextChosen}&lt;/div&gt;
                &lt;div id=&quot;author&quot; className=&quot;author&quot;&gt;
                  {this.state.quoteAuthorChosen}
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;
            &lt;div className=&quot;actions&quot;&gt;
              &lt;button
                id=&quot;new-quote&quot;
                className=&quot;new-quote&quot;
                onClick={this.chosenRandomQuoteToState}
              &gt;
                Get New Quote
              &lt;/button&gt;
              &lt;button className=&quot;tweet-quote&quot;&gt;
                &lt;a id=&quot;tweet-quote&quot; href={twitterLink} target=&quot;_blank&quot;&gt;
                  &lt;em className=&quot;fab fa-twitter&quot;&gt;&lt;/em&gt;Tweet Quote
                &lt;/a&gt;
              &lt;/button&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;footer&gt;
          &lt;ul className=&quot;footer-options&quot;&gt;
            &lt;li className=&quot;footer-link&quot;&gt;
              &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
                Legal
              &lt;/a&gt;
            &lt;/li&gt;
            &lt;li className=&quot;footer-link&quot;&gt;
              &lt;a href=&quot;#&quot; className=&quot;footer-linktext&quot;&gt;
                Contact Us
              &lt;/a&gt;
            &lt;/li&gt;
          &lt;/ul&gt;
          &lt;span&gt;&#xA9; 2019 Developed by Pat Eskinasy. All Rights Reserved.&lt;/span&gt;
        &lt;/footer&gt;
      &lt;/React.Fragment&gt;
    );
  }
}
</code></pre><p></p><p>As a React component can only return one single element, I&#x2019;m using <a href="https://reactjs.org/docs/fragments.html?ref=morsewall.com"><code>&lt;React.Fragment&gt;</code></a> to add a parent tag to my JSX elements without adding an extra node to the DOM. <code>React.Fragment</code> outputs no HTML element (it is an invisible HTML tag).</p><p>Any code to be treated as JavaScript comes within <a href="https://reactjs.org/docs/introducing-jsx.html?ref=morsewall.com#embedding-expressions-in-jsx">curly braces in JSX</a>. So, as I access a state value within the <code>return</code> of the render method, I have to enclose the value in curly braces, e.g. <code>{this.state.quoteTextChosen}</code>.</p><p>Since this component is stateful, it has access to the data in <code>state</code> in its <code>render()</code> method. React uses a virtual DOM to keep track of changes in state behind the scenes. When state data update changes, React triggers a re-render of the component using the data. React then updates the actual DOM, but only when necessary.</p><h3 id="making-the-machine-tweet"><br>Making the machine tweet</h3><p></p><p>The logic to invoke <a href="https://developer.twitter.com/en/docs/twitter-for-websites/web-intents/overview.html?ref=morsewall.com">Twitter Web Intents</a> is still missing (allowing me to ship the last <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user story</a>: <em>&#x201C;I want to be able to share on Twitter the quote the random quote machine gives me so that I can share my source of inspiration with the world&#x201D;</em>), so here it comes:</p><pre><code class="language-js">// script.js
render() {
    let twitterLink;
    let quoteTextElem = this.state.quoteTextChosen;
    let quoteAuthorElem = &quot; - &quot; + this.state.quoteAuthorChosen;
    let contentQuote = quoteTextElem + quoteAuthorElem;
    if (contentQuote.length &gt; 280) {
      let charCountAuthor = quoteAuthorElem.length;
      const extraStylingChar = &quot;...&quot; + &apos;&quot;&apos;;
      let extraCharCount = extraStylingChar.length;
      let subString =
        quoteTextElem.substring(0, 280 - extraCharCount - charCountAuthor) +
        extraStylingChar +
        quoteAuthorElem;
      //generate url available for Twitter intent and inject url on HTML
      twitterLink = &quot;https://twitter.com/intent/tweet?text=&quot; + subString;
    } else {
      //generate url available for Twitter intent and inject url on HTML
      twitterLink = &quot;https://twitter.com/intent/tweet?text=&quot; + contentQuote;
    }
    return (
      ...
    )
}</code></pre><p></p><p>The JavaScript code (above <code>return</code>), dealing with making the machine tweet is very much in line with what has been implemented in all previous flavors of this project. In other words, the code here follows the logic implemented in <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#making-the-machine-tweet">part 1 of this series</a>.</p><p>So now the random quote machine ships all the required user stories!</p><p>You can <a href="https://morsewall.github.io/random-quote-react/">check the project live</a>. Source code for <a href="https://github.com/morsewall/random-quote-react">flavor #6 in Github</a>.</p><!--kg-card-begin: html--><div class="button-set">
    <button style="border-radius:8px;background-color:#000000;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://morsewall.github.io/random-quote-react/" style="margin:1rem;" class="button-in-post">Live Project</a></button>
    <button style="border-radius:8px;background-color:#000000;color:#ffffff;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://github.com/morsewall/random-quote-react" style="margin:1rem;" class="button-in-post">Source code</a></button>
</div><!--kg-card-end: html--><hr><h3 id="acknowledgement">Acknowledgement</h3><p></p><p>The following goes without saying, but here it comes anyways: Please note that in this ever changing world of technology, I am writing this article in July 2019 (hello, summer!) and alternate solutions might have become available as you read this writing.</p><hr><p><em>In Part 7 (to be posted next week), I will cover a seventh flavor and will be calling an asynchronous endpoint to request the data, while still using React.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><hr><p><em>So, what did you like about this post? <a href="https://twitter.com/celue">Come say hello on Twitter!</a></em></p><!--kg-card-begin: html--><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Of course you need one more tutorial on how to build a random quote machine with React &#x1F64C;<br><br>My tutorial covers 11 different ways on how to build a random quote machine though (not only with React) (Ha!) <a href="https://t.co/GQdB1lsIR9">pic.twitter.com/GQdB1lsIR9</a></p>&#x2014; Pat&apos;s Morse Wall (@morsewall) <a href="https://twitter.com/morsewall/status/1427968811160985603?ref_src=twsrc%5Etfw">August 18, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script><!--kg-card-end: html--><p></p><p><em>Also, if you have built a random quote machine after reading this post, share it as comment to the tweet above on Twitter. Really excited to see what you create!</em></p><p><em>Happy coding!</em></p><hr><h3 id="where-to-find-me">Where to find me:</h3><p></p><p>Follow me on Twitter:</p><!--kg-card-begin: markdown--><p><a href="https://twitter.com/celue"><img src="https://i.ibb.co/pZ016N6/Follow-Pat-Eskinasy.png" alt="How to Build a Random Quote Machine &#x2013; Part 6 &#x2013; React: Using various front end stacks" style="width:100%"></a></p>
<!--kg-card-end: markdown--><p>You can always get my latest writings directly to your email address by <strong><a href="https://morsewall.com/signup/">subscribing to Morse Wall</a>.</strong></p><hr><h3 id="update">UPDATE</h3><p></p><p>Part 7 of this series has now been published. <a href="https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/">Go check it out!</a> I&#x2019;m still using React but the app calls an asynchronous endpoint to request the data in the seventh flavor.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Random Quote Machine – Part 5 – Redux Thunk: Using various front end stacks]]></title><description><![CDATA[11 ways - How to build a random quote machine. Calling asynchronous endpoints in a Redux app using Redux Thunk.]]></description><link>https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/</link><guid isPermaLink="false">6383dec385b265021049b941</guid><category><![CDATA[Redux Thunk]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Side Project]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Redux]]></category><category><![CDATA[JSON]]></category><dc:creator><![CDATA[Pat Eskinasy]]></dc:creator><pubDate>Wed, 11 Aug 2021 11:37:00 GMT</pubDate><media:content url="https://morsewall.com/content/images/2022/11/what_happens_in_Redux_store.png" medium="image"/><content:encoded><![CDATA[<h3 id="building-a-random-quote-machine-with-redux-thunk">Building a random quote machine with Redux Thunk</h3><img src="https://morsewall.com/content/images/2022/11/what_happens_in_Redux_store.png" alt="How to Build a Random Quote Machine &#x2013; Part 5 &#x2013; Redux Thunk: Using various front end stacks"><p></p><p>Here comes Part 5 of the <em>Making a random quote machine in a few different flavors</em> series.</p><p><em>You can read more about this project&#x2019;s background <a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">on the project&#x2019;s page</a>. Or start from the beginning with <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">part 1 of this series</a>.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><p>In <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#flavor-4-html-css-redux-quotes-array-in-js-module">flavor #4</a>, the different UI elements are updated using state management with Redux.</p><p>In this flavor, I continue updating the different UI elements with the current application state, but the app is calling an asynchronous endpoint as the data (quotes) is requested from an external resource (a JSON stored in a public content delivery network (CDN)).</p><p>These are the different flavors that are part of this series:</p><!--kg-card-begin: html--><ol>
    <li><a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-3-vanilla-javascript-and-rest-api-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes REST API</a></li>
    <li><strike>HTML + Vanilla JS + SAAS + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about SASS)</em></li>
    <li><strike>HTML + Vanilla JS + Bootstrap + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about Bootstrap)</em></li>
    <li><strike>HTML + CSS + JQuery + JSON with quotes</strike><em> (nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/">HTML + CSS + Redux + quotes array</a></li>
    <li><strike>HTML + CSS + Redux + JQuery + JSON with quotes</strike> <em>(nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li>HTML + CSS + Redux + Redux Thunk + JSON with quotes (this flavor)</li>
    <li><a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/"> HTML + CSS + React + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/">HTML + CSS + React + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-8-react-hooks-using-various-front-end-stacks/">HTML + CSS + React Hooks + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/">HTML + CSS + React Hooks + JSON with quotes</a> (members-only post)</li>
    <li><strike>HTML + CSS + React + React Redux + quotes array</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><strike>HTML + CSS + React + React Redux + Redux Thunk + JSON with quotes</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-11-react-hooks-react-redux-and-redux-thunk-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + Redux Thunk + JSON with quotes</a></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + Redux Thunk + JSON with quote</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
</ol>  <!--kg-card-end: html--><p>If you are new here, you may wonder why I am overcomplicating a really simple application that can be shipped in 3 lines of functional Vanilla JavaScript. And the reason is: Shipping a simple app in a simple environment with fewer moving parts = great way to practice a new way to solve a problem. This is the spirit behind the <em><em><a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">Making a random quote machine in a few different flavors</a></em></em> series. Enjoy!</p><hr><p><em>In Part 6 (to be posted next week), I will cover a sixth flavor and will be using a User Interface JavaScript library (React) to build the app&#x2019;s UI.</em></p><p><em>If you&#x2019;re curious about the next flavors and would like to make a writer very happy today, you should <strong><a href="https://morsewall.com/signup/">subscribe to Morse Wall</a>.</strong></em></p><hr><h3 id="flavor-5-html-css-redux-json-with-quotes">Flavor #5: HTML + CSS + Redux + JSON with quotes</h3><p></p><p>Like previously in <a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/#flavor-2-html-css-vanilla-js-json-with-quotes">flavor #2</a>, I&#x2019;m storing the quotes in a separate JSON file. This time I&#x2019;m storing it in <a href="https://www.jsdelivr.com/?ref=morsewall.com">jsDelivr</a>, a public CDN.</p><p>There is a limited number of quotes from the <a href="https://cdn.jsdelivr.net/gh/morsewall/jsondb@master/db.json">JSON</a> in the code snippet below (so I can illustrate the point), but many more quotes in the JSON in production.</p><pre><code class="language-json">{
  &quot;quotes&quot;: [
    {
      &quot;quoteText&quot;: &quot;\&quot;Many of you appear concerned that we are wasting valuable lesson time, but I assure you we will go back to school the moment you start listening to science and give us a future.\&quot;&quot;,
      &quot;quoteAuthor&quot;: &quot;@GretaThunberg&quot;
    },
    {
      &quot;quoteText&quot;: &quot;\&quot;I was fortunate to be born in a time and place where everyone told us to dream big. I could become whatever I wanted to. I could live wherever I wanted to. People like me had everything we needed and more. Things our grandparents could not even dream of. We had everything we could ever wish for and yet now we may have nothing. Now we probably don&#x2019;t even have a future any more.\&quot;&quot;,
      &quot;quoteAuthor&quot;: &quot;@GretaThunberg&quot;
    },
    {
      &quot;quoteText&quot;: &quot;\&quot;That future was sold so that a small number of people could make unimaginable amounts of money. It was stolen from us every time you said that the sky was the limit, and that you only live once. You lied to us. You gave us false hope. You told us that the future was something to look forward to.\&quot;&quot;,
      &quot;quoteAuthor&quot;: &quot;@GretaThunberg&quot;
    }
  ]
}</code></pre><p></p><h3 id="calling-asynchronous-endpoints-in-redux">Calling asynchronous endpoints in Redux</h3><p></p><p>Since I&#x2019;m hitting asynchronous endpoints I need to adjust my code to make sure things will happen in order. I need to make sure the code will only try to render the quote when I have the data available, i.e. after I&#x2019;ve finished fetching the data from the JSON file. This is of course necessary even when dealing with Vanilla JavaScript code like in <a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/#flavor-2-html-css-vanilla-js-json-with-quotes">flavor #2</a>. The additional challenge in this flavor (with Redux) is that, by default, actions in Redux are dispatched synchronously. To help with this, I am using the <a href="https://github.com/reduxjs/redux-thunk/?ref=morsewall.com">Redux Thunk</a> middleware. Redux Thunk is a middleman that sits in between an action being dispatched and the action reaching the reducer (for more on actions and reducers, check <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#flavor-4-html-css-redux-quotes-array-in-js-module">flavor #4</a>).</p><p>The concept of a <a href="https://en.wikipedia.org/wiki/Thunk/?ref=morsewall.com">thunk</a> comes from computer programming and more widely refers to using a function to delay the evaluation/running of an operation.</p><p>To create an asynchronous action, I return a function in an action creator that takes <code>dispatch</code> as an argument. Within this function, I can dispatch actions and perform asynchronous requests.</p><pre><code class="language-js">//handleAsync.js
import { requestingApiData } from &quot;../../redux/actions/actions.js&quot;;
import { receivedApiData } from &quot;../../redux/actions/actions.js&quot;;
import { store } from &quot;../index.js&quot;;

// defining a special action creator that returns a function. The returned function takes dispatch as an argument. Within this function, I can dispatch actions and perform asynchronous requests. It&apos;s common to dispatch an action before initiating any asynchronous behavior so that the application state knows that some data is being requested (this state could display a loading icon, for instance). Then, once the application receives the data, another action is dispatched, an action that carries the data as a payload along with information that the action is completed.
const handleAsync = () =&gt; {
  return function (dispatch) {
    // dispatch request action here
    store.dispatch(requestingApiData());
    const makeRequest = async () =&gt; {
      const responseJSON = await fetch(
        &quot;https://cdn.jsdelivr.net/gh/morsewall/jsondb@master/db.json&quot;
      );
      const responseObject = await responseJSON.json();
      const quotesArray = responseObject.quotes;
      // dispatch received data action here
      store.dispatch(receivedApiData(quotesArray));
    };
    makeRequest();
  };
};

export default handleAsync;</code></pre><p></p><p>In this case, the asynchronous request is <code>fetch()</code> (just like in <a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/#flavor-2-html-css-vanilla-js-json-with-quotes">flavor #2</a>). Above is the special action creator designed to handle the asynchronous behavior. This is a special action creator since it returns a function instead of an action object (<code>handleAsync</code> returns a function). The returned function takes <code>dispatch</code> as an argument. It is within this function that I can dispatch actions and perform asynchronous requests.</p><p>It&#x2019;s common to dispatch an action before initiating any asynchronous behavior so that the application knows that some data is being requested (this state could for instance display <code>&quot;Loading...&quot;</code> on the console). Then, once the application receives the data, another action is dispatched, this action carries the data as payload along with information that the action is completed.</p><p>The two dispatched action creators above (<code>requestingApiData</code> and <code>receivedApiData</code>) are defined in <code>actions.js</code>. They return actions containing information about action-events that have occurred. <code>RECEIVED_API_DATA</code> is tied to having received the data from a finalized <code>fetch()</code> and gives the <code>apiData</code> value a key named <code>payloadQuotes</code>.</p><pre><code class="language-js">//actions.js
import { REQUESTING_API_DATA } from &quot;../constants/constants.js&quot;;
import { RECEIVED_API_DATA } from &quot;../constants/constants.js&quot;;

// defining action creators related to the asynch function. Action creator is a function that returns an action (object that contains information about an action-event that has occurred). The action creator gets called by `dispatch()`
export const requestingApiData = () =&gt; {
  return {
    type: REQUESTING_API_DATA,
  };
};

export const receivedApiData = (apiData) =&gt; {
  return {
    type: RECEIVED_API_DATA,
    payloadQuotes: apiData,
  };
};</code></pre><p></p><p>I&#x2019;m defining those action types in <code>constants.js</code>.</p><pre><code class="language-js">//constants.js
// defining action types for the special asynch action creator-type function
export const REQUESTING_API_DATA = &quot;REQUESTING_API_DATA&quot;;
export const RECEIVED_API_DATA = &quot;RECEIVED_API_DATA&quot;;</code></pre><p></p><p>When the action creators are called it is time for the reducer to make sense of the <code>type</code> of action and inform the Redux store how to respond to the action (i.e. telling the store how to modify the state).</p><pre><code class="language-js">//reducers.js
import { REQUESTING_API_DATA } from &quot;../constants/constants.js&quot;;
import { RECEIVED_API_DATA } from &quot;../constants/constants.js&quot;;

// defining default state
const defaultState = {
  status: &quot;&quot;,
  quotesData: [],
};

//defining reducer functions to allow the Redux store to know how to respond to the action created
const getNextQuoteReducer = (state = defaultState, action) =&gt; {
  switch (action.type) {
    case REQUESTING_API_DATA:
      return {
        ...state,
        status: &quot;waiting&quot;,
        quotesData: [],
      };
    case RECEIVED_API_DATA:
      return {
        ...state,
        status: &quot;received&quot;,
        quotesData: action.payloadQuotes,
      };
    default:
      return state;
  }
};

export default getNextQuoteReducer;</code></pre><!--kg-card-begin: html--><div class="notice" style="position:relative;min-height: 1em;margin-top: 1.45rem;margin-bottom: 1.45rem;padding: 1em 1.5em 1.5em;border: 2px solid;-webkit-box-shadow: 0.25em 0.25em 0 #000;box-shadow: 0.25em 0.25em 0 #000;">
    <h3 id="disclaimer-react-hooks" style="display: block;margin-bottom: 1.25em;padding-bottom: 0.25em;border-bottom: 2px solid">Disclaimer: Use of switch...case in reducers</h3>
    <div>
        <p>
            switch...case statements are great to show how the internals work but aren&apos;t typically used in production. You can <a href="https://redux-toolkit.js.org/usage/usage-guide/?ref=morsewall.com/#writing-reducers">use any conditional logic you want</a> to write a reducer.
        </p>
        <p>
         (Update 2021: The intention with this series is to get very incremental progress from one stack to another. Making it all as much bare bones as possible in order to get concepts adequately explored and explained. For this reason, I&apos;ve covered the Redux core library (unopinionated - let&apos;s you decide how to handle everything) in the  flavors covered in this series. That said, <a href="https://redux.js.org/redux-toolkit/overview/?ref=morsewall.com">Redux Toolkit</a> is now intended to be the standard way to write Redux logic and the recommendation is for it to be used).
        </p>
    </div>
</div>    <!--kg-card-end: html--><p></p><h3 id="fetching-the-data">Fetching the data</h3><p></p><p>As per my <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user stories</a>: &#x201C;I want to be welcomed by a quote when I first load the app&#x201D;. So far, however, I haven&#x2019;t even fetched the quotes from the JSON yet. So, doing that now:</p><pre><code class="language-js">//index.js
&quot;use strict&quot;;

import handleAsync from &quot;./js-modules/handleAsync.js&quot;;

// The UMD build makes Redux available as a window.Redux global variable
const Redux = window.Redux;

//dispatching the asynch special action creator
store.dispatch(handleAsync());</code></pre><p></p><p>From the above, I&#x2019;m dispatching the <code>handleAsync</code> action creator, which will trigger an update of the state in the Redux store with the help of the reducer. When the app has finalized fetching, the Redux store will keep the full JSON contents stored in the state.</p><p></p><h3 id="adding-the-redux-thunk-library">Adding the Redux Thunk library</h3><p></p><p>I&#x2019;m soon calling the Redux Thunk middleware, so I better add it to the project. The Redux Thunk library is available from a <a href="https://github.com/reduxjs/redux-thunk?ref=morsewall.com#note-on-2x-update">precompiled UMD package</a>, so I can simply add it as <code>script</code> to my HTML. The snippet below shows the bottom of my HTML.</p><pre><code class="language-html">&lt;!-- index.html --&gt;
  &lt;/footer&gt;
	&lt;!-- adding the Redux library from a precompiled UMD package. window.Redux is the global variable to call Redux. --&gt;
	&lt;script src=&quot;https://unpkg.com/redux@4.0.4/dist/redux.js&quot;&gt;&lt;/script&gt;
	&lt;!-- adding the Redux Thunk library from a precompiled UMD package. window.ReduxThunk.default is the global variable to call Redux Thunk. --&gt;
	&lt;script src=&quot;https://unpkg.com/redux-thunk@2.3.0/dist/redux-thunk.min.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;module&quot; src=&quot;src/js/index.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html
</code></pre><p></p><p>With the library added, the UMD build makes Redux Thunk available as a <code>window.ReduxThunk.default</code> global variable. I&#x2019;m calling that global variable <code>ReduxThunk</code>, so I can simply call the library by <code>ReduxThunk</code> from now on.</p><pre><code class="language-JS">//index.js
// The UMD build makes Redux-Thunk available as a window.ReduxThunk.default global variable
const ReduxThunk = window.ReduxThunk.default;</code></pre><p></p><h3 id="creating-the-redux-store-when-using-the-redux-thunk-middleware">Creating the Redux store when using the Redux Thunk middleware</h3><p></p><p>I still need to create the Redux store. The <code>createStore()</code> method takes as arguments:</p><ul><li>The <code>getNextQuoteReducer</code> reducer function</li><li><code>Redux.applyMiddleware(ReduxThunk)</code></li><li><a href="https://github.com/zalmoxisus/redux-devtools-extension/?ref=morsewall.com">Redux DevTool&#x2019;s store enhancer</a> (Optional. For more on Redux DevTools extension, see <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#what-is-state">flavor #4</a>)</li></ul><pre><code class="language-js">//index.js
&quot;use strict&quot;;

import getNextQuoteReducer from &quot;../redux/reducers/reducers.js&quot;;
import handleAsync from &quot;./js-modules/handleAsync.js&quot;;

// The UMD build makes Redux available as a window.Redux global variable
const Redux = window.Redux;

// The UMD build makes Redux-Thunk available as a window.ReduxThunk.default global variable
const ReduxThunk = window.ReduxThunk.default;

//to add Chrome&apos;s Redux DevTool&apos;s extension https://github.com/zalmoxisus/redux-devtools-extension that allows me to go back in the state history. When the extension is not installed, I&apos;m using Redux&#x2019;s compose.
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || Redux.compose;

//creating the Redux store, including Redux Thunk middleware. This is where the state lives.
export const store = Redux.createStore(
  getNextQuoteReducer,
  composeEnhancers(Redux.applyMiddleware(ReduxThunk))
);

//dispatching the asynch special action creator
store.dispatch(handleAsync());</code></pre><p></p><p>With Redux Thunk middleware now added, action creators, receiving <a href="https://redux.js.org/api/store?ref=morsewall.com#dispatchaction"><code>dispatch</code></a> as an argument, can call <code>dispatch</code> asynchronously and take control by dispatching functions.</p><p></p><h3 id="designing-for-one-batch-endpoint-call-versus-multiple-endpoint-calls">Designing for one batch endpoint call versus multiple endpoint calls</h3><p></p><p>I now have the full JSON (of quotes) in the Redux Store. I however only need one (randomly selected) quote to render in the UI. I could design the app to do one endpoint call (<code>fetch()</code>) every time a new quote was needed, but that would mean using network resources every time a new quote was requested.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-4.cloudinary.com/hnhggca76/image/upload/q_auto/v1/ghost-blog-images/asynch_design.png" class="kg-image" alt="How to Build a Random Quote Machine &#x2013; Part 5 &#x2013; Redux Thunk: Using various front end stacks" loading="lazy" width="1784" height="960"><figcaption>Asynchronous design of endpoint calls</figcaption></figure><h3 id="deciding-whether-to-duplicate-data-in-the-redux-store"><br>Deciding whether to duplicate data in the Redux store</h3><p></p><p>As the Redux store has the full JSON of quotes, I could use the store as a database and use Redux selectors (a selector is a function that accepts Redux state as an argument and returns data that is derived from that state) to do <code>SELECT</code>-type queries called by UI listeners (e.g. through click events). For this application this would mean using a Redux selector to randomly pick a quote from the store.</p><p>I&#x2019;m duplicating data in the Redux store instead. In other words, I&#x2019;m making the Redux store hold the <strong>currently</strong> randomly selected quote in addition to the full JSON of quotes. And the reason for that decision is: I want to allow any store listener to <code>getState()</code> and consistently get the <strong>current</strong> quote that has been randomly selected.</p><p>So, the Redux store stores:</p><ul><li>The full JSON of quotes</li><li>The randomly chosen quote object</li></ul><p>Alternatively, I could store the index for the quote object in the Redux store. That would similarly allow me to <code>getState()</code> and arrive at the same quote object without fully duplicating the data.</p><h3 id="working-through-the-user-stories">Working through the user stories</h3><p></p><p>Once again, back to the <a href="http://localhost:4000/notes/random-quote-machine/#userstories">user stories</a>: &#x201C;I want to be welcomed by a quote when I first load the app&#x201D; and &#x201C;I want to be able to click a UI element (a button) to get a new quote&#x201D;.</p><p>Like in <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#action-events-events-triggering-actions">flavor #4</a>, I&#x2019;m naming the UI elements to make them more readable throughout the code:</p><pre><code class="language-js">//index.js
//defining UI elements
const newQuoteButton = document.getElementById(&quot;new-quote&quot;);
const quoteTextContent = document.getElementById(&quot;text&quot;);
const quoteAuthorContent = document.getElementById(&quot;author&quot;);
export const tweetButton = document.getElementById(&quot;tweet-quote&quot;);
</code></pre><p><br>I&#x2019;m now creating a store listener function which is called whenever an action is dispatched to the store. I then retrieve the state with the <code>getState()</code> method and render my UI elements with data from the state.</p><pre><code class="language-js">//index.js
//creating store listener function that is called whenever an action is dispatched to the store. The getState() method retrieves the current state held in the Redux store
store.subscribe(() =&gt; {
  const state = store.getState();
  if (state.status == &quot;waiting&quot;) {
    console.log(&quot;Loading&#x2026;&quot;);
  }
  if (state.status == &quot;received&quot;) {
    let quoteObject = getRandomElementSelector(state);
    //inject random quote on HTML
    quoteTextContent.innerHTML = quoteObject.quoteText;
    //inject author on HTML
    quoteAuthorContent.innerHTML = &quot;- &quot; + quoteObject.quoteAuthor;
    //calling the JS module that generates a Twitter url for Twitter intent
    getTwitterUrl(quoteObject);
  }
});</code></pre><p><br>The <code>getRandomElementSelector</code> above is a Redux selector. I&#x2019;ve implemented it to take <code>stateObject</code> (state as per above snippet when the selector is called) as argument and return a randomly selected quote object.</p><pre><code class="language-js">//selectors.js
//defining a Redux selector,  i.e. it will be used to take Redux state as an argument and return some data from it
const getRandomElementSelector = (stateObject) =&gt; {
  let array = stateObject.quotesData;
  //access random quote from array
  return array[Math.floor(Math.random() * array.length)];
};

export default getRandomElementSelector;</code></pre><p></p><p>The <code>getTwitterUrl</code> called inside the store listener further above, handles truncating the quote text to the adequate tweetable number of characters, generates the url for the Tweet Quote button and sets the url on the HTML. Below code is as per <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#subscribing-to-the-redux-store">flavor #4</a>.</p><pre><code class="language-js">//getTwitterUrl.js
import { tweetButton } from &quot;../index.js&quot;;

//defining function that generates a Twitter URL (for Twitter intent) and inject url on HTML, making it a JS function/module
const getTwitterUrl = (quoteObject) =&gt; {
  //truncating quote text in case full tweet gets to be over 280 characters
  let quoteTextElem = quoteObject.quoteText;
  let quoteAuthorElem = &quot; - &quot; + quoteObject.quoteAuthor;
  let contentQuote = quoteTextElem + quoteAuthorElem;
  if (contentQuote.length &gt; 280) {
    let charCountAuthor = quoteAuthorElem.length;
    const extraStylingChar = &quot;...&quot; + &apos;&quot;&apos;;
    let extraCharCount = extraStylingChar.length;
    let subString =
      quoteTextElem.substring(0, 280 - extraCharCount - charCountAuthor) +
      extraStylingChar +
      quoteAuthorElem;
    //generate url available for Twitter intent and inject url on HTML
    tweetButton.href = &quot;https://twitter.com/intent/tweet?text=&quot; + subString;
  } else {
    //generate url available for Twitter intent and inject url on HTML
    tweetButton.href = &quot;https://twitter.com/intent/tweet?text=&quot; + contentQuote;
  }
};

export default getTwitterUrl;</code></pre><p></p><p>With the code so far I&#x2019;m shipping the <em>&#x201C;I want to be welcomed by a quote when I first load the app&#x201D;</em> user story, but <em>&#x201C;I want to be able to click a UI element (a button) to get a new quote&#x201D;</em> has not been implemented yet.</p><p>I&#x2019;m starting with the UI listener function tied to the <code>newQuoteButton</code>. This function will be dispatching actions via the <code>newQuoteActionCreator</code> action creator to the Redux store when a click event happens. I&#x2019;m implementing this new action creator to trigger the storing of the randomly chosen quote object in the Redux store as <a href="#deciding-whether-to-duplicate-data-in-the-redux-store">mentioned above</a>.</p><pre><code class="language-js">//index.js
//creating UI listeners. Dispatching actions (via the action creators that return a &quot;type&quot; to the reducer) to the redux store. When a new state is set in the Redux store, the store listeners will be retrieving the current state held in the Redux store
newQuoteButton.addEventListener(&quot;click&quot;, () =&gt; {
  store.dispatch(newQuoteActionCreator());
});</code></pre><p></p><h3 id="a-new-action-creator">A new action creator</h3><p></p><p>So, when <code>newQuoteActionCreator</code> is called, it returns an action (which has an informative <code>type</code>). Inside the returned action/object, I&#x2019;m naming <code>payloadQuote</code> the key that will be associated with the object that will store the selected random quote. The selected random quote, like previously, is chosen by <code>getRandomElementSelector</code>, the selector function.<br></p><p>This is <code>actions.js</code> in full, including <code>newQuoteActionCreator</code>:</p><pre><code class="language-js">//actions.js
import { NEW_QUOTE } from &quot;../constants/constants.js&quot;;
import { REQUESTING_API_DATA } from &quot;../constants/constants.js&quot;;
import { RECEIVED_API_DATA } from &quot;../constants/constants.js&quot;;
import getRandomElementSelector from &quot;../selectors/selectors.js&quot;;
import { store } from &quot;../../js/index.js&quot;;

// defining action creators related to the asynch function. Action creator is a function that returns an action (object that contains information about an action-event that has occurred). The action creator gets called by `dispatch()`
export const requestingApiData = () =&gt; {
  return {
    type: REQUESTING_API_DATA,
  };
};

export const receivedApiData = (apiData) =&gt; {
  return {
    type: RECEIVED_API_DATA,
    payloadQuotes: apiData,
  };
};

//defining action creator related to the &quot;Get New Quote&quot; button. a function that returns an action (object that contains information about an action-event that has occurred). The action creator gets called by `dispatch()`
export const newQuoteActionCreator = () =&gt; {
  const state = store.getState();
  let quoteObject = getRandomElementSelector(state);
  return {
    type: NEW_QUOTE,
    payloadQuote: quoteObject,
  };
};</code></pre><p></p><p>The reducer then makes sense of the <code>type</code> and informs the Redux store how to respond to the action. In other words, the reducer tells the Redux store how to modify the state.</p><p><code>reducers.js</code> now in full, including the <code>NEW_QUOTE</code> case:</p><pre><code class="language-js">//reducers.js
import { NEW_QUOTE } from &quot;../constants/constants.js&quot;;
import { REQUESTING_API_DATA } from &quot;../constants/constants.js&quot;;
import { RECEIVED_API_DATA } from &quot;../constants/constants.js&quot;;

// defining default state
const defaultState = {
  status: &quot;&quot;,
  quotesData: [],
};

//defining reducer functions to allow the Redux store to know how to respond to the action created
const getNextQuoteReducer = (state = defaultState, action) =&gt; {
  switch (action.type) {
    case REQUESTING_API_DATA:
      return {
        ...state,
        status: &quot;waiting&quot;,
        quotesData: [],
      };
    case RECEIVED_API_DATA:
      return {
        ...state,
        status: &quot;received&quot;,
        quotesData: action.payloadQuotes,
      };
    case NEW_QUOTE:
      return {
        ...state,
        status: &quot;new quote&quot;,
        data: action.payloadQuote,
      };
    default:
      return state;
  }
};

export default getNextQuoteReducer;</code></pre><p></p><p>The new state object has a new property: <code>data</code> and this property has value equal to the object associated with <code>payloadQuote</code> (see <a href="http://localhost:4000/notes/random-quote-machine-part5/#actioncreator"><code>newQuoteActionCreator</code></a>).</p><p>I now need to adjust the store listener to render a new quote whenever a new randomly selected quote is added to the store. Here I&#x2019;m adding an <code>if</code> statement to handle any changes to store when <code>state.status</code> is equal to <code>new quote</code>.</p><pre><code class="language-js">//creating store listener function that is called whenever an action is dispatched to the store. The getState() method retrieves the current state held in the Redux store
store.subscribe(() =&gt; {
  const state = store.getState();
  if (state.status == &quot;waiting&quot;) {
    console.log(&quot;Loading&#x2026;&quot;);
  }
  if (state.status == &quot;received&quot;) {
    let quoteObject = getRandomElementSelector(state);
    //inject random quote on HTML
    quoteTextContent.innerHTML = quoteObject.quoteText;
    //inject author on HTML
    quoteAuthorContent.innerHTML = &quot;- &quot; + quoteObject.quoteAuthor;
    //calling the JS module that generates a Twitter url for Twitter intent
    getTwitterUrl(quoteObject);
  }
  if (state.status == &quot;new quote&quot;) {
    //inject random quote on HTML
    quoteTextContent.innerHTML = state.data.quoteText;
    //inject author on HTML
    quoteAuthorContent.innerHTML = &quot;- &quot; + state.data.quoteAuthor;
    //calling the JS module that generates a Twitter url for Twitter intent
    getTwitterUrl(state.data);
  }
});</code></pre><p></p><p>So now the random quote machine ships all the required user stories!</p><h3 id="action-what-happens-in-the-redux-store">Action! What happens in the Redux store</h3><p></p><p>As I use <a href="https://github.com/zalmoxisus/redux-devtools-extension/?ref=morsewall.com">Redux DevTools Extension</a> to time travel in the application&#x2019;s state, I can check the state of the Redux store at every point in time. So, below is the state prior to finalizing the <code>fetch()</code> (i.e. <code>status: &quot;waiting&quot;</code> from <code>reducers.js</code>), the state when the store has the full JSON (i.e. <code>status: &quot;received&quot;</code>) and the state when it additionally stores a new object called <code>data</code> that holds the <strong>current</strong> randomly selected quote (i.e. after the &#x201C;Get New Quote&#x201D; button is clicked).</p><!--kg-card-begin: markdown--><p><img src="https://i.ibb.co/ZcNYHTm/gif-redux-store-asynch.gif" alt="How to Build a Random Quote Machine &#x2013; Part 5 &#x2013; Redux Thunk: Using various front end stacks" loading="lazy"></p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-2.cloudinary.com/hnhggca76/image/upload/q_auto/v1/ghost-blog-images/what_happens_in_Redux_store.png" class="kg-image" alt="How to Build a Random Quote Machine &#x2013; Part 5 &#x2013; Redux Thunk: Using various front end stacks" loading="lazy" width="4652" height="2936"><figcaption>What happens in the Redux store</figcaption></figure><h3 id="redux-redux-thunk-application-structure">Redux + Redux Thunk application structure</h3><p></p><p>Like I did in <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#redux-application-structure">flavor #4</a>, as I&#x2019;ve been jumping across a few JS modules in the write-up above, it can be helpful to zoom out and give a high-level view of the application&#x2019;s file structure. Since this is a very simple app, I&#x2019;m distributing actions, constants, selectors and reducers in different folders as opposed to following a more modular approach (bringing them together under a single folder related to every specific feature. Not following this approach since there aren&#x2019;t many &#x201C;features&#x201D; in this application):</p><pre><code>.
&#x251C;&#x2500;&#x2500; index.html
&#x2514;&#x2500;&#x2500; src
    &#x251C;&#x2500;&#x2500; js
    &#x2502;   &#x251C;&#x2500;&#x2500; index.js
    &#x2502;   &#x2514;&#x2500;&#x2500; js-modules
    &#x2502;       &#x251C;&#x2500;&#x2500; getTwitterUrl.js
    &#x2502;       &#x2514;&#x2500;&#x2500; handleAsync.js
    &#x251C;&#x2500;&#x2500; redux
    &#x2502;   &#x251C;&#x2500;&#x2500; actions
    &#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500; actions.js
    &#x2502;   &#x251C;&#x2500;&#x2500; constants
    &#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500; constants.js
    &#x2502;   &#x251C;&#x2500;&#x2500; reducers
    &#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500; reducers.js
    &#x2502;   &#x2514;&#x2500;&#x2500; selectors
    &#x2502;       &#x2514;&#x2500;&#x2500; selectors.js
    &#x2514;&#x2500;&#x2500; stylesheets
        &#x2514;&#x2500;&#x2500; style.css</code></pre><h3 id="a-visual-look-into-the-application%E2%80%99s-execution-flow"><br>A visual look into the application&#x2019;s execution flow</h3><p></p><p>Despite this flavor using a middleware and working with asynchronicity, the code execution flow is not that much different to <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/#a-visual-look-into-the-application%E2%80%99s-execution-flow">flavor #4</a>. I&#x2019;m changing the state in the Redux store with random quotes that get selected as the application runs (additionally, in this flavor, I&#x2019;m also storing the contents of a full JSON file in the Redux store).</p><p>Yes, Redux updates the store with help from an action creator and a reducer (and in this flavor a third-party extension point (Redux Thunk middleware) is between dispatching an action and handing the action off to the reducer), but on high-level, this is how data flows in the application: Different UI elements, such as the <em>Get New Quote</em> button, trigger state changes in the Redux store (with a new random quote) and a store listener function next updates the UI with the new state.</p><p>And in a diagram:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-2.cloudinary.com/hnhggca76/image/upload/q_auto/v1/ghost-blog-images/redux_thunk_execution_flow.png" class="kg-image" alt="How to Build a Random Quote Machine &#x2013; Part 5 &#x2013; Redux Thunk: Using various front end stacks" loading="lazy" width="2120" height="1936"><figcaption>Redux Thunk Execution Flow</figcaption></figure><p>You can <a href="https://morsewall.github.io/random-quote-redux-json/">check the project live</a>. Source code for <a href="https://github.com/morsewall/random-quote-redux-json">flavor #5 in Github</a>.</p><!--kg-card-begin: html--><div class="button-set">
    <button style="border-radius:8px;background-color:#000000;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://morsewall.github.io/random-quote-redux-json/" style="margin:1rem;" class="button-in-post">Live Project</a></button>
    <button style="border-radius:8px;background-color:#000000;color:#ffffff;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://github.com/morsewall/random-quote-redux-json" style="margin:1rem;" class="button-in-post">Source code</a></button>
</div><!--kg-card-end: html--><hr><h3 id="acknowledgement">Acknowledgement</h3><p></p><p>The following goes without saying, but here it comes anyways: Please note that in this ever changing world of technology, I am writing this article in July 2019 (hello, summer!) and alternate solutions might have become available as you read this writing.</p><hr><p><em>In Part 6 (to be posted next week), I will cover a sixth flavor and will be using a User Interface JavaScript library (React) to build the app&#x2019;s UI.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><hr><p><em>So, what did you like about this post? <a href="https://twitter.com/celue">Come say hello on Twitter!</a></em></p><!--kg-card-begin: html--><blockquote class="twitter-tweet"><p lang="en" dir="ltr">What happens in the Redux store? Here comes Part 5 of the Making a random quote machine in a few different flavors series. Doing this tiny project with 11 different front-end stacks. This week using Redux Thunk. <a href="https://t.co/BAr6co5f4u">pic.twitter.com/BAr6co5f4u</a></p>&#x2014; Morse Wall (@morsewall) <a href="https://twitter.com/morsewall/status/1425430563679244291?ref_src=twsrc%5Etfw">August 11, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script><!--kg-card-end: html--><p></p><p><em>Also, if you have built a random quote machine after reading this post, share it as comment to the tweet above on Twitter. Really excited to see what you create!</em></p><p><em>Happy coding!</em></p><hr><h3 id="where-to-find-me">Where to find me:</h3><p></p><p>Follow me on Twitter:</p><!--kg-card-begin: markdown--><p><a href="https://twitter.com/celue"><img src="https://i.ibb.co/pZ016N6/Follow-Pat-Eskinasy.png" alt="How to Build a Random Quote Machine &#x2013; Part 5 &#x2013; Redux Thunk: Using various front end stacks" style="width:100%"></a></p>
<!--kg-card-end: markdown--><p>You can always get my latest writings directly to your email address by <a href="https://morsewall.com/signup/"><strong>subscribing to Morse Wall</strong></a><strong>.</strong></p><hr><h3 id="update">UPDATE</h3><p></p><p>Part 6 of this series has now been published. <a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/">Go check it out!</a> I&apos;m using a User Interface Javascript library (React) to build the app&#x2019;s UI in the sixth flavor.</p><p></p>]]></content:encoded></item><item><title><![CDATA[How to Build a Random Quote Machine – Part 4 – Redux: Using various front end stacks]]></title><description><![CDATA[11 ways - How to build a random quote machine. Adding state management with Redux.
]]></description><link>https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/</link><guid isPermaLink="false">6383dccd85b265021049b8ca</guid><category><![CDATA[Redux]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Side Project]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Pat Eskinasy]]></dc:creator><pubDate>Wed, 04 Aug 2021 00:00:00 GMT</pubDate><media:content url="https://morsewall.com/content/images/2022/11/tracking_redux_store_state_changes.png" medium="image"/><content:encoded><![CDATA[<h3 id="building-a-random-quote-machine-with-redux">Building a random quote machine with Redux</h3><img src="https://morsewall.com/content/images/2022/11/tracking_redux_store_state_changes.png" alt="How to Build a Random Quote Machine &#x2013; Part 4 &#x2013; Redux: Using various front end stacks"><p></p><p>This is Part 4 of the <em>Making a random quote machine in a few different flavors</em> series.</p><p><em>You can read more about this project&#x2019;s background <a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">on the project&#x2019;s page</a>. Or start from the beginning with <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">part 1 of this series</a>.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><p>In <a href="https://morsewall.com/random-quote-part-3-vanilla-javascript-and-rest-api-using-various-front-end-stacks/#flavor-3-html-css-vanilla-js-quotes-rest-api">flavor #3</a>, the data (quotes) is requested from a REST API.</p><p>In this flavor, I have the data inside an array stored inside a JavaScript module part of the project and I&#x2019;m using state management (with Redux) to help me update the different UI elements with the current application state.</p><p>These are the different flavors that are part of this series:</p><!--kg-card-begin: html--><ol>
    <li><a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-3-vanilla-javascript-and-rest-api-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes REST API</a></li>
    <li><strike>HTML + Vanilla JS + SAAS + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about SASS)</em></li>
    <li><strike>HTML + Vanilla JS + Bootstrap + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about Bootstrap)</em></li>
    <li><strike>HTML + CSS + JQuery + JSON with quotes</strike><em> (nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li>HTML + CSS + Redux + quotes array (this flavor)</li>
    <li><strike>HTML + CSS + Redux + JQuery + JSON with quotes</strike> <em>(nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/">HTML + CSS + Redux + Redux Thunk + JSON with quotes</a></li>
    <li><a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/"> HTML + CSS + React + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/">HTML + CSS + React + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-8-react-hooks-using-various-front-end-stacks/">HTML + CSS + React Hooks + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/">HTML + CSS + React Hooks + JSON with quotes</a> (members-only post)</li>
    <li><strike>HTML + CSS + React + React Redux + quotes array</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><strike>HTML + CSS + React + React Redux + Redux Thunk + JSON with quotes</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-11-react-hooks-react-redux-and-redux-thunk-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + Redux Thunk + JSON with quotes</a></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + Redux Thunk + JSON with quote</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
</ol>  <!--kg-card-end: html--><hr><p><em>In Part 5 (to be posted next week), I will cover a fifth flavor and will using Redux Thunk to call an asynchronous endpoint as the data (quotes) is requested from an external resource.</em></p><p><em>If you&#x2019;re curious about the next flavors and would like to make a writer very happy today, you should <strong><a href="https://morsewall.com/signup/">subscribe to Morse Wall</a>.</strong></em></p><hr><h3 id="state-management-why-overcomplicate">State management? Why overcomplicate?</h3><p></p><p>Why am I overcomplicating a really simple application that can be shipped in 3 lines of functional Vanilla JavaScript? Because:</p><blockquote>True that...</blockquote><blockquote>There are always (at least) two ways to solve a problem. One is faster, the other you just don&#x2019;t know yet.</blockquote><p>The above is the spirit behind the <em><a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">Making a random quote machine in a few different flavors</a></em> series. And with that in mind, there is no better way to practice a new way to solve a problem than to ship a simple app in a simpler environment with fewer moving parts. Enjoy!</p><p></p><h3 id="what-is-state">What is <code>state</code> ?</h3><p></p><p>State is the &#x201C;situation&#x201D; the application is currently in. To exemplify, a few of the many states a given application can be in, at any moment, are for instance:</p><ul><li>loaded;</li><li>not loaded;</li><li>logged-in;</li><li>not logged-in;</li><li>hamburger navigation menu open;</li><li>hamburger navigation menu closed;</li><li>etc.</li></ul><p>For this random quote machine application, the state stores a piece of data, a random quote that gets selected when the application runs. This state (random quote) is then listened to and different UI elements are updated with it.</p><p>The GIF below shows the state changing following a certain action-event in the application.</p><!--kg-card-begin: markdown--><p><img src="https://i.ibb.co/kDnXS2b/track-state-chages-redux.gif" alt="How to Build a Random Quote Machine &#x2013; Part 4 &#x2013; Redux: Using various front end stacks" loading="lazy"></p>
<!--kg-card-end: markdown--><p>As a note, to track state (as per gif above), I use <a href="https://github.com/zalmoxisus/redux-devtools-extension/?ref=morsewall.com">Redux DevTools Extension</a> to time travel in the application&#x2019;s state. The extension records dispatched actions (more on dispatched actions below in the article) and the state of the Redux store (more on the store further down) at every point in time. This allows me to inspect the state and travel back in time to a previous application state without reloading the page.<br></p><h3 id="flavor-4-html-css-redux-quotes-array-in-js-module">Flavor #4: HTML + CSS + Redux + quotes array in JS module</h3><p></p><p>First things first, the data is stored in a JavaScript module. Because good software developers divide their code into modules, right? In other words, unlike previous flavors in this series (all JS code was previously inside a single file), there are a number of JavaScript files in this flavor.</p><p>Like previously, there is a tiny number of quotes in the code snippet below (so I can illustrate the point), but many more quotes in the array in production.</p><p>The <code>getRandomQuote</code> function spits out a random quote from the quotes array. I then export <code>getRandomQuote</code> so I can use it in another JS module.</p><pre><code class="language-js">//getRandomQuote.js
//defining function that accesses random quote from quotes array, making it a JS function/module
const getRandomQuote = () =&gt; {
  //defining an array for the quotes, wrapping it inside a JS function/module
  const quotes = [
    {
      quoteText:
        &apos;&quot;Many of you appear concerned that we are wasting valuable lesson time, but I assure you we will go back to school the moment you start listening to science and give us a future.&quot;&apos;,
      quoteAuthor: &quot;@GretaThunberg&quot;,
    },
    {
      quoteText:
        &apos;&quot;I was fortunate to be born in a time and place where everyone told us to dream big. I could become whatever I wanted to. I could live wherever I wanted to. People like me had everything we needed and more. Things our grandparents could not even dream of. We had everything we could ever wish for and yet now we may have nothing. Now we probably don&#x2019;t even have a future any more.&quot;&apos;,
      quoteAuthor: &quot;@GretaThunberg&quot;,
    },
  ];
  //access random quote from quote array
  return quotes[Math.floor(Math.random() * quotes.length)];
};

export default getRandomQuote;</code></pre><p></p><h3 id="adding-the-redux-library">Adding the Redux library</h3><p><br>The Redux library is available from a <a href="https://redux.js.org/introduction/installation?ref=morsewall.com">precompiled UMD package</a>, so I can simply add it as <code>script</code> to my HTML. The snippet below shows the bottom of my HTML.</p><!--kg-card-begin: html--><p id="module">
    Note also the <code>type=&quot;module&quot;</code> used when linking <code>index.js</code>. Given I&#x2019;m creating <code>index.js</code> as a JavaScript module, this is necessary to inform the browser to deal with it appropriately.
</p>    <!--kg-card-end: html--><pre><code class="language-js">&lt;!-- index.html --&gt;
	&lt;/footer&gt;
	&lt;!-- adding the Redux library from a precompiled UMD package. window.Redux is the global variable to call Redux. --&gt;
	&lt;script src=&quot;https://unpkg.com/redux@4.0.4/dist/redux.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;module&quot; src=&quot;src/js/index.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><p></p><p>With the library added, the UMD build makes Redux available as a <code>window.Redux</code> global variable. I&#x2019;m calling that global variable <code>Redux</code>, so I can simply call the library by <code>Redux</code> from now on.<br></p><pre><code class="language-js">//index.js
// The UMD build makes Redux available as a window.Redux global variable
const Redux = window.Redux;</code></pre><h3 id="action-events-events-triggering-actions"><br>Action-events: events triggering actions</h3><p><br>Back to the <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user stories</a>, I want to be able to click a UI element (a button) to get a new quote. So, to make things more readable as I refer to UI elements throughout the code, I&#x2019;m naming them appropriately.</p><pre><code class="language-js">//index.js
//defining UI elements
const newQuoteButton = document.getElementById(&quot;new-quote&quot;);
const quoteTextContent = document.getElementById(&quot;text&quot;);
const quoteAuthorContent = document.getElementById(&quot;author&quot;);
const tweetButton = document.getElementById(&quot;tweet-quote&quot;);</code></pre><p><br>I&#x2019;m creating a UI listener function tied to the <code>newQuoteButton</code>. This function will be <a href="https://redux.js.org/glossary?ref=morsewall.com#action-creator">dispatching actions</a> via the <code>newQuoteActionCreator</code> action creator (more on action creators further down) to the Redux store (the Redux store is where the state lives) when a <code>click</code> event happens.</p><pre><code class="language-js">//index.js
//creating UI listeners. Dispatching actions (via the action creators that return a &quot;type&quot; to the reducer) to the redux store. When a new state is set in the Redux store, the store listeners will be retrieving the current state held in the Redux store
newQuoteButton.addEventListener(&quot;click&quot;, () =&gt; {
  store.dispatch(newQuoteActionCreator());
});</code></pre><p></p><p>These <a href="https://redux.js.org/basics/actions?ref=morsewall.com#actions">actions</a>, created by <a href="https://redux.js.org/glossary?ref=morsewall.com#action-creator">action creators</a>, are simply objects that contain information about an action event that has occurred. The actions carry a <code>type</code> property, this property specifies the type of action that occurred.</p><p>It is common practice to write action types as <code>const</code> declarations.</p><pre><code class="language-js">//constants.js
//defining action types
export const NEW_QUOTE = &quot;NEW_QUOTE&quot;;</code></pre><p></p><p>Given I&#x2019;m declaring those constants in a separate <code>constants.js</code> module, I&#x2019;m importing the <code>const</code> into the action creator <code>actions.js</code> module.</p><p>I&#x2019;m also importing <code>getRandomQuote</code> in <code>actions.js</code> since I&#x2019;m using it in the module.</p><!--kg-card-begin: html--><span id="actioncreator">
</span><!--kg-card-end: html--><p>The action creator here (<code>newQuoteActionCreator</code>) is a function that returns an action. It creates an object. Inside the returned action/object, I&#x2019;m naming <code>payload</code> the key that will be associated with the object that will store the selected random quote.</p><pre><code class="language-js">//actions.js
import { NEW_QUOTE } from &quot;../constants/constants.js&quot;;
import getRandomQuote from &quot;../../js/js-modules/getRandomQuote.js&quot;;

//defining action creator. a function that returns an action (object that contains information about an action-event that has occurred). The action creator gets called by `dispatch()`
const newQuoteActionCreator = () =&gt; {
  let quoteObject = getRandomQuote();
  return {
    type: NEW_QUOTE,
    payload: quoteObject,
  };
};

export default newQuoteActionCreator;</code></pre><p></p><p>So, when <code>newQuoteActionCreator</code> is called, it returns an action (which has an informative <code>type</code>). Another function, called <a href="https://redux.js.org/basics/reducers?ref=morsewall.com#reducers">reducer</a>, makes sense of the <code>type</code> and informs the <a href="https://redux.js.org/basics/store?ref=morsewall.com#store">Redux store</a>) how to respond to the action. In other words, the reducer tells the Redux store how to modify the state.</p><p>The reducer takes <code>state</code> and <code>action</code> as arguments and returns a new state.</p><pre><code class="language-js">//reducers.js
import { NEW_QUOTE } from &quot;../constants/constants.js&quot;;
import getRandomQuote from &quot;../../js/js-modules/getRandomQuote.js&quot;;

//defining initial state
const defaultQuote = getRandomQuote();

//defining reducer function to allow the Redux store to know how to respond to the action created
const getNextQuoteReducer = (state = defaultQuote, action) =&gt; {
  switch (action.type) {
    case NEW_QUOTE:
      return {
        ...state,
        data: action.payload,
      };
    default:
      return state;
  }
};

export default getNextQuoteReducer;</code></pre><p></p><!--kg-card-begin: html--><div class="notice" style="position:relative;min-height: 1em;margin-top: 1.45rem;margin-bottom: 1.45rem;padding: 1em 1.5em 1.5em;border: 2px solid;-webkit-box-shadow: 0.25em 0.25em 0 #000;box-shadow: 0.25em 0.25em 0 #000;">
    <h3 id="disclaimer-react-hooks" style="display: block;margin-bottom: 1.25em;padding-bottom: 0.25em;border-bottom: 2px solid">Disclaimer: Use of switch...case in reducers</h3>
    <div>
        <p>
            switch...case statements are great to show how the internals work but aren&apos;t typically used in production. You can <a href="https://redux-toolkit.js.org/usage/usage-guide/?ref=morsewall.com/#writing-reducers">use any conditional logic you want</a> to write a reducer.
        </p>
        <p>
         (Update 2021: The intention with this series is to get very incremental progress from one stack to another. Making it all as much bare bones as possible in order to get concepts adequately explored and explained. For this reason, I&apos;ve covered the Redux core library (unopinionated - let&apos;s you decide how to handle everything) in the flavors covered in this series. That said, <a href="https://redux.js.org/redux-toolkit/overview/?ref=morsewall.com">Redux Toolkit</a> is now intended to be the standard way to write Redux logic and the recommendation is for it to be used).
        </p>
    </div>
</div>    <!--kg-card-end: html--><p><br>As state is <a href="https://redux.js.org/faq/immutable-data?ref=morsewall.com">immutable</a> and should never be directly modified, I&#x2019;m using the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals?ref=morsewall.com">object spread operator</a> to return a new copy of the state.</p><p>The new state object has a new property: <code>data</code> and this property has value equal to the object associated with <code>payload</code> (see <code><a href="#actioncreator">newQuoteActionCreator</a></code>).</p><p>I still need to create the Redux store. The <a href="https://redux.js.org/api/createstore?ref=morsewall.com">createStore() method</a>) takes the <code>getNextQuoteReducer</code> reducer function as an argument.</p><pre><code class="language-js">//index.js
//creating the Redux store. This is where the state lives.
const store = Redux.createStore(getNextQuoteReducer);</code></pre><p></p><h3 id="redux-application-structure">Redux application structure</h3><p><br>As I&#x2019;ve been jumping across a few JS modules in the write-up above, it can be helpful to zoom out and give a high-level view of the application&#x2019;s file structure. Since this is a very simple app, I&#x2019;m distributing actions, constants and reducers in different folders as opposed to following a more modular approach (bringing them together under a single folder related to every specific feature. Not following this approach since there aren&#x2019;t many &#x201C;features&#x201D; in this application):</p><pre><code>.
&#x251C;&#x2500;&#x2500; index.html
&#x2514;&#x2500;&#x2500; src
    &#x251C;&#x2500;&#x2500; js
    &#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; index.js
    &#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; js-modules
    &#x2502;&#xA0;&#xA0;   &#xA0; &#x251C;&#x2500;&#x2500; getRandomQuote.js
    &#x2502;&#xA0;&#xA0;   &#xA0; &#x2514;&#x2500;&#x2500; getTwitterUrl.js
    &#x251C;&#x2500;&#x2500; redux
    &#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; actions
    &#x2502;&#xA0;&#xA0; &#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; actions.js
    &#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; constants
    &#x2502;&#xA0;&#xA0; &#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; constants.js
    &#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; reducers
    &#x2502;&#xA0;&#xA0;     &#x2514;&#x2500;&#x2500; reducers.js
    &#x2514;&#x2500;&#x2500; stylesheets
        &#x2514;&#x2500;&#x2500; style.css</code></pre><p></p><h3 id="subscribing-to-the-redux-store">Subscribing to the Redux store</h3><p><br>As the application runs, actions are dispatched to the store and the state changes. The <a href="https://redux.js.org/api/store?ref=morsewall.com#subscribelistener"><code>store.subscribe()</code></a> method allows me to create a store listener function which is called whenever an action is dispatched to the store. I then retrieve the new state with the <a href="https://redux.js.org/api/store?ref=morsewall.com#getstate"><code>getState()</code></a> method and re-render my UI elements with data from the new state.</p><pre><code class="language-js">//index.js
//creating store listener function that is called whenever an action is dispatched to the store. The getState() method retrieves the current state held in the Redux store
store.subscribe(() =&gt; {
  //access the state of the app
  const state = store.getState();
  //inject random quote on HTML
  quoteTextContent.innerHTML = state.data.quoteText;
  //inject author on HTML
  quoteAuthorContent.innerHTML = &quot;- &quot; + state.data.quoteAuthor;
  //calling the JS module that generates a Twitter url for Twitter intent
  getTwitterUrl(state.data);
});
</code></pre><p></p><p>The <code>getTwitterUrl</code> function called by the <code>subscribe()</code> method handles truncating the quote text to the adequate tweetable number of characters; generates the url for the <em>Tweet Quote</em> button and sets the url on the HTML. The code here follows the logic implemented in <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#making-the-machine-tweet">part 1 of this series</a>.<br></p><pre><code class="language-js">//getTwitterUrl.js
import tweetButton from &quot;../index.js&quot;;

//defining function that generates a Twitter URL (for Twitter intent) and inject url on HTML, making it a JS function/module
const getTwitterUrl = (quoteObject) =&gt; {
  //truncating quote text in case full tweet gets to be over 280 characters
  let quoteTextElem = quoteObject.quoteText;
  let quoteAuthorElem = &quot; - &quot; + quoteObject.quoteAuthor;
  let contentQuote = quoteTextElem + quoteAuthorElem;
  if (contentQuote.length &gt; 280) {
    let charCountAuthor = quoteAuthorElem.length;
    const extraStylingChar = &quot;...&quot; + &apos;&quot;&apos;;
    let extraCharCount = extraStylingChar.length;
    let subString =
      quoteTextElem.substring(0, 280 - extraCharCount - charCountAuthor) +
      extraStylingChar +
      quoteAuthorElem;
    //generate url available for Twitter intent and inject url on HTML
    tweetButton.href = &quot;https://twitter.com/intent/tweet?text=&quot; + subString;
  } else {
    //generate url available for Twitter intent and inject url on HTML
    tweetButton.href = &quot;https://twitter.com/intent/tweet?text=&quot; + contentQuote;
  }
};

export default getTwitterUrl;</code></pre><p></p><p>I still need to ship one missing <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#userstories">user story</a>: I want to be welcomed by a quote when I first load the app. Currently, I only get a quote if I click the <em>Get New Quote</em> button.</p><p>I&#x2019;m adding a new listener that will check for the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event/?ref=morsewall.com"><code>DOMContentLoaded</code></a> event that fires when the initial HTML document has been completely loaded and parsed.</p><pre><code class="language-js">//index.js
//getting initial state, a reset state as the DOM is loaded.
document.addEventListener(&quot;DOMContentLoaded&quot;, () =&gt; {
  //access the state of the app
  const state = store.getState();
  //inject random quote on HTML
  quoteTextContent.innerHTML = state.quoteText;
  //inject author on HTML
  quoteAuthorContent.innerHTML = &quot;- &quot; + state.quoteAuthor;
  //calling the JS module that generates a Twitter url for Twitter intent
  getTwitterUrl(state);
});</code></pre><p><br>So now the random quote machine ships all the required user stories!</p><h3 id="a-visual-look-into-the-application%E2%80%99s-execution-flow">A visual look into the application&#x2019;s execution flow</h3><p><br>In summary, I&#x2019;m changing the state in the Redux store with random quotes that get selected as the application runs. Yes, Redux updates the store with help from an action creator and a reducer, but on high-level, this is how data flows in the application: Different UI elements, such as the <em>Get New Quote</em> button, trigger state changes in the Redux store (with a new random quote) and a store listener function next updates the UI with the new state.</p><p>And in a diagram:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-2.cloudinary.com/hnhggca76/image/upload/q_auto/v1/ghost-blog-images/redux_execution_flow.png" class="kg-image" alt="How to Build a Random Quote Machine &#x2013; Part 4 &#x2013; Redux: Using various front end stacks" loading="lazy" width="1112" height="770"><figcaption>Redux Execution Flow</figcaption></figure><p><br>You can <a href="https://morsewall.github.io/random-quote-redux-array/">check the project live</a>. Source code for <a href="https://github.com/morsewall/random-quote-redux-array">flavor #4 in Github</a>.</p><!--kg-card-begin: html--><div class="button-set">
    <button style="border-radius:8px;background-color:#000000;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://morsewall.github.io/random-quote-redux-array/" style="margin:1rem;" class="button-in-post">Live Project</a></button>
    <button style="border-radius:8px;background-color:#000000;color:#ffffff;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://github.com/morsewall/random-quote-redux-array" style="margin:1rem;" class="button-in-post">Source code</a></button>
</div><!--kg-card-end: html--><p></p><hr><h3 id="acknowledgement">Acknowledgement</h3><p></p><p>The following goes without saying, but here it comes anyways: Please note that in this ever changing world of technology, I am writing this article in July 2019 (hello, summer!) and alternate solutions might have become available as you read this writing.</p><hr><p><em>In Part 5 (to be posted next week), I will cover a fifth flavor and will be using Redux Thunk to call an asynchronous endpoint as the data (quotes) is requested from an external resource.</em></p><p><em><em>If you&#x2019;re curious about the next flavors, you should <a href="https://morsewall.com/signup"><strong>subscribe to Morse Wall</strong></a>. I think you&#x2019;ll like it a lot!</em></em><br></p><hr><p><em>So, what did you like about this post? <a href="https://twitter.com/celue">Come say hello on Twitter!</a></em></p><!--kg-card-begin: html--><blockquote class="twitter-tweet"><p lang="en" dir="ltr">True that...<br>There are always (at least) two ways to solve a problem. One is faster, the other you just don&#x2019;t know yet.<br>So.. I&apos;ve just added state management with Redux to an ultra simple application that could be shipped with 3 lines of functional Vanilla JS.<br>You are welcome &#x1F643; <a href="https://t.co/5oNDwU7suB">pic.twitter.com/5oNDwU7suB</a></p>&#x2014; Morse Wall (@morsewall) <a href="https://twitter.com/morsewall/status/1423002361757376518?ref_src=twsrc%5Etfw">August 4, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script><!--kg-card-end: html--><p><br><em>Also, if you have built a random quote machine after reading this post, share it as comment to the tweet above on Twitter. Really excited to see what you create!</em></p><p><em>Happy coding!</em></p><hr><h3 id="where-to-find-me">Where to find me:</h3><p></p><p>Follow me on Twitter:</p><!--kg-card-begin: markdown--><p><a href="https://twitter.com/celue"><img src="https://i.ibb.co/pZ016N6/Follow-Pat-Eskinasy.png" alt="How to Build a Random Quote Machine &#x2013; Part 4 &#x2013; Redux: Using various front end stacks" style="width:100%"></a></p>
<!--kg-card-end: markdown--><p>You can always get my latest writings directly to your email address by<strong> <a href="https://morsewall.com/signup/">subscribing to Morse Wall</a>.</strong></p><hr><h3 id="update">UPDATE</h3><p></p><p>Part 5 of this series has now been published. <a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/">Go check it out!</a> I&apos;m using Redux Thunk to call an asynchronous endpoint as the data (quotes) is requested from an external resource in the fifth flavor.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Random Quote Machine – Part 3 – Vanilla JavaScript and REST API: Using various front end stacks]]></title><description><![CDATA[11 ways - How to build a random quote machine. And a bonus Kanye West random Quote machine via a REST API.
]]></description><link>https://morsewall.com/random-quote-part-3-vanilla-javascript-and-rest-api-using-various-front-end-stacks/</link><guid isPermaLink="false">6383dba085b265021049b863</guid><category><![CDATA[REST API]]></category><category><![CDATA[JSON]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Side Project]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Pat Eskinasy]]></dc:creator><pubDate>Wed, 28 Jul 2021 00:00:00 GMT</pubDate><media:content url="https://morsewall.com/content/images/2022/11/kanyequote2.png" medium="image"/><content:encoded><![CDATA[<h3 id="building-a-random-quote-machine-with-vanilla-javascript-and-rest-api">Building a random quote machine with Vanilla JavaScript and REST API</h3><img src="https://morsewall.com/content/images/2022/11/kanyequote2.png" alt="How to Build a Random Quote Machine &#x2013; Part 3 &#x2013; Vanilla JavaScript and REST API: Using various front end stacks"><p></p><p>Part 3 of this series is now ON. <em>You can read more about this project&#x2019;s background <a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">on the project&#x2019;s page</a>. Or start from the beginning with <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">part 1 of this series</a>.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><p>In <a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/#flavor-2-html-css-vanilla-js-json-with-quotes">flavor #2</a>, the data (quotes) is found in a <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy?ref=morsewall.com">same origin resource</a>, since it is stored in a separate JSON file hosted together with the rest of the code.</p><p>In this flavor, I&#x2019;m requesting the quotes data from a REST API.</p><p>These are the different flavors that are part of this series:</p><!--kg-card-begin: html--><ol>
    <li><a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + JSON with quotes</a> (members-only post)</li>
    <li>HTML + CSS + Vanilla JS + quotes REST API (this flavor)</li>
    <li><strike>HTML + Vanilla JS + SAAS + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about SASS)</em></li>
    <li><strike>HTML + Vanilla JS + Bootstrap + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about Bootstrap)</em></li>
    <li><strike>HTML + CSS + JQuery + JSON with quotes</strike><em> (nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/">HTML + CSS + Redux + quotes array</a></li>
    <li><strike>HTML + CSS + Redux + JQuery + JSON with quotes</strike> <em>(nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/">HTML + CSS + Redux + Redux Thunk + JSON with quotes</a></li>
    <li><a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/"> HTML + CSS + React + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/">HTML + CSS + React + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-8-react-hooks-using-various-front-end-stacks/">HTML + CSS + React Hooks + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/">HTML + CSS + React Hooks + JSON with quotes</a> (members-only post)</li>
    <li><strike>HTML + CSS + React + React Redux + quotes array</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><strike>HTML + CSS + React + React Redux + Redux Thunk + JSON with quotes</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-11-react-hooks-react-redux-and-redux-thunk-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + Redux Thunk + JSON with quotes</a></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + Redux Thunk + JSON with quote</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
</ol>  <!--kg-card-end: html--><p>If you are new here, you may wonder why I am overcomplicating a really simple application that can be shipped in 3 lines of functional Vanilla JavaScript. And the reason is: Shipping a simple app in a simple environment with fewer moving parts = great way to practice a new way to solve a problem. This is the spirit behind the <em><em><a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">Making a random quote machine in a few different flavors</a></em></em> series. Enjoy!</p><hr><p><em>In Part 4 (to be posted next week), I will cover a fourth flavor and will be using state management (with Redux) to render the random quotes.</em></p><p><em>If you&#x2019;re curious about the next flavors and would like to make a writer very happy today, you should <strong><a href="https://morsewall.com/signup/">subscribe to Morse Wall</a>.</strong></em></p><hr><h3 id="flavor-3-html-css-vanilla-js-quotes-rest-api">Flavor #3: HTML + CSS + Vanilla JS + quotes REST API</h3><p></p><p>To make things simple and not have to deal with back end code for such a simple project, I&#x2019;m implementing an API with the help of Typicode&#x2019;s <a href="https://my-json-server.typicode.com/?ref=morsewall.com">My JSON Server</a>. My JSON Server is a fake online REST server that does what I need it to do: <code>GET</code> API calls. Another positive is that it doesn&#x2019;t persist data changes, i.e. <code>POST</code>, <code>PUT</code>, <code>PATCH</code> and <code>DELETE</code> API requests for a resource do not persist between different calls, so I don&#x2019;t need to worry about securing the API.</p><p>I&#x2019;m calling the API with the <a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch?ref=morsewall.com">fetch() method</a>, the same method I&#x2019;m using in <a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/#flavor-2-html-css-vanilla-js-json-with-quotes">flavor #2</a>.</p><pre><code class="language-js">//asynchronous function that gets data from the API and populates the quotes array
const makeRequest = async () =&gt; {
  const responseJSON = await fetch(
    &quot;https://my-json-server.typicode.com/morsewall/jsondb/quotes&quot;
  );
  quotes = await responseJSON.json();
};</code></pre><p></p><p>The JSON response from the API returns all quotes and I&#x2019;m randomly picking a quote from the data in my front end code (as done in previous flavors). The rest of the code remains the same as in <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#flavor-1-html-css-vanilla-js-quotes-array">flavor #1</a> and you can <a href="https://morsewall.github.io/random-quotes-vanillajs-rest-api/">check the project live</a>. Source code for <a href="https://github.com/morsewall/random-quotes-vanillajs-rest-api">flavor #3 in Github</a>.</p><!--kg-card-begin: html--><div class="button-set">
    <button style="border-radius:8px;background-color:#000000;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://morsewall.github.io/random-quotes-vanillajs-rest-api/" style="margin:1rem;" class="button-in-post">Live Project</a></button>
    <button style="border-radius:8px;background-color:#000000;color:#ffffff;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://github.com/morsewall/random-quotes-vanillajs-rest-api" style="margin:1rem;" class="button-in-post">Source code</a></button>
</div><!--kg-card-end: html--><p></p><h3 id="using-a-different-rest-api-making-a-random-kanye-west-quote-machine">Using a different REST API. Making a random Kanye West quote machine.</h3><p></p><p>Looking for alternative quote APIs to call (someone else&#x2019;s data, on someone else&#x2019;s server), I came across Andrew Jazbec&#x2019;s <a href="https://github.com/ajzbc/kanye.rest/?ref=morsewall.com">Rest API for random Kanye West&#x2019;s quotes</a>. Fetching from that, doing a quick change to the background image and DONE: The <a href="https://kanye-west.netlify.com/?ref=morsewall.com">Random Kanye West quote machine</a> is ready to receive any random person on the web.<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-5.cloudinary.com/hnhggca76/image/upload/q_auto/v1/ghost-blog-images/kanyequote2.png" class="kg-image" alt="How to Build a Random Quote Machine &#x2013; Part 3 &#x2013; Vanilla JavaScript and REST API: Using various front end stacks" loading="lazy" width="3360" height="1790"><figcaption>Kanye West random quote generator</figcaption></figure><!--kg-card-begin: html--><div class="button-set">
    <button style="border-radius:8px;background-color:#000000;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://kanye-west.netlify.app/" style="margin:1rem;" class="button-in-post">Check Live Project</a></button>
</div><!--kg-card-end: html--><hr><h3 id="acknowledgement">Acknowledgement</h3><p></p><p>The following goes without saying, but here it comes anyways: Please note that in this ever changing world of technology, I am writing this article in July 2019 (hello, summer!) and alternate solutions might have become available as you read this writing.</p><hr><p><em>In Part 4 (to be posted next week), I will cover a fourth flavor and will be using state management (with Redux) to render the random quotes.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should<strong> <a href="https://morsewall.com/signup/">subscribe to Morse Wall</a>. </strong>I think you&#x2019;ll like it a lot!</em></p><hr><p><em>So, what did you like about this post? <a href="https://twitter.com/celue">Come say hello on Twitter!</a></em></p><!--kg-card-begin: html--><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Random quote machine done once, random quote machine done twice, now thrice. Doing this tiny project with 11 different front-end stacks. This week, by calling a REST API we get from a Greta Thunberg quote machine to a Kanye West quote machine. <a href="https://t.co/KXDD2CsU5c">pic.twitter.com/KXDD2CsU5c</a></p>&#x2014; Morse Wall (@morsewall) <a href="https://twitter.com/morsewall/status/1420391316177948678?ref_src=twsrc%5Etfw">July 28, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<!--kg-card-end: html--><p></p><p><em>Also, if you have built a random quote machine after reading this post, share it as comment to the tweet above on Twitter. Really excited to see what you create!</em></p><p><em>Happy coding!</em></p><hr><h3 id="where-to-find-me">Where to find me:</h3><p></p><p>Follow me on Twitter:</p><!--kg-card-begin: markdown--><p><a href="https://twitter.com/celue"><img src="https://i.ibb.co/pZ016N6/Follow-Pat-Eskinasy.png" alt="How to Build a Random Quote Machine &#x2013; Part 3 &#x2013; Vanilla JavaScript and REST API: Using various front end stacks" style="width:100%"></a></p>
<!--kg-card-end: markdown--><p>You can always get my latest writings directly to your email address by <a href="https://morsewall.com/signup/"><strong>subscribing to Morse Wall</strong></a><strong>.</strong></p><hr><h3 id="update">UPDATE</h3><p></p><p>Part 4 of this series has now been published. <a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/">Go check it out!</a> I&#x2019;m using state management (with Redux) to help me update the different UI elements with the current application state in the fourth flavor.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Random Quote Machine – Part 2 – Vanilla JavaScript and JSON: Using various front end stacks]]></title><description><![CDATA[11 ways - How to build a random quote machine. Using Vanilla JavaScript and other data structures (JSON).]]></description><link>https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/</link><guid isPermaLink="false">6383daf285b265021049b84c</guid><category><![CDATA[JSON]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Side Project]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Pat Eskinasy]]></dc:creator><pubDate>Wed, 21 Jul 2021 17:01:00 GMT</pubDate><media:content url="https://morsewall.com/content/images/2022/11/flavor2.png" medium="image"/><content:encoded><![CDATA[<h3 id="building-a-random-quote-machine-with-vanilla-javascript-and-json">Building a random quote machine with Vanilla JavaScript and JSON</h3><img src="https://morsewall.com/content/images/2022/11/flavor2.png" alt="How to Build a Random Quote Machine &#x2013; Part 2 &#x2013; Vanilla JavaScript and JSON: Using various front end stacks"><p></p><p>Here comes Part 2 of this series. <em>You can read more about this project&#x2019;s background <a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">on the project&#x2019;s page</a>. Or start from the beginning with <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/">part 1 of this series</a>.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><p>In <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#flavor-1-html-css-vanilla-js-quotes-array">flavor #1</a>, I have the data (quotes) inside an array. In this flavor, I&#x2019;m storing the quotes in a separate JSON file.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Random Quote Machine – Vanilla JavaScript: Using various front end stacks]]></title><description><![CDATA[11 ways - How to build a random quote machine. Using Vanilla JavaScript.]]></description><link>https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/</link><guid isPermaLink="false">6383d93b85b265021049b7e4</guid><category><![CDATA[Javascript]]></category><category><![CDATA[Scraping]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Side Project]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Pat Eskinasy]]></dc:creator><pubDate>Thu, 15 Jul 2021 13:09:00 GMT</pubDate><media:content url="https://morsewall.com/content/images/2022/11/flavor1.png" medium="image"/><content:encoded><![CDATA[<h3 id="building-a-random-quote-machine-with-vanilla-javascript">Building a random quote machine with Vanilla JavaScript</h3><img src="https://morsewall.com/content/images/2022/11/flavor1.png" alt="How to Build a Random Quote Machine &#x2013; Vanilla JavaScript: Using various front end stacks"><p></p><p>This is Part 1 of an 11-part series. Each part using a different front end stack (different flavor). Starring in this flavor: Vanilla JavaScript.</p><p><em>If you&#x2019;re curious about the next flavors, you should <strong><em><em><em><a href="https://morsewall.com/signup">subscribe to Morse Wall</a></em></em></em>.</strong> I think you&#x2019;ll like it a lot!</em></p><!--kg-card-begin: html--><p><strong>Goal with this series of writings:</strong> Build a random quote machine with <strike>19</strike> 11 different front end stacks and ship quickly.</p><!--kg-card-end: html--><blockquote><strong>True that&#x2026;</strong></blockquote><blockquote><strong>There are always (at least) two ways to solve a problem. One is faster, the other you just don&#x2019;t know yet.</strong></blockquote><p><em>You can read more about this project&#x2019;s background <a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors">on the project&#x2019;s page</a>.</em></p><p>So, what should the random quote machine do? It should spit out quotes.</p><!--kg-card-begin: html--><p id="userstories">
    These are the <strong>user stories</strong>:
</p>    <!--kg-card-end: html--><p>As a random person on the web inspired by Greta Thunberg (or not - <em>see note below</em>), I want to be welcomed by a nice inspirational quote from Greta Thunberg so that I become (even more) inspired.</p><ol><li>As a random person on the web, I want to be able to click a button to get a new inspirational quote from Greta Thunberg so that I can pimp my inspiration levels.</li><li>As a random person on the web, I want to be able to share on Twitter the quote the random quote machine gives me so that I can share my source of inspiration with the world.</li></ol><p>Note: <em>Before you get your &#x201C;I have issues with Greta Thunberg&#x201D; sticker-coated pitchforks out: No matter your strongly held opinions&#x2026;powerful narratives you know, gotta love them. Point being: don&#x2019;t @ me if you dislike Ms. Thunberg</em>.</p><!--kg-card-begin: markdown--><p><img src="https://i.ibb.co/XFZWpBY/gretablogpost.gif" alt="How to Build a Random Quote Machine &#x2013; Vanilla JavaScript: Using various front end stacks" loading="lazy"></p>
<!--kg-card-end: markdown--><p>Here are the different flavors available:</p><!--kg-card-begin: html--><ol>
    <li>HTML + CSS + Vanilla JS + quotes array (this flavor)</li>
    <li><a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-3-vanilla-javascript-and-rest-api-using-various-front-end-stacks/">HTML + CSS + Vanilla JS + quotes REST API</a></li>
    <li><strike>HTML + Vanilla JS + SAAS + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about SASS)</em></li>
    <li><strike>HTML + Vanilla JS + Bootstrap + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about Bootstrap)</em></li>
    <li><strike>HTML + CSS + JQuery + JSON with quotes</strike><em> (nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-4-redux-using-various-front-end-stacks/">HTML + CSS + Redux + quotes array</a></li>
    <li><strike>HTML + CSS + Redux + JQuery + JSON with quotes</strike> <em>(nah, because let&#x2019;s be opinionated about JQuery)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-5-redux-thunk-using-various-front-end-stacks/">HTML + CSS + Redux + Redux Thunk + JSON with quotes</a></li>
    <li><a href="https://morsewall.com/random-quote-part-6-react-using-various-front-end-stacks/"> HTML + CSS + React + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-7-react-and-json-using-various-front-end-stacks/">HTML + CSS + React + JSON with quotes</a> (members-only post)</li>
    <li><a href="https://morsewall.com/random-quote-part-8-react-hooks-using-various-front-end-stacks/">HTML + CSS + React Hooks + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-9-react-hooks-and-json-using-various-front-end-stacks/">HTML + CSS + React Hooks + JSON with quotes</a> (members-only post)</li>
    <li><strike>HTML + CSS + React + React Redux + quotes array</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><strike>HTML + CSS + React + React Redux + Redux Thunk + JSON with quotes</strike><em> (nah, because let&#x2019;s be bullish about writing any new components with React Hooks)</em></li>
    <li><a href="https://morsewall.com/random-quote-part-10-react-hooks-and-react-redux-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + quotes array</a></li>
    <li><a href="https://morsewall.com/random-quote-part-11-react-hooks-react-redux-and-redux-thunk-using-various-front-end-stacks/">HTML + CSS + React Hooks + React Redux + Redux Thunk + JSON with quotes</a></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + quotes array</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
    <li><strike>HTML + CSS + React Hooks + React Redux Hooks + Redux Thunk + JSON with quote</strike><em> (nah, because let&#x2019;s be opinionated about React Redux Hooks)</em></li>
</ol>    <!--kg-card-end: html--><p>If you are new here, you may wonder why I am overcomplicating a really simple application that can be shipped in 3 lines of functional Vanilla JavaScript. And the reason is: Shipping a simple app in a simple environment with fewer moving parts = great way to practice a new way to solve a problem. This is the spirit behind the <em><em><a href="https://morsewall.com/projects/making-a-random-quote-machine-in-different-flavors/">Making a random quote machine in a few different flavors</a></em></em> series. Enjoy!</p><hr><p><em>In Part 2 (to be posted next week), I will cover a second flavor and will be storing the quotes in a separate JSON file.</em></p><p><em>If you&#x2019;re curious about the next flavors and would like to make a writer very happy today, you should <strong><a href="https://morsewall.com/signup">subscribe to Morse Wall</a>.</strong></em></p><hr><p>This is a simple project. <a href="https://morsewall.com/random-quote-vanilla-javascript-using-various-front-end-stacks/#flavor-1-html-css-vanilla-js-quotes-array">Flavor #1</a> has essentially 3 lines of functional JavaScript code.</p><p>The URL to the source code for each flavor is linked at the bottom of each section in this series.</p><h3 id="flavor-1-html-css-vanilla-js-quotes-array">Flavor #1: HTML + CSS + Vanilla JS + quotes array</h3><p></p><p>HTML and CSS aside (they can be found in the <a href="https://github.com/morsewall/random-quote-vanillajs-array/">Github repo for flavor #1</a>). I&#x2019;m into Vanilla JavaScript universe in flavor #1. The data (quotes) are inside an array.</p><p>I&#x2019;ve scraped the quotes with the help of <a href="https://tryspider.com//?ref=morsewall.com">Spider</a>, a point&amp;click scraping tool built by Amie-Chen. So, with the help of Spider, you can also go ahead and easily collect quotes from any prolific public figure you choose.</p><p>When I was done scraping, I&#x2019;ve then downloaded a JSON from Spider and copy-pasted the quotes into an array inside my <code>script.js</code>. There are only 3 quotes in the code snippet below (so I can illustrate the point), but many more quotes in the array in production.</p><pre><code class="language-javascript">// script.js
//defining an array for the quotes
const quotes = [
  {
    quoteText:
      &apos;&quot;Many of you appear concerned that we are wasting valuable lesson time, but I assure you we will go back to school the moment you start listening to science and give us a future.&quot;&apos;,
    quoteAuthor: &quot;Greta Thunberg&quot;,
  },
  {
    quoteText:
      &apos;&quot;I was fortunate to be born in a time and place where everyone told us to dream big. I could become whatever I wanted to. I could live wherever I wanted to. People like me had everything we needed and more. Things our grandparents could not even dream of. We had everything we could ever wish for and yet now we may have nothing. Now we probably don&#x2019;t even have a future any more.&quot;&apos;,
    quoteAuthor: &quot;Greta Thunberg&quot;,
  },
  {
    quoteText:
      &apos;&quot;That future was sold so that a small number of people could make unimaginable amounts of money. It was stolen from us every time you said that the sky was the limit, and that you only live once. You lied to us. You gave us false hope. You told us that the future was something to look forward to.&quot;&apos;,
    quoteAuthor: &quot;Greta Thunberg&quot;,
  },
];</code></pre><p></p><p>Given I want a random quote to be ready for me when the quote machine loads, I need to call a function (that I still need to define) that fetches a random quote and renders it my HTML.</p><pre><code class="language-javascript">// script.js
// inject a quote on screen when app loads
injectQuote();</code></pre><p></p><p>And given I also want a new random quote when the user clicks a button, I&#x2019;ve added a <code>click</code> event listener to the HTML element with <code>new-quote</code> id.</p><p>In the HTML, setting up <code>new-quote</code> id (as always, you can check the <a href="https://github.com/morsewall/random-quote-vanillajs-array/">full source code in the repo</a>. Also linked at the bottom of this write-up):</p><pre><code class="language-html">&lt;!-- index.html --&gt;
&lt;button id=&quot;new-quote&quot; class=&quot;new-quote&quot;&gt;Get New Quote&lt;/button&gt;</code></pre><p></p><p>Back to JavaScript, adding the <code>click</code> event listener:</p><pre><code class="language-javascript">// script.js
//inject a quote on screen when &quot;Get New Quote&quot; button is clicked
document.getElementById(&quot;new-quote&quot;).addEventListener(&quot;click&quot;, function () {
  injectQuote();
});</code></pre><p></p><h3 id="injectquote-function"><code>injectQuote</code> function</h3><p></p><p>The bit missing is to define the function I&#x2019;ve mentioned above that will fetch a random quote from my <code>quotes</code> array and render it in my HTML. I&#x2019;m calling that function <code>injectQuote</code>.</p><pre><code class="language-js">// script.js
//function to access random quote from array and inject it together with author on HTML
function injectQuote() {}</code></pre><p></p><p><code>injectQuote</code> needs to pick a random quote from <code>quotes</code>, so let&#x2019;s do that first thing. I&#x2019;ll be incrementally expanding <code>injectQuote</code> in each of the following code snippets, to the point it will be clear it would have been better to break <code>injectQuote</code> down into smaller functions (huh&#x2026;)</p><pre><code class="language-js">// script.js
//function to access random quote from array and inject it together with author on HTML
function injectQuote() {
  //access random quote from quote array
  let randomQuote = quotes[Math.floor(Math.random() * quotes.length)];
}
</code></pre><p></p><p>After fetching a random quote, <code>injectQuote</code> should render the quote text and and quote author in my HTML.</p><pre><code class="language-js">// script.js
//function to access random quote from array and inject it together with author on HTML
function injectQuote() {
  //access random quote from quote array
  let randomQuote = quotes[Math.floor(Math.random() * quotes.length)];
  //inject random quote on HTML
  document.getElementById(&quot;text&quot;).innerHTML = randomQuote.quoteText;
  let quoteTextElem = randomQuote.quoteText;
  //inject author on HTML
  document.getElementById(&quot;author&quot;).innerHTML = &quot;- &quot; + randomQuote.quoteAuthor;
  let quoteAuthorElem = &quot; - &quot; + randomQuote.quoteAuthor;
}</code></pre><p></p><p>With the above in production, the random quote machine beautifully renders a new quote upon page load and when a user clicks a button requesting a new quote.</p><h3 id="making-the-machine-tweet"><br>Making the machine tweet</h3><p><br>However, I haven&#x2019;t made the <em>Tweet Quote</em> button work yet. So, to invoke <a href="https://developer.twitter.com/en/docs/twitter-for-websites/web-intents/overview.html?ref=morsewall.com">Twitter Web Intents</a>, <code>injectQuote</code> should URL-encode the tweet text, concatenate it with <code>https://twitter.com/intent/tweet?text=</code> and pass it to the HTML element&#x2019;s <code>href</code>.</p><p>In the HTML, setting up <code>tweet-quote</code> id:</p><pre><code class="language-html">&lt;!-- index.html --&gt;
&lt;button class=&quot;tweet-quote&quot;&gt;
  &lt;a id=&quot;tweet-quote&quot; href=&quot;twitter.com/intent/tweet&quot; target=&quot;_blank&quot;
    &gt;&lt;em class=&quot;fab fa-twitter&quot;&gt;&lt;/em&gt;Tweet Quote&lt;/a
  &gt;
&lt;/button&gt;</code></pre><p></p><p>And back to JavaScript:</p><pre><code class="language-js">//script.js
//function to access random quote from array and inject it together with author on HTML
function injectQuote() {
  //access random quote from quote array
  let randomQuote = quotes[Math.floor(Math.random() * quotes.length)];
  //inject random quote on HTML
  document.getElementById(&quot;text&quot;).innerHTML = randomQuote.quoteText;
  let quoteTextElem = randomQuote.quoteText;
  //inject author on HTML
  document.getElementById(&quot;author&quot;).innerHTML = &quot;- &quot; + randomQuote.quoteAuthor;
  let quoteAuthorElem = &quot; - &quot; + randomQuote.quoteAuthor;
  //defining tweet text
  let contentQuote = quoteTextElem + quoteAuthorElem;
  //generate url available for Twitter intent and inject url on HTML
  document.getElementById(&quot;tweet-quote&quot;).href =
    &quot;https://twitter.com/intent/tweet?text=&quot; + contentQuote;
}</code></pre><p></p><p>Ok, now the random quote machine ships all the required user stories.</p><p>The issue here though is that some of Greta&#x2019;s quotes are longer than 280 characters (better than 140 char, I know. Thanks <a href="https://twitter.com/jack">@jack</a>). I have to truncate the quote text to allow the user to tweet the quote without having to delete characters. <code>injectQuote</code> (now already <a href="https://martinfowler.com/bliki/FunctionLength.html?ref=morsewall.com">doing far too much for a single function</a>) needs some adjustments.</p><pre><code class="language-js">// script.js
//function to access random quote from array and inject it together with author on HTML
function injectQuote() {
  //access random quote from quote array
  let randomQuote = quotes[Math.floor(Math.random() * quotes.length)];
  //inject random quote on HTML
  document.getElementById(&quot;text&quot;).innerHTML = randomQuote.quoteText;
  let quoteTextElem = randomQuote.quoteText;
  //inject author on HTML
  document.getElementById(&quot;author&quot;).innerHTML = &quot;- &quot; + randomQuote.quoteAuthor;
  let quoteAuthorElem = &quot; - &quot; + randomQuote.quoteAuthor;
  //truncating quote text in case full tweet gets to be over 280 characters
  let contentQuote = quoteTextElem + quoteAuthorElem;
  if (contentQuote.length &gt; 280) {
    let charCountAuthor = quoteAuthorElem.length;
    const extraStylingChar = &quot;...&quot; + &apos;&quot;&apos;;
    let extraCharCount = extraStylingChar.length;
    let subString =
      quoteTextElem.substring(0, 280 - extraCharCount - charCountAuthor) +
      extraStylingChar +
      quoteAuthorElem;
    //generate url available for Twitter intent and inject url on HTML
    document.getElementById(&quot;tweet-quote&quot;).href =
      &quot;https://twitter.com/intent/tweet?text=&quot; + subString;
  } else {
    //generate url available for Twitter intent and inject url on HTML
    document.getElementById(&quot;tweet-quote&quot;).href =
      &quot;https://twitter.com/intent/tweet?text=&quot; + contentQuote;
  }
}
</code></pre><p><br>Done. The <a href="https://morsewall.github.io/random-quote-vanillajs-array/">random quote machine</a> is ready to receive any random person on the web.</p><p>If you think a great Greta Thunberg quote is missing, I&#x2019;ll be happy to include it. Pull requests are more than welcome in the <a href="https://github.com/morsewall/random-quote-vanillajs-array/">Github repo for flavor #1</a>.</p><!--kg-card-begin: html--><div class="button-set">
    <button style="border-radius:8px;background-color:#000000;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://morsewall.github.io/random-quote-vanillajs-array/" style="margin:1rem;" class="button-in-post">Live Project</a></button>
    <button style="border-radius:8px;background-color:#000000;color:#ffffff;font-size:1.5rem;font-weight:bold;height:3.5rem;"><a href="https://github.com/morsewall/random-quote-vanillajs-array" style="margin:1rem;" class="button-in-post">Source code</a></button>
</div><!--kg-card-end: html--><hr><h3 id="acknowledgement">Acknowledgement</h3><p></p><p>The following goes without saying, but here it comes anyways: Please note that in this ever changing world of technology, I am writing this article in July 2019 (hello, summer!) and alternate solutions might have become available as you read this writing.</p><hr><p><em>In Part 2 (to be posted next week), I will cover a second flavor and will be storing the quotes in a separate JSON file.</em></p><p><em>If you&#x2019;re curious about the next flavors, you should <a href="https://morsewall.com/signup"><strong>subscribe to Morse Wall</strong></a>. I think you&#x2019;ll like it a lot!</em></p><hr><p><em>So, what did you like about this post? &#xA0;<a href="https://twitter.com/celue">Come say hello on Twitter!</a></em></p><!--kg-card-begin: html--><blockquote class="twitter-tweet"><p lang="en" dir="ltr">My favourite formula for solving a software development problem<br>1) Get it done fast and cheaply<br>2) Solve the same problem in 11 different ways because *shiny new thing* syndrome<br><br>&#x1F643;Ha! <br>Over the next weeks I&apos;ll write about 11 different ways to build a random quote machine <a href="https://t.co/gLBWItAkCi">pic.twitter.com/gLBWItAkCi</a></p>&#x2014; Morse Wall (@morsewall) <a href="https://twitter.com/morsewall/status/1415721438808510468?ref_src=twsrc%5Etfw">July 15, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script><!--kg-card-end: html--><p></p><p><em>Also, if you have built a random quote machine after reading this post, share it as comment to the tweet above on Twitter. Really excited to see what you create!</em></p><p><em>Happy coding!</em></p><hr><h3 id="where-to-find-me">Where to find me:</h3><p></p><p>Follow me on Twitter:</p><!--kg-card-begin: markdown--><p><a href="https://twitter.com/celue"><img src="https://i.ibb.co/pZ016N6/Follow-Pat-Eskinasy.png" alt="How to Build a Random Quote Machine &#x2013; Vanilla JavaScript: Using various front end stacks" style="width:100%"></a></p>
<!--kg-card-end: markdown--><p>You can always get my latest writings directly to your email address by <a href="https://morsewall.com/signup/"><strong>subscribing to Morse Wall</strong></a><strong>.</strong></p><hr><h3 id="update">UPDATE<br></h3><p></p><p>Part 2 of this series has now been published. <a href="https://morsewall.com/random-quote-part-2-vanilla-javascript-and-json-using-various-front-end-stacks/">Go check it out!</a> I&apos;m storing the quotes in a separate JSON file in the second flavor.</p>]]></content:encoded></item></channel></rss>