<?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:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Megan (Dommel) Story on Medium]]></title>
        <description><![CDATA[Stories by Megan (Dommel) Story on Medium]]></description>
        <link>https://medium.com/@dommelmeg?source=rss-e32a9fbc4b7------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*v5-g62j4f1_CrhXyfQBy6A.png</url>
            <title>Stories by Megan (Dommel) Story on Medium</title>
            <link>https://medium.com/@dommelmeg?source=rss-e32a9fbc4b7------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 24 May 2026 02:24:59 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@dommelmeg/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Date Night, Software Engineer Style]]></title>
            <link>https://medium.com/@dommelmeg/date-night-software-engineer-style-85e001216936?source=rss-e32a9fbc4b7------2</link>
            <guid isPermaLink="false">https://medium.com/p/85e001216936</guid>
            <category><![CDATA[date-night]]></category>
            <category><![CDATA[react-query]]></category>
            <category><![CDATA[coding-challenge]]></category>
            <category><![CDATA[rock-paper-scissors]]></category>
            <dc:creator><![CDATA[Megan (Dommel) Story]]></dc:creator>
            <pubDate>Fri, 19 Jan 2024 03:46:08 GMT</pubDate>
            <atom:updated>2024-01-19T03:51:57.825Z</atom:updated>
            <content:encoded><![CDATA[<p>My husband, Bill and I are both Software Engineers. We both went through the Flatiron School Software Engineering Bootcamp, I just took the plunge 7 years after him. As a couple, we are always looking for unique twists on date nights and typically go for a fun game or art night and as professionals, we are always striving to improve our technical skills. Since I recently graduated from the Flatiron Bootcamp, we decided to take our date night in a slightly different direction by incorporating <em>code</em>!</p><blockquote>Can you really call it a date night if you are learning technical skills?? Idk, but we had fun &amp; plan on doing this again!</blockquote><h3>Recipe for a Coding Delight</h3><ol><li>Choose a public API. We used <a href="https://github.com/public-apis/public-apis">this list</a>. <em>Bill got first pick, but I’m up next!</em></li><li>Set a timer &amp; stick to it! <em>We decided on ~2 hours for our trial run, but will probably stick with 1 hour in the future.</em></li><li>Move fast and break things!</li><li>When the timer goes off, it’s time to share and discuss! <em>We showed each other what we built &amp; our code. Then we talked through any challenges we ran into, things we’d do differently next time and provided any feedback we had for each other.</em></li></ol><h3>So how did it go?</h3><p>We used the <a href="https://rps101.pythonanywhere.com/api">Rock, Paper, Scissors 101 API</a> for our first attempt — it provides you with 101 different <em>Rock, Paper, Scissors</em> tools to use and an endpoint to hit when you want to see who wins/loses in a match up, we’ll call this the ‘match result’. We both used Vite + React + React Query + Chakra. I coded all in one file (<em>like a complete monster</em>), Bill used a couple components. Then we were off!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*t4jrVvwpTHaJ4FX83_85eQ.png" /></figure><h3>Difficulties</h3><p>We both hit the same bump in the road, hitting the <em>match result</em> endpoint, <em>after</em> both tools had been chosen. With React Query, all hooks must be called at the top level of a functional component. This means doing something like the code shown below wouldn’t work.</p><pre>const handleGamePlay = () =&gt; {<br>  const { data: results, refetch } = useQuery({<br>    queryKey: [&quot;results&quot;],<br>    queryFn: () =&gt; {<br>      return axios.get(<br>        `https://rps101.pythonanywhere.com/api/v1/match?object_one=${playerChoice}&amp;object_two=${computerChoice}`<br>      );<br>    },<br>  });<br>}<br><br>&lt;Button onClick={handleGamePlay}&gt;Let&#39;s Play!&lt;/Button&gt;</pre><p>I admit, this was not a super challenging problem to solve, however, it was something neither of us had come across before. <em>The solution? </em>The refetch method! We set the default setting to <em>NOT</em> fetch the data automatically using the key <em>enabled </em>&amp; setting it to<em> false. Refetch </em>is a method that comes with<em> useQuery </em>so don’t forget to extract that!</p><pre>const { data: results, refetch } = useQuery({<br>    queryKey: [&quot;results&quot;],<br>    queryFn: () =&gt; {<br>      return axios.get(<br>        `https://rps101.pythonanywhere.com/api/v1/match?object_one=${playerChoice}&amp;object_two=${computerChoice}`<br>      );<br>    },<br>    enabled: false,<br>  });</pre><p>Then when the button is clicked you can call the <em>refetch</em> method.</p><pre>&lt;Button onClick={() =&gt; refetch()}&gt;Let&#39;s Play!&lt;/Button&gt;</pre><h3>Take Aways</h3><ul><li>We both agreed that 1-hour is probably going to be the sweet spot now that we have 1 attempt under our belt.</li><li>We are going to try to stick to unique API’s like this Rock, Paper, Scissors one to avoid making 1 CRUD app after another.</li></ul><p>Check out a quick walk through of my app here: <a href="https://youtu.be/6TxWBGsdAkk">https://youtu.be/6TxWBGsdAkk</a></p><p>Articles that helped me during this challenge:<br>- <a href="https://www.calvintorra.com/blog/how-to-trigger-usequery-with-a-button-click-react-query">https://www.calvintorra.com/blog/how-to-trigger-usequery-with-a-button-click-react-query</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=85e001216936" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jotai + React Query > Redux Toolkit]]></title>
            <link>https://medium.com/@dommelmeg/jotai-react-query-redux-1c4e1afc0df8?source=rss-e32a9fbc4b7------2</link>
            <guid isPermaLink="false">https://medium.com/p/1c4e1afc0df8</guid>
            <category><![CDATA[jotai]]></category>
            <category><![CDATA[redux]]></category>
            <category><![CDATA[usereducer]]></category>
            <category><![CDATA[react-query]]></category>
            <category><![CDATA[rtk-query]]></category>
            <dc:creator><![CDATA[Megan (Dommel) Story]]></dc:creator>
            <pubDate>Thu, 14 Dec 2023 23:13:47 GMT</pubDate>
            <atom:updated>2023-12-15T21:26:48.248Z</atom:updated>
            <content:encoded><![CDATA[<p><em>I’ll start off by saying, my feelings on Redux/RTK Query are purely based on the research I did and the small tantrums I threw while trying to implement Redux into my Flatiron Capstone project — Redux may be the best choice for you and your project, it just wasn’t for me and mine this time around. *DISCLAIMER* If you are an employer reading this, I promised I learned a lot on my Redux journey and I am capable of working with it. :)</em></p><p>Alright, now let’s get into the real meat and potatoes of the thing.</p><h3>Redux Toolkit + RTK Query</h3><p>My Capstone project requirements were pretty straightforward — manage state using something like useContext or Redux. I had used useContext for my previous 2 projects and loved it so much that <a href="https://medium.com/@dommelmeg/giving-some-context-to-prop-drilling-2039c41856f8">I wrote a blog</a> on it. However, I wanted to expand my knowledge so I decided to go the Redux route this time around. I was excited about the possibilities of the combo of Redux &amp; RTK Query (so long handling complex state management–coincidentally another <a href="https://medium.com/@dommelmeg/simplifying-state-management-81ea0ab42a3c">blog post</a> of mine). But that excitement died pretty quickly after spending some time trying to get everything up and running smoothly. Here are some of the problems I ran into:</p><ol><li>THE LEARNING CURVE<br>I found the Redux learning curve to be intense. The docs were confusing and when I would look to other sources for examples it seemed like everyone was doing it a completely different way. It made it challenging to figure out which parts were 100% necessary to get it up and running successfully.</li><li>BOILERPLATE CODE<br>My goodness there is A LOT of boilerplate code that goes into Redux Toolkit (what’s crazy is Toolkit is the “cut down” version of Redux). This adds unnecessary confusion. And I say unnecessary because it really didn’t take much to get the libraries I did use working. This leads me to my “final straw”.</li><li>RTK QUERY IS WORDY<br>Much like the contestants on the Bachelor/Bachelorette, RTK Query uses A LOT of words…to say very little. That’s really all that needs to be said here.</li></ol><h3>Why I Avoided useContext This Time</h3><p>Like I said before, despite loving the ease of useContext, I still wanted to use something new for this project. I also discovered, while reading around that useContext isn’t always the best answer. It turns out that once your context grows too large then you have entire re-renders every time anything within that context object changes. This isn’t great for performance.</p><h3>What I Did Use</h3><p>STATE MANAGEMENT</p><ol><li><a href="https://jotai.org/">Jotai</a> — a state management library that is simple and flexible. Jotai also solves the re-rendering issues surrounding Context by optimizing re-renders based on atom dependency. <em>Bonus points, it has a fun ghost mascot!</em></li></ol><p>I used Jotai to store my user state. Once the atom is created, you can use it in any component. Using <em>atoms</em> looks and functions similarly to useState, however instead of the state living in that component, atoms are global.</p><pre>// atoms.ts<br>import { atom } from &#39;jotai&#39;<br><br>export const userAuthAtom = atomWithStorage(&#39;userAuth&#39;, initialState)<br><br>// SignIn.tsx<br>import { userAuthAtom } from &quot;../StateManagement/store&quot;<br>import { useAtom } from &quot;jotai&quot;<br><br>const [currentUser, setCurrentUser] = useAtom(userAuthAtom)</pre><p>2. useReducer — instead of useState to handle my form state, I went with useReducer for this project. This simplified handling my form components and I felt like it was easier to read as well.</p><p>I defined my initial SignIn State object and wrote a reducer function (this can include other cases such as radio changes, select changes, etc). The reducer function takes in the initial state and an action then returns the new state.</p><pre>// SignIn.tsx<br>import React, { useReducer } from &quot;react&quot;;<br><br>const initialSignInState = {<br>    username: &#39;&#39;,<br>    password: &#39;&#39;,<br>}<br><br>const signInReducer = (state, action) =&gt; {<br>  switch (action.type) {<br>    case &#39;HANDLE INPUT TEXT&#39;:<br>      return {<br>        ...state,<br>        [action.field]: action.payload,<br>      }<br>    default:<br>      return state <br>  }<br>}<br><br>const [signInState, dispatch] = useReducer(signInReducer, initialSignInState)<br><br>const handleInputChange = (e) =&gt; {<br>  dispatch({<br>    type: &#39;HANDLE INPUT TEXT&#39;,<br>    field: e.target.name,<br>    payload: e.target.value,<br>  })<br>}</pre><p>FETCHING DATA</p><ol><li><a href="https://tanstack.com/query/v3">React Query</a> — a server-state library that manages remote data fetching in React Apps, handles automatic refetching of stale data, and so much more. While I also found the docs challenging at times, once I got the hang of handling Queries and Mutations, there is very little code needed to get the job done. Another star feature of React Query — it completely handles the state of items that would be stored in Redux/Context, allowing you to keep your client-side state fairly small.</li></ol><p>In this sign in example, I am using a mutation instead of a query. The useMutation hook takes the mutation function and provides a mutation object. I used the data returned to setCurrentUser (this is the atom from above). In addition to onSuccess, you can also use the onError callback to handle any errors that may occur.</p><pre>// SignIn.tsx<br>import { useMutation } from &#39;@tanstack/react-query&#39;;<br>import axios from &#39;axios&#39;;<br><br>const signUserIn = useMutation({<br>    mutationFn: (user) =&gt; {<br>      return axios.post(&#39;/signin&#39;, user)<br>      .then((res) =&gt; {<br>        setCurrentUser(res.data)<br>      })<br>    },<br>    onSuccess: () =&gt; {<br>        navigate(&#39;/&#39;)<br>      }<br>  })<br>  <br>  const handleSignInClick = (e) =&gt; {<br>    e.preventDefault()<br>    signUserIn.mutate(signInState)<br>  }</pre><p>There are many other libraries out there that are comparable, but these are the ones that I decided worked best for me and weren’t to crazy to figure out!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1c4e1afc0df8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[All Aboard! First stop, [Rails] Migration Station]]></title>
            <link>https://medium.com/@dommelmeg/all-aboard-first-stop-rails-migration-station-54a22f3eb76?source=rss-e32a9fbc4b7------2</link>
            <guid isPermaLink="false">https://medium.com/p/54a22f3eb76</guid>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[rails]]></category>
            <category><![CDATA[rails-generators]]></category>
            <category><![CDATA[rails-migration]]></category>
            <dc:creator><![CDATA[Megan (Dommel) Story]]></dc:creator>
            <pubDate>Mon, 03 Jul 2023 01:18:32 GMT</pubDate>
            <atom:updated>2023-07-10T03:59:58.033Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/900/1*XY_FICijm2VIxCoJ6okf6A.jpeg" /></figure><p>As I was working on my 4th project for my Flatiron Software Engineering program, I found myself constantly having to look up the syntax for Rails Generators (many other things too, but we won’t go there, ha! Any other new coders have like a million tabs open while they work??) So I figured creating a Rails Generator syntax guide would not only be helpful for me, but hopefully for you too since you are reading this. So without further ado, all aboard the Rails[road] Train.</p><h3>What Are Rails Generators and Why Use Them?</h3><p>If you are reading this post, you are likely already familiar with the full-stack framework, Rails. Rails has ready-to-use tools called <em>generators</em> that make creating, updating, migrating, etc., simple. Rails generators allow you to develop via the command line in your terminal rather than having to manually create files and write out any code for the additions/changes you want to make.</p><p>Here’s what your generator should look like:</p><pre>Rails generator [name of generator] [options]</pre><p>Or, to save yourself a few keystrokes, you can type ‘g’ instead of ‘generator’:</p><pre>Rails g [name of generator] [options]</pre><p>I’ll dive more into what goes in each of those brackets below. For now, sit back and enjoy the ride.</p><h3>Generators: The Basics</h3><p>Alright, the train is leaving the station — let’s talk the basics.</p><p><strong>MODELS<br></strong><em>Naming Conventions–</em>models should be capitalized and singular, ie. <em>User</em>. If the model name requires that you use more than one word, you should use CamelCase, ie. <em>QuiltPattern.</em></p><p><em>Creating a Model</em>–To generate a model using a generator, you want to use this syntax:</p><pre>Rails g model [model name] [attribute:data type]</pre><p>You’ll use the naming convention mentioned above for the <em>model name</em>. The default data type for an <em>attribute</em> is ‘string’, so you do not have to type that out. However, you will need to specify the data type if it is anything other than a string. Let’s look at an example:</p><pre>Rails g model Event event_name user_id:integer event_date:date image_url</pre><p>Note, once you run the above command, a model file and migration file will also be generated–more on that later. The model file will look like this:</p><pre>class Event &lt; ApplicationRecord<br> <br>end</pre><p>*Don’t forget to run <strong><em>rails db:migrate</em></strong> to migrate any changes made.</p><p><strong>CONTROLLERS</strong><br><em>Naming Conventions–</em>capitalized and plural. ie. <em>Users</em> or <em>QuiltPatterns.</em></p><p><em>Creating a Controller–</em>To generate a controller, you want to use the following syntax:</p><pre>Rails g controller [PluralName] [list of actions]</pre><p>The list of actions are optional, but if you choose to include them, they will update the <em>routes.rb</em> file as well. Let’s look at an example:</p><pre>Rails g controller Events index show</pre><p>Your controller file will look something like this:</p><pre>class EventsController &lt; ApplicationController<br>  def index<br>  end<br>  <br>  def show<br>  end<br>end</pre><p><strong>SERIALIZERS</strong><br><em>Naming Conventions–</em>singular and snake_case. ie. <em>user</em> or <em>quilt_pattern</em></p><p><em>Creating a serializer</em>–To generate a serializer, you want to use the following syntax:</p><pre>Rails g serializer [name]</pre><p>Let’s look at an example:</p><pre>Rails g serializer event</pre><p>This will generate a <em>serializer.rb</em> file that looks something like this:</p><pre>class EventSerializer &lt; ActiveModel::Serializer<br><br>end</pre><h3>Generators: Migrations</h3><p>We’re almost to our destination–let’s talk migrations.</p><p><em>Naming Conventions–</em>for the following migrations, the naming conventions are the same. You want to use CamelCase and the plural table name when generating migrations.</p><p>CREATE A TABLE<br>Use the word <strong>“Create”</strong> in your generator to create a new table. Like creating a model–discussed above–you can include attributes and their data types <em>(remember ‘string’ is the default data type). </em>This also generates a migration file populated with the new table info.</p><pre>Rails g migration Create[tableName] [attribute:data type]</pre><p>Example:<br><em>Generator</em></p><pre>Rails g migration CreateVendors vendor_name vendor_type rating:integer website_url</pre><p><em>Migration File</em></p><pre>class CreateVendors &lt; ActiveRecord::Migration[6.1]<br>  def change<br>    create_table :vendors do |t|<br>      t.string :name<br>      t.string :vendor_type<br>      t.integer :rating<br>      t.string :website_url<br><br>      t.timestamps<br>    end<br>  end<br>end</pre><p>DELETE A TABLE<br>Use the word <strong>“Drop” </strong>in your generator to delete a table. This will create an empty migration file.</p><pre>Rails g migration Drop[tableName]</pre><p>Example:<br><em>Generator</em></p><pre>Rails g migration DropVendors</pre><p><em>Migration File</em><br>You’ll need to fill in this migration file using <strong><em>drop_table :table_name</em></strong></p><pre>class DropVendors &lt; ActiveRecord::Migration[6.1]<br>  def change<br>    drop_table :vendors<br>  end<br>end</pre><p>ADD A COLUMN</p><pre>Rails g migration Add[columnName]To[tableName] [attribute:data type]</pre><p>Example:<br><em>Generator</em></p><pre>Rails g migration AddReviewToVendors review:text</pre><p><em>Migration File<br></em>That will generate a migration file filled in with the column addition wanted. It will look something like this:</p><pre>class AddReviewToVendors &lt; ActiveRecord::Migration[6.1]<br>  def change<br>    add_column :vendors, :review, :text<br>  end<br>end</pre><p>CHANGE A COLUMN NAME</p><pre>Rails g migration Change[columnName]Column</pre><p>Example:<br><em>Generator</em></p><pre>Rails g migration ChangeWebsiteUrlColumn</pre><p><em>Migration File</em><br>You’ll need to fill in this migration file using <strong><em>rename_column :table_name, :old_column_name, :new_column_name. </em></strong>It should look something like this:</p><pre>class ChangeWebsiteUrlColumn &lt; ActiveRecord::Migration[6.1]<br>  def change<br>    rename_column :vendors, :website_url, :web_address<br>  end<br>end</pre><p>DELETE COLUMN</p><pre>Rails g migration Remove[columnName]From[tableName] [attribute:data type]</pre><p>Example:<br><em>Generator</em></p><pre>Rails g migration RemoveWebAddressFromVendors web_address</pre><p><em>Migration File<br></em>This automatically generates a migration file with the info for the column you want removed.</p><pre>class RemoveWebAddressFromVendors &lt; ActiveRecord::Migration[6.1]<br>  def change<br>    remove_column :vendors, :web_address, :string<br>  end<br>end</pre><p>**To lock in any changes you make via migrations, be sure to run:</p><pre>rails db:migrate</pre><h3>Generators: The One-and-Done Command</h3><p>As we pull into the station (we made it!) I can’t leave out the one and done command that generates everything I talked about above. But, of course, it doesn’t come with out its own list of pros and cons.</p><p>Run the command below, will create the following:</p><pre>Rails g resource [model name] [attribute:data type]</pre><p>1.Model<br>2. Migration<br>3. Controller<br>4. Resources in <em>routes.rb </em>file</p><p>While this makes it quick and easy to generate all of those files, you just want to make sure you don’t have unnecessary/unused routes (resources). If you want to have more control over what you are creating, I suggest creating each file individually.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=54a22f3eb76" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Tackling the Complexities of State Management]]></title>
            <link>https://medium.com/@dommelmeg/simplifying-state-management-81ea0ab42a3c?source=rss-e32a9fbc4b7------2</link>
            <guid isPermaLink="false">https://medium.com/p/81ea0ab42a3c</guid>
            <dc:creator><![CDATA[Megan (Dommel) Story]]></dc:creator>
            <pubDate>Mon, 17 Apr 2023 20:29:51 GMT</pubDate>
            <atom:updated>2023-04-18T21:04:42.041Z</atom:updated>
            <content:encoded><![CDATA[<p>While working on my latest project, I ran into what felt like some of the most complex code I’ve had to write so far in my coding journey. I’m talking about <em>State Management </em>and all of the complexities that can come with that. This is a very important part of development that allows your app to function smoothly and scale efficiently.</p><h3>The Problem</h3><p>My back end deals with 2 models — books and reviews<em>. </em>Books <em>have many</em> reviews, reviews<em> belong to a </em>book. When I initially fetch my books data when the app loads, I want to include the reviews associated with each book.</p><pre>get &quot;/books&quot; do<br>    book = Book.all<br>    book.to_json(include: :reviews)<br>  end</pre><p>This is what my book data looks like with reviews included.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jqEljuHO_X9RDMHJK8M7zQ.png" /></figure><p>Okay, that seems simple enough right? Well what if I want to edit(PATCH) a review, add(POST) a new review, or delete a review associated with a specific book? That’s where things get a little more complicated. You want do this without fetching your books data again. <em>But how?</em></p><p>For simplicity, I am going to show you how I solved the problem for adding a new review to a specific book.</p><h3>The Janky “Fix”</h3><p><em>*Disclaimer: Do not manage your state in the way I am about to show you!*</em></p><p>My initial solution to the problem? Refetch the updated data and reset my state… Why did I do it this way? Probably because I was being lazy, or maybe because the right solution seemed daunting. However, if my app were to refetch data to reset state every time I wanted to manipulate the data in someway, several issues could occur including a slow running app and the lack of scalability.</p><p>Here is what my code originally looked like before I reworked it. Notice the double fetch.</p><pre>fetch(&#39;http://localhost:9292/reviews&#39;, {<br>      method: &#39;POST&#39;,<br>      headers: {<br>        &#39;Content-Type&#39;: &#39;application/json&#39;<br>      },<br>      body: JSON.stringify(formData)<br>    })<br>      .then((r) =&gt; r.json())<br>      .then(() =&gt; {<br>        fetch(&#39;http://localhost:9292/books&#39;)<br>          .then((r) =&gt; r.json())<br>          .then((books) =&gt; setBooks(books))<br>      })</pre><h3>The “Correct” Fix</h3><p><em>Now of course there are several different ways you can correctly manage your state, but the point I am trying to make by calling it the “correct fix” is just that you are not refetching your updated data.</em></p><pre>fetch(&#39;http://localhost:9292/reviews&#39;, {<br>      method: &#39;POST&#39;,<br>      headers: {<br>        &#39;Content-Type&#39;: &#39;application/json&#39;<br>      },<br>      body: JSON.stringify(formData)<br>    })<br>      .then((r) =&gt; r.json())<br>      .then((newReview) =&gt; {<br>        const updatedBooks = books.map((book) =&gt; {<br>          if (book.id === newReview.book_id) {<br>            return {...book, reviews: [...book.reviews, newReview]}<br>          } else { <br>            return book<br>          }<br>        })<br>        setBooks(updatedBooks)<br>      })</pre><h3>Let’s Break It Down</h3><p>Here is the pseudo coding I wrote to help me figure out the steps I needed to take:</p><ol><li>Iterate through the array of book objects to find the book that I am adding the review to.</li><li>Grab the array of review objects associated with that book.</li><li>Set that book’s review array to a copy of that review array with the new review added in. <em>Spread operator.</em></li><li>Update the array of book objects with a copy of that book with it’s now updated array of reviews.</li></ol><p>Like I said before, there are many ways you could manage your state, this is just the way that made the most sense to me. I’d love to see your approach!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=81ea0ab42a3c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Giving Some Context to Prop Drilling]]></title>
            <link>https://medium.com/@dommelmeg/giving-some-context-to-prop-drilling-2039c41856f8?source=rss-e32a9fbc4b7------2</link>
            <guid isPermaLink="false">https://medium.com/p/2039c41856f8</guid>
            <category><![CDATA[prop-drilling]]></category>
            <category><![CDATA[react-context]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Megan (Dommel) Story]]></dc:creator>
            <pubDate>Wed, 08 Feb 2023 23:51:59 GMT</pubDate>
            <atom:updated>2023-04-05T16:21:11.912Z</atom:updated>
            <content:encoded><![CDATA[<p>While the term ‘prop drilling’ has nothing to do with actual construction, speaking from experience, it can feel like you are demolishing and building back parts of your code if you don’t initially think about ways to combat prop drilling before diving into a project.</p><h3>What is prop drilling?</h3><p>When working in React, oftentimes you will need to pass data (in the form of props) from a parent component to a child component — or from the top of your nested components to bottom. Generally you only want to pass data to/through components that actually need to use said props. However, if, like me, you find yourself passing props down several layers of nested components — some of which aren’t using the prop at all — you have began to prop drill.</p><p>In short, <em>prop drilling</em> is when you pass props down through several layers of nested components solely for the purpose of using it in a deeply-nested component.</p><p>Let’s look at a visual example of prop drilling, using state. The * indicates the components that are actually using the data.</p><pre>App [favoriteCharacters, setFavoriteCharacters]<br>-&gt; Characters[favoriteCharacters, setFavoriteCharacters]<br>   -&gt; CharacterCard [favoriteCharacters, setFavoriteCharacters]<br>      -&gt; FavoriteButton [favoriteCharacters, setFavoriteCharacters]*<br>-&gt; Favorite Characters [favoriteCharacters, setFavoriteCharacters]*<br>   -&gt; CharacterCard [favoriteCharacters, setFavoriteCharacters]<br>      -&gt; FavoriteButton [favoriteCharacters, setFavoriteCharacters]*</pre><p>You can see above that I needed to set FavoriteCharacter state in the <em>App</em> component in order to pass it to both <em>Home</em> and <em>Favorite Characters </em>(to then be trickled down to their children, etc). However, <em>App</em> and <em>Home</em> do not actually use this data.</p><h3>Why should you avoid prop drilling?</h3><p>You may be asking yourself, <em>why is prop drilling a problem</em>? Or maybe you’re a bit newer to React like me, and didn’t realize it was a problem until you started refactoring your code.</p><ul><li><strong>Unnecessary Code:</strong> Since most of the components involved in prop drilling do not actually use the data passed through them (other than to pass them along to their children), they are merely acting as middlemen. This can lead to issues down the road, or just messy code.</li><li><strong>Confusing Code:</strong> Confusing code isn’t just a ‘you-problem’. If you are working on a joint project, or in industry, other people are going to be looking at your code, if it is difficult for them to follow, then you are doing your job incorrectly!</li><li><strong>Prone to Errors:</strong> Passing data down through many components leaves room for errors, for example if you forget to pass a prop through just one component, it can lead to a frustrating time trying to figure out why your code isn’t working–again, speaking from experience here…</li></ul><h3><strong>Ways to deal with prop drilling</strong></h3><p>There are 2 ways you can handle prop drilling: <em>component composition</em> and <em>context</em>. I will be showing you how I solved prop drilling with context. However, it is worth briefly mentioning component composition in case that is a better option for you.</p><p><strong>Component Composition — <em>many levels, same nest</em></strong></p><p>Are you passing your props through many levels of the same nested group of components? Then component composition is probably your best bet. Component composition is essentially the fundamental of how you work in React. You can learn more about component composition in the <a href="https://reactjs.org/docs/composition-vs-inheritance.html">React Docs</a>.</p><p><strong>Context — <em>many levels, different nests</em></strong></p><p>Are you passing your props through components at different nesting levels? Context — the star of the show here — can help! Creating Context allows you to pass your props directly to the components you need, rather than trickling down the list of nested components — which is just tedious (and confusing!) It takes a little bit of set up, but once that is done, it is easy to implement.</p><h3>Let’s create some Context</h3><p>Okay enough chit chat, let’s get to the example. In this specific case, I was passing state through several components to get to the spot where I needed to set state. Let’s refer back to the example from earlier and look at how we can clean it up with context. Ideally we want it to look more like this:</p><pre>App<br>-&gt; Characters<br>   -&gt; CharacterCard<br>      -&gt; FavoriteButton [favoriteCharactersContext]<br>-&gt; Favorite Characters [favoriteCharactersContext]<br>   -&gt; CharacterCard<br>      -&gt; FavoriteButton [favoriteCharactersContext]</pre><h4>Step 1: Create your Context file</h4><ul><li>Create a new folder in your project called <em>context</em>.</li><li>Inside of that <em>context</em> folder, create a <em>.js fil</em>e. <em>I named mine</em> ‘favoriteCharacters.js’.</li></ul><h4>Step 2: Create Context</h4><ul><li>First, lets create context by using React.createContext()</li></ul><pre>import React, { useState } from &#39;react&#39;<br><br>const FavoriteCharacterContext = React.createContext()</pre><ul><li>Next, add a <em>provider</em> component. <em>We will eventually wrap our app in this provider tag in order to give our components access to the data in the </em>favoriteCharacters.js<em> file.</em></li></ul><pre>import React, { useState } from &#39;react&#39;<br><br>const FavoriteCharacterContext = React.createContext()<br><br>const FavoriteCharacterProvider = ({children}) =&gt; {<br>  return (<br>  )<br>}</pre><ul><li>Inside the <em>FavoriteCharacterProvider</em> component, I added the favoriteCharacters state that I needed access to.</li></ul><pre>import React, { useState } from &#39;react&#39;<br><br>const FavoriteCharacterContext = React.createContext()<br><br>const FavoriteCharacterProvider = ({children}) =&gt; {<br>  const [favoriteCharacters, setFavoriteCharacters] = useState([])<br><br>  return (<br>  )<br>}</pre><ul><li>Finally, in the return of the provider component, the value is set to the state and since I used {children} between the tags, the children of the provider tag will have access to ‘value’. <em>To reiterate, once we wrap our app in the provider tag, anything inside of those tags will have access to the set value.</em></li></ul><pre>import React, { useState } from &#39;react&#39;<br><br>const FavoriteCharacterContext = React.createContext()<br><br>const FavoriteCharacterProvider = ({children}) =&gt; {<br>  const [favoriteCharacters, setFavoriteCharacters] = useState([])<br><br>  return (<br>    &lt;FavoriteCharacterContext.Provider<br>      value={{ favoriteCharacters, setFavoriteCharacters }}<br>    &gt;<br>      {children}<br>    &lt;/FavoriteCharacterContext.Provider&gt;<br>  )<br>}</pre><ul><li>Don’t forget: Import React and in this case, useState &amp; export both the context variable you declared and the provider component!</li></ul><pre>import React, { useState } from &#39;react&#39;<br><br>const FavoriteCharacterContext = React.createContext()<br><br>const FavoriteCharacterProvider = ({children}) =&gt; {<br>  const [favoriteCharacters, setFavoriteCharacters] = useState([])<br><br>  return (<br>    &lt;FavoriteCharacterContext.Provider<br>      value={{ favoriteCharacters, setFavoriteCharacters }}<br>    &gt;<br>      {children}<br>    &lt;/FavoriteCharacterContext.Provider&gt;<br>  )<br>}<br><br>export { FavoriteCharacterContext, FavoriteCharacterProvider }</pre><h4>Step 3: useContext — Implementing context in your code</h4><ul><li>Before we <em>wrap our app</em>, let’s take a look at what my <em>App </em>component looked like before context was introduced.</li></ul><pre>function App() {<br>  const [favoriteCharacters, setFavoriteCharacter] = useState([])<br><br>  return (<br>    &lt;NavBar /&gt;<br>    &lt;Switch&gt;<br>      &lt;Route path=&#39;/characters&#39;&gt;<br>        &lt;Characters <br>          favoriteCharacters={favoriteCharacters}<br>          setFavoriteCharacters={setFavoriteCharacters}<br>        /&gt;<br>      &lt;/Route&gt;<br>      &lt;Route path=&#39;/ohmybabies&#39;&gt;<br>        &lt;OhMyBabies<br>          favoriteCharacters={favoriteCharacters}<br>          setFavoriteCharacters={setFavoriteCharacters}<br>        /&gt;<br>      &lt;/Route&gt;<br>    &lt;/Switch&gt;<br>  )<br>}</pre><p>That’s a lot to take in right? A couple things to point out:</p><ol><li>The <em>App </em>component itself is not utilizing the state I set up, it is just passing it along to its 2 children, <em>Characters </em>and<em> OhMyBabies</em>.</li><li>I have repetitive code:</li></ol><pre>favoriteCharacters={favoriteCharacters}<br>setFavoriteCharacters={setFavoriteCharacters}</pre><ul><li>Okay, we have finally made it to the long anticipated<em> wrapping of the app</em>–woo! After importing your context file, you want to be sure to wrap the components that need access to the data in your context file.</li></ul><pre>import { FavoriteCharacterProvider } from &quot;../context/favoriteCharacters&quot;;<br><br>function App() {<br>  return (<br>    &lt;NavBar /&gt;<br>    &lt;FavoriteCharacterProvider&gt;<br>      &lt;Switch&gt;<br>        &lt;Route path=&#39;/characters&#39;&gt;<br>          &lt;Characters /&gt;<br>        &lt;/Route&gt;<br>        &lt;Route path=&#39;/ohmybabies&#39;&gt;<br>          &lt;OhMyBabies /&gt;<br>        &lt;/Route&gt;<br>      &lt;/Switch&gt;<br>    &lt;/FavoriteCharacterProvider&gt;<br>  )<br>}</pre><p>Isn’t that much cleaner! Notice that I also removed useState() as well as the repetitive props from both children components.</p><ul><li>Next, we need to add it to the components that need access to the data in the context file. Let’s look at the original <em>FavoriteCharacters</em> component:</li></ul><pre>import React from &quot;react&quot;;<br>import { Box, SimpleGrid, Stack, Heading } from &#39;@chakra-ui/react&#39;<br>import CharacterCard from &quot;../components/CharacterCard&quot;;<br><br>const OhMyBabies = ({favoriteCharacters, setFavoriteCharacters}) =&gt; {<br>  return (<br>    &lt;Stack m={10}&gt;<br>      &lt;Box&gt;<br>        &lt;Heading color=&#39;yellow.500&#39; size=&#39;2xl&#39;&gt;Oh My Babies!&lt;/Heading&gt;<br>      &lt;/Box&gt;<br>      &lt;SimpleGrid spacing={4} templateColumns=&#39;repeat(auto-fill, minmax(400px, 1fr))&#39;&gt;<br>        {favoriteCharacters.map((favoriteCharacter) =&gt; {<br>          return (<br>            &lt;CharacterCard <br>              key={favoriteCharacter.id} <br>              character={favoriteCharacter}<br>              favoriteCharacters={favoriteCharacters}<br>              setFavoriteCharacters={setFavoriteCharacters}<br>            /&gt;<br>          )<br>        })}<br>      &lt;/SimpleGrid&gt;<br>    &lt;/Stack&gt;<br>  )<br>}<br><br>export default OhMyBabies</pre><p>The important things to note here are that we are passing in both <em>favoriteCharacters </em>and <em>setFavoriteCharacters, </em>only using <em>favoriteCharacters</em>, and then passing both props along to the <em>CharacterCard</em> component so it can then give the <em>FavoriteButton</em> component access to both props.</p><ul><li>Adding context is now very simple!</li></ul><pre>import React, { useContext } from &quot;react&quot;;<br>import { Box, SimpleGrid, Stack, Heading } from &#39;@chakra-ui/react&#39;<br>import CharacterCard from &quot;../components/CharacterCard&quot;;<br>import { FavoriteCharacterContext } from &quot;../context/favoriteCharacters&quot;;<br><br>const OhMyBabies = () =&gt; {<br>  const { favoriteCharacters } = useContext(FavoriteCharacterContext)<br><br>  return (<br>    &lt;Stack m={10}&gt;<br>      &lt;Box&gt;<br>        &lt;Heading color=&#39;yellow.500&#39; size=&#39;2xl&#39;&gt;Oh My Babies!&lt;/Heading&gt;<br>      &lt;/Box&gt;<br>      &lt;SimpleGrid spacing={4} templateColumns=&#39;repeat(auto-fill, minmax(400px, 1fr))&#39;&gt;<br>        {favoriteCharacters.map((favoriteCharacter) =&gt; {<br>          return (<br>            &lt;CharacterCard <br>              key={favoriteCharacter.id} <br>              character={favoriteCharacter} <br>            /&gt;<br>          )<br>        })}<br>      &lt;/SimpleGrid&gt;<br>    &lt;/Stack&gt;<br>  )<br>}<br><br>export default OhMyBabies</pre><p>A few things to note:</p><ol><li>I added { useContext } to my React import.</li><li>I imported my context file and <em>FavoriteCharacterContext</em>.</li><li>I added useContext() inside my <em>OhMyBabies</em> component and only pulled out the one prop I needed to use — in this case <em>favoriteCharacters</em>.</li><li>Finally, I deleted the two <em>favoriteCharacters</em> props passing through the <em>CharacterCard</em> component.</li></ol><ul><li>This process looks the exact same for the FavoriteButton component, except for one minor change. I need to use both props in that component so my useContext() looks like this:</li></ul><pre>const { favoriteCharacters, setFavoriteCharacters } = useContext(FavoriteCharacterContext)</pre><h3>Conclusion</h3><p>And there you have it! We’ve added context, using state to simplify our code!</p><h4>References</h4><ul><li><a href="https://reactjs.org/docs/context.html#before-you-use-context">Context</a></li><li><a href="https://reactjs.org/docs/composition-vs-inheritance.html">Composition v. Inheritance</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2039c41856f8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[console.log(‘hi’)]]></title>
            <link>https://medium.com/@dommelmeg/console-log-hi-730583c24f56?source=rss-e32a9fbc4b7------2</link>
            <guid isPermaLink="false">https://medium.com/p/730583c24f56</guid>
            <category><![CDATA[new-to-programming]]></category>
            <category><![CDATA[beginner-code]]></category>
            <category><![CDATA[beginner-coding]]></category>
            <category><![CDATA[console-log]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Megan (Dommel) Story]]></dc:creator>
            <pubDate>Tue, 13 Dec 2022 02:24:00 GMT</pubDate>
            <atom:updated>2022-12-13T02:24:00.035Z</atom:updated>
            <content:encoded><![CDATA[<p>What is console logging and why is it — in my opinion — just as important as learning the logic behind code?</p><p>When I first started learning to code (mind you I came in with next to zero experience), I remember first reading about console.log() and thinking, okay that’s cool… but how will this actually be used in real life? It wasn’t until I started my first project that I realized just how important console logging really is.</p><p>Have you ever written code that just doesn’t seem to be working and you can’t figure out why? Or maybe you have an event listener on an element that you <em>just know</em> you grabbed correctly, but the event isn’t functioning the way you expect it to and the error in your code isn’t jumping out at you. In both situations (and many many others), console.log() can be used to get to the bottom of the problem.</p><p>Okay, let’s back up a little. console.log() is a JavaScript method that logs something to the console — pretty self explanatory, eh?</p><p>The syntax is as follows:</p><pre>console.log(x)</pre><p>In the general example above, the x is the variable or value that you want logged to the console.</p><p>You can console.log() any JavaScript data type. Let’s look at a few more simple examples:</p><p><strong>console.log() a string</strong></p><pre>console.log(&#39;hi&#39;)</pre><p>Open your browser dev tools, navigate to your console, copy and paste the above code into the console + press enter, you should see <em>hi </em>is now logged.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/418/1*6WSpAgD0piDLKqsRpqLO4Q.png" /></figure><p><strong>console.log() a number</strong></p><pre>console.log(6)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/418/1*iY9VW4ku26d_FftUIswBxA.png" /></figure><p><strong>console.log() variables</strong></p><pre>let x = &#39;hi &#39;<br>let y = &#39;world&#39;<br><br>console.log(x + y)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/420/1*fbFP0vYsNG3m6cwevsbWyA.png" /></figure><p><strong>console.log() an object</strong></p><pre>console.log([&#39;red&#39;, &#39;orange&#39;, &#39;yellow&#39;, &#39;green&#39;, &#39;blue&#39;, &#39;violet&#39;])</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1014/1*dj2PRVSSKg-W8B8FjjB6eQ.png" /></figure><p>Okay now you’re probably thinking <em>“That’s cool and all… but how is that going to help me in real life?”</em> Console logging <em>irl</em> can be used in many ways — debugging, confirming that you selected the correct element, and checking how data is being returned, just to name a few. All of these examples are ways that will make building your first (or two-hundred and first) project a much smoother process.</p><p><strong>But wait, what DOM element am I actually selecting?</strong></p><p>When manipulating the DOM (document object model), knowing if you’re selecting the exact HTML element you want can sometimes be tricky. It’s always good to do a quick console.log() of the element you want to grab and use later on in your code. This could ultimately save you time debugging code if you were to grab the wrong element (or no element at all!) Trust me, there is no such thing as console logging too much!</p><p><strong>I have a collection of data (in this example, an API) but now what?</strong></p><p>When working on my first project, one of the most helpful ways that I used console.log() was checking exactly how the <a href="https://www.thecocktaildb.com/api.php">API I used</a> was returning data. Let’s take a closer look:</p><p>Let’s say I have this bit of code, that is fetching a random cocktail from my API. Before I start working with the data, I really want to see what I am getting back, so I know how to best work with said data.</p><pre>const getRandomCocktail = () =&gt; {<br>  fetch(&#39;https://www.thecocktaildb.com/api/json/v1/1/random.php&#39;)<br>    .then((res) =&gt; res.json())<br>    .then((drink) =&gt; console.log(drink))<br>}</pre><p>When I refresh my index.html in the browser — once again I will need my browser console open — I should see one random drink displayed in the console.</p><p><em>*If you are new to coding, it is important to remember that you will only see what ever you </em><em>console.log() in your console, not on the web page itself!</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lcyvmszY9DVspyC2h3fsXA.png" /></figure><p>As you can see, what was logged is an object of an array of a single object. Now I know how to properly manipulate this data — think if I had assumed the data was displayed in a different way, my code would break and I wouldn’t have known why.</p><h3><strong>console.log() Helps You Understand What is Happening in Your Code</strong></h3><p><strong>Breaking down the </strong><strong>.forEach() array method with </strong><strong>console.log()</strong></p><p>For me, array methods didn’t 100% click until I started my first real world use of them. If that is also the case for you, don’t fret, console.log() is here to help!</p><p><em>For this example I am going to use the </em><a href="https://www.w3schools.com/jsref/jsref_foreach.asp"><em>.forEach() JavaScript array method</em></a><em>.</em></p><p>Let’s start with the following code snippet:</p><pre>const renderDrinks = (objectOfDrinks) =&gt; {<br>  const arrayOfDrinks = objectOfDrinks.drinks<br>  arrayOfDrinks.forEach(drink =&gt; {<br>    const { strDrink, strDrinkThumb, idDrink } = drink<br>    const card = document.createElement(&#39;div&#39;)<br>    card.className = &#39;card&#39;<br>    card.innerHTML = `<br>      &lt;img src=&quot;${strDrinkThumb}&quot;<br>        class=&#39;drinkImage&#39;<br>        alt=&quot;${strDrink}&quot;<br>        id=&#39;${strDrink} image&#39;<br>      /&gt;<br>      &lt;h2&gt;${strDrink}&lt;/h2&gt;<br>      &lt;button class=learnMoreBtn id=${idDrink}&gt;Gimmie the Deets!<br>    `<br>    cocktailCardDiv.appendChild(card)<br>}</pre><p>In this example, I want to render multiple drinks using an array of objects provided to me by the cocktail API I used in my previous example. Let’s break this down a little more:</p><ol><li>I am using an <a href="https://www.w3schools.com/js/js_arrow_function.asp">arrow function</a> to build a function that will render multiple drinks.</li><li>This function is taking in an <strong>objectOfDrinks</strong>… but wait, what does that look like you ask? Let’s console.log() it and find out.</li></ol><pre>const renderDrinks = (objectOfDrinks) =&gt; console.log(objectOfDrinks)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KV9x9ALWxqdjMLunVWUQWg.png" /></figure><p>Okay perfect, now I know I am getting an object of an array of objects (Inception anyone?) — let’s get into that array so I can use the .forEach() array method on it.</p><p>3. In order to do that, I am going to declare a variable and dive down a level into my array. This is another great time to console log. Let’s see what we are working with now.</p><pre>const renderDrinks = (objectOfDrinks) =&gt; {<br>  const arrayOfDrinks = objectOfDrinks.drinks<br>  console.log(arrayOfDrinks)<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*y3RWMPMK1UZcXPvH2nFOSg.png" /></figure><p>Awesome, now I am working with just the array of objects. Now let’s use the .forEach() method on this new array that we assigned to the variable <strong>arrayOfDrinks.</strong></p><p>4. I will take my <strong>arrayOfDrinks</strong> array and apply the .forEach() method. Inside of the parenthesis goes like this “For each <strong>drink</strong>, I want to console log <strong>drink”. </strong><em>Remember, I am using </em><em>console.log() here to simply see what the data that I am about to manipulate looks like.</em></p><pre>const renderDrinks = (objectOfDrinks) =&gt; {<br>  const arrayOfDrinks = objectOfDrinks.drinks<br>  arrayOfDrinks.forEach(drink =&gt; console.log(drink))<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WfRZ3tjQXQ8MbVrsRavI1w.png" /></figure><p>Look at that — console logging <strong>drink</strong> in this .forEach() example has broken the array of objects into individual objects. This makes it easy to now apply some sort of manipulation to each drink!</p><p>These are just a few examples of how I used console.log() to make the process of coding my first project smoother and to help myself really understand the logic behind the code, there are of course many other ways you can use it as well.</p><p><em>The best way to learn is to get in there and try things out, happy coding!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=730583c24f56" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>