<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: william-luck</title>
    <description>The latest articles on DEV Community by william-luck (@williamluck).</description>
    <link>https://dev.to/williamluck</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F860554%2F30d5e2d8-94b2-41b5-b3e2-03e657d39d9a.png</url>
      <title>DEV Community: william-luck</title>
      <link>https://dev.to/williamluck</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/williamluck"/>
    <language>en</language>
    <item>
      <title>My Journey Through Flatiron's Software Engineering Flex Program</title>
      <dc:creator>william-luck</dc:creator>
      <pubDate>Sat, 29 Apr 2023 18:54:41 +0000</pubDate>
      <link>https://dev.to/williamluck/my-journey-through-flatirons-software-engineering-flex-program-4hph</link>
      <guid>https://dev.to/williamluck/my-journey-through-flatirons-software-engineering-flex-program-4hph</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;If you're wondering if you can complete Flatiron's software engineering bootcamp as a flex student, you definetely and most certainly can. But I hope that I can get the message across that it is not easy, and your life is going to look a lot different over the next 20, 40, or 60 weeks (or 59 weeks in my case). &lt;/p&gt;

&lt;p&gt;I originally planned to finish the program between 20 and 40 weeks, but ending up doubling that due to work commitments, relationships, traveling, and becoming an expat in the strange land that is Argentina. &lt;/p&gt;

&lt;p&gt;I have worked on completing the program. from Austin, Seattle, Puerto Vallarta, Buenos Aires, Patagonia (even stuffing myself in a cabin for a month to refocus), Belize, and Guatemala, where I am currently writing this post. I have done all of this while doing third-party monitoring of USAID-funded aid assistance in post-ISIS Iraq, which is more remote-work-accessible than you think. &lt;/p&gt;

&lt;p&gt;The beauty of this program is that all this is indeed possible, at the price of some measurable level of sanity, but possible nonetheless. I would recommend this program to anyone with a full time job or other serious responsibilities to confront, and those who are clinging to remote work in the face of consistent return-to-office requests post COVID. It is not easy balancing responsibilities, and I would have to count the number of times  I’ve had to reschedule 1:1s with my instructor on three hands, when work somehow has the ability to schedule meetings exactly during my 1:1 slot. &lt;/p&gt;

&lt;h2&gt;
  
  
  Journey throughout the phases:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Phase 1:
&lt;/h3&gt;

&lt;p&gt;From the very start, I immediately began to reexamine normal tasks in my daily life and applying coding to them. I thought about how I could store mundane information in arrays and objects, and once spent an hour to sweep a kitchen in terms on functions and event listeners.&lt;/p&gt;

&lt;p&gt;I still believe that this is the most challenging phase. You are presented with something completely new and have essentially re-learn how to think, especially if your someone with no formal STEM education (other than acing physics in high school, thank you Mr. Canafax). I took many notes trying to drill the concepts in my head, but found that I did not use them that much. I freaked out many times, and congratulated myself too early many more times. &lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 2:
&lt;/h3&gt;

&lt;p&gt;Things are still hard, but I found that it is much easier to learn new concepts and immediately apply them.  I wondered why they didn’t introduce React earlier, as it truly makes front end programming easier, and I found myself saying in my head ‘why didn’t they tell me this existed before, this just makes life so much easier and why did I spend all that time learning phase 1 when I could have just been doing this?” A little flawed logic, but if you’re like me you’ll find that half your logic is flawed anyway. &lt;/p&gt;

&lt;p&gt;By this time I really began to know the concepts by heart. I hand-wrote several fetch requests on full sized pieces of paper (I didn’t have sticky notes and forgot Amazon Prime existed). I remember once when I. think it then took me an hour and half of thinking through broom sweeps of my kitchen floor, in terms of increments, setting and updating state, and clearing that state whenever I left the Kitchen. &lt;/p&gt;

&lt;p&gt;My daily remote work and my remote coding bootcamp became a living application itself, and I began to think of each room as a component and how I could pass information between rooms and deciding where shared state should live so to speak (in the living room most often than not).  &lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 3:
&lt;/h3&gt;

&lt;p&gt;This was the most deflating phase for me, as it felt like I had just been taken several steps back. You start with a completely new language (and the syntax and the code just looked ugly to me in my opinion, big gripe there). There are completely new concepts, such as object orientation, SQL, and relationships between back-end data. &lt;/p&gt;

&lt;p&gt;I think I just got frustrated that this phase seemed not be not to be a natural extension of phase 1 and 2, and I often wondered why this information was relevant, especially SQL which still holds a personal grudge. &lt;/p&gt;

&lt;p&gt;But just stick with it, things started to click for me when I learned about Active Record and Active Record Associations. Things will ultimately click during the last module of Web API with Sinatra, and I finally knew why I spent close to two months trudging along. The phase is all just really about the relationship between the front-end and the back-end, and I saw the benefit as I started to work through my project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 4:
&lt;/h3&gt;

&lt;p&gt;I worked through this phase relatively quickly as I finally just committed myself to sit down with the code with nothing else to do, and did so from a small little cabin in the woods (you might not need to go this far, but if you feel that you’re falling behind and not catching up, sometimes extreme measures are warranted). This seemed to balance out anyway, as I took a long break after the curriculum for the holidays and spent a lot of time developing my project. &lt;/p&gt;

&lt;p&gt;This phase goes back to the comfort afforded by phase 2 and the prevailing manta of “Hey, things are still hard, but I’m getting a hang of it a lot better now at least.” The lesson of Model-View-Controller is one of the most important conceptual lessons in the curriculum in my opinion. I had similar thoughts of “wait, we could have just been using Rails this entire time?” Again flawed logic, but I now have a deeper appreciation for both phases 1 and 3. &lt;/p&gt;

&lt;p&gt;As I worked through the rest of the program, I found myself continuously coming back to the lessons in the early part of the curriculum, especially concerning migrations, generators, routing, params, strong params, and error validation. &lt;/p&gt;

&lt;p&gt;Similar to my insanity demonstrated in phase 2 with the oversized fetch requests everywhere, I applied the same with error validation. The fetch requests were replaced with voice memos of the process of the validation. I spent a lot of time in the guides outside of the curriculum and learned much about the roles of each of controller, model, and serializers.  &lt;/p&gt;

&lt;p&gt;I never thought that before starting this phase this would make sense to me…  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rDEGyMzN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uy97ezqai31xyf721rbl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rDEGyMzN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uy97ezqai31xyf721rbl.png" alt="easter egg" width="762" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;.. but it very much does. These lines concern protecting the database from bad data being saved, rejecting that data with an understanding of just when those validations would be checked, the relationship between dependent resources and displaying nested JSON in fetch requests, and having another resource (menu item) exist without having to be assigned to to parent menu resource.  &lt;/p&gt;

&lt;p&gt;I explain data validation in more detail in a previous blog post I wrote &lt;a href="https://dev.to/williamluck/rails-validations-exceptions-and-error-handling-1g1h"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks to the long break I had around the holidays, where I gave myself permission to finally take a rest and revisit these concepts, and because of the relatively slow pace of working on the project once I began, I believe this project review was my strongest. &lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 5:
&lt;/h3&gt;

&lt;p&gt;This is where it all comes together, and it is definetely the scariest phase. It kinda feels like you’re forcibly thrown into the pool, but in contrast to the old analogy, you actually know how to swim this time. The pool just happens to be much larger and deeper than you expect. &lt;/p&gt;

&lt;p&gt;I struggled to come up with an idea of just what to do for this project, and went through several ideas either ruled out by my instructor or myself. But once I got going, the going got, and it seemed natural enough and fitting enough to finish out the program proudly. This phase gave me ideas on the next scary step: the actual job search. As much it was challenging, I found it be a good reflection of just how I could demonstrate all that I’ve learned in the program, and I feel like I can continue to develop the application even after the program ends (which I guess is kinda the point). &lt;/p&gt;

&lt;p&gt;You can check out my phase 5 project &lt;a href="https://github.com/william-luck/blue-rate-tracker"&gt;here.&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  A Send Off
&lt;/h2&gt;

&lt;p&gt;To conclude, I’d like to finish with some of my biggest tips for success in the Flatiron flex program. If you’re thinking about doing it, please take these tips to heart. I like to think that I can now speak with some authority on this. &lt;/p&gt;

&lt;h3&gt;
  
  
  Please Read These:
&lt;/h3&gt;

&lt;p&gt;My biggest tips for any poor soul that stumbles upon this blog post:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Relation to Daily Life:&lt;/strong&gt; No matter the pace, integrate coding into your daily life. You don’t have to code everyday, and I would go so far as to say that could be detrimental. The concepts need time to digest, and proving to yourself the concepts still make sense after some time means that I have learned them, not just memorized them (thank you school tests). Think of how you can think about mundane tasks and chores in terms of JavaScript and Ruby. Say it out loud. Even if people think you are a tad crazy. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Work according to your interests and profession:&lt;/strong&gt; Create projects that are relevant to your interests or work. It makes them much more engaging, and it feels less of a requirement and more of something that you can use. I still use my &lt;a href="https://github.com/william-luck/books-showcase"&gt;phase 2 books application&lt;/a&gt; for my guilty procrastinations. I then moved to creating applications that are more relevant to my work in my &lt;a href="https://github.com/william-luck/traveler-tracker"&gt;phase 3&lt;/a&gt; and &lt;a href="https://github.com/william-luck/camp-management"&gt;phase 4&lt;/a&gt; projects. They loved it, and we are working now  to develop some basic CRM software (sub-contractors in Iraq still use Skype and WhatsApp for important work notifications). My phase 5 project is the most relevant to daily life. I plan to live in Argentina for the remainder of my job search, or until I get something going on my own. The 100% inflation in Argentina wreaks havoc. My local pub has already agreed to start using in some capacity upon completion, and that’s enough of a start for me (but comes with a whole new sense of anxieties).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Connection to others:&lt;/strong&gt; My biggest regret from the program, by either extension of conflicting work schedules, travels, grasping for some semblance of free time, or just plain unwillingness on the false belief that I can do this on my own, led me to not interacting much with other students. Flex students will feel isolated, it’s part of the nature of the program unless there is active effort to not feel that way. I reached out to live students residing in Austin and we had a picnic in the park. That single interaction went a long way knowing that’s actually other human beings experiencing this. You don’t have to meet up, but respond when others are asking about a problem, attend community events, go to office hours. Do what is necessary to feel that connection and shared identity with other students. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Program pacing:&lt;/strong&gt; Truly work at your own pace to the best of your ability. It’s helpful to commit yourself to a pace, but it is not necessary if that creates more stress than it relieves, and if you feel can keep yourself accountable to meet general deadlines you have set for yourself. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Pacing of Projects:&lt;/strong&gt; As an extension of the above, take your time with your projects. Don’t rush it. This is your time to cement your learning and review all the concepts you learned. Do a little each day, not a lot. Even I had no other responsibilities, I think I would struggle heavily completing a project within a week or 10 days. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Accountability:&lt;/strong&gt; If you aren’t in touch much with other students, at least tell others who you trust in your life what you are doing. They can keep you accountable, ask about your progress, and ask about something that you learned. If you’re surrounded by all non-techy people such as myself, this is a really good opportunity to truly explain concepts like they're five. If you can explain it simply, and if they have no coding experience and they can understand it, you’re doing it pretty well (keep in mind these explanations probably won’t work during project reviews and live coding). If somehow the other person is still interested, teach it to them! Maybe you can even perhaps trade Spanish lessons for some basic JavaScript principles, which worked for me until I started to explain things in a way too complex manner, signaling to me that I didn’t really know the concept. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Resources:&lt;/strong&gt; Use other resources outside of the curriculum! The curriculum is not the be-all end-all source of omnipotent knowledge you need to figure problems out. As I advanced through the program, I continuously found the curriculum to be used as a starting point, not the final solution for challenging bugs. Use the resources often included at the the bottom of each lesson. Watch videos. See what others have done and how they fixed it. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Working through bugs:&lt;/strong&gt; Reexamine your relationship with bugs. When starting the program, I thought bugs were a reflection of my poor coding skills. They are not. They can be something as simple as overthinking a concept or simple mistakes in syntax, or they be a strong signal that you are just not understanding a concept all that well. Use your debugging tools, see the values of state as you navigate your applications in the react tools, see how your redux state changes (pro tip, click that ‘diff’ tab and take away approximately 17% of your frustration). &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Permission for yourself:&lt;/strong&gt; The biggest tip I can give is patience, and giving yourself permission to be flexible on your expectations. This program isn’t easy, and it wasn’t meant to be. Take breaks, change the timeline on yours goals accordingly. As part of the flex program, no one is going to tell you that you need to speed up (except perhaps on weeks 50-59, and everyone will tell you on weeks 58-59). There are many success stories of new students completely changing gears and getting jobs in less than a year and having a completely new life. That’s great, but it should not be expected, especially when you have other big factors in your life that deserve attention. The biggest plus of the flex program is that ability to be, well, flexible, and you shouldn’t beat yourself up just for being inflexible.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10. Cheeky note:&lt;/strong&gt; Do your blog posts. More than one per phase. Just do them. Don’t wait until April 29th, 2023 for a March 2022 start date :) &lt;/p&gt;

</description>
      <category>flatiron</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Using Redux Toolkit, and differences with action creators, state updates, and async actions</title>
      <dc:creator>william-luck</dc:creator>
      <pubDate>Sat, 29 Apr 2023 15:43:56 +0000</pubDate>
      <link>https://dev.to/williamluck/using-redux-toolkit-and-differences-with-action-creators-state-updates-and-async-actions-22fc</link>
      <guid>https://dev.to/williamluck/using-redux-toolkit-and-differences-with-action-creators-state-updates-and-async-actions-22fc</guid>
      <description>&lt;p&gt;What are the advantages of using Redux Toolkit? I asked myself this question when I had spent a solid week trying to learn how Redux alone could be used in my applications, and then learned Redux Toolkit, which simplifies mostly everything I learned in the  week previous. &lt;/p&gt;

&lt;p&gt;The most helpful benefits of using the toolkit for me involve mutable state updates, generating action creators automatically, and handling asynchronous fetch requests. There are many more, especially in regard to simplifying syntax and removing much of the boilerplate code to even get Redux up and running, but these three benefits address the most challenging aspects I struggled with in using Redux. &lt;/p&gt;

&lt;h2&gt;
  
  
  Updating state
&lt;/h2&gt;

&lt;p&gt;I will use examples from a &lt;a href="https://github.com/william-luck/blue-rate-tracker"&gt;recent application I developed&lt;/a&gt;, which involves CRUD actions for ingredients, menus, and products as part of my phase 5 project for Flatiron School.&lt;/p&gt;

&lt;p&gt;When I want to add ingredients to the Redux state without the use of the toolkit, I cannot change the state directly, but I have to return the previous form of state with any new additions that override the previous data in my reducer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ingredientsReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ingredientAdded&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the use of the spread operator, I am never mutating state directly, only returning a new form of state to override any changes. &lt;/p&gt;

&lt;p&gt;With the toolkit, I am able to write code that &lt;em&gt;appears&lt;/em&gt; to mutate state (but not actually doing so because of some behinds the scenes toolkit magic, using Immer library):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ingredientsSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ingredients&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="na"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ingredientAdded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The state updates are found under the reducers key in the ingredients slice (using createSlice, which is also specific to the toolkit). Instead of worrying about bug-prone mutable state updates with the use of the spread operator, I can write code that directly appears to push the new ingredient to the state mutably. For emphasis, the toolkit is handling the work behind the scenes to not actually mutate state, but I can write simpler and more digestible code. &lt;/p&gt;

&lt;p&gt;But what is happening above with the created slice and specifying the state and reducers? &lt;/p&gt;

&lt;h2&gt;
  
  
  Generating Action Creators Automatically
&lt;/h2&gt;

&lt;p&gt;Another change in the toolkit is that I no longer have to write out my action creators, and the toolkit handles those processes for me. &lt;/p&gt;

&lt;p&gt;Action creators, without the toolkit, are functions that return an action object for dispatching actions to the store. An alternative of the above above when writing an action creator explicitly would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ingredientAdded&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;ingredient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ingredientAdded&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ingredient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the toolkit, the action creators are generated automatically under the reducers key in the created slice. All we need to do to use them in our application to export them from the 'actions' property of the ingredientsSlice object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ingredientAdded&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;anyOtherReducers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ingredientsSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Asynchronous Actions
&lt;/h2&gt;

&lt;p&gt;When using createSlice, we create an object with keys including name, state (where we store data as normal along with any errors or loading state needed), and reducers (which generate the action creators automatically). Another key we can define is &lt;code&gt;extraReducers&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The difference between the reducers key on the extraReducers is that the reducers key creates those action creator functions and responds to the actions within the reducer. The extraReducers do not create an action creator function, but responds to actions we have defined somewhere else. &lt;/p&gt;

&lt;p&gt;Without the toolkit, we would stick with explicitly defining an action creators and make a fetch requests, and return the type and payload depending on the response from the fetch request itself. But since the fetch requests are asynchronous, and even though we can chain a series of .then()s to the request, any action creators will return the action even though the promise has not resolved:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fetchMenus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;menus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;menus&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;menus&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;fetchMenus&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;menus&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without the toolkit, we would have to import and incorporate redux-thunk middleware by default to avoid this issue, and include it in the index file when creating the store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;thunkMiddleware&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;redux-thunk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;applyMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;thunkMiddleware&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in the action creator, we dispatch actions as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fetchMenus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;menus&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;menusLoading&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;


&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;menus&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;menus&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;menus&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;menusLoaded&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;menus&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Notice that we are not actually returning any actions, but instead a function that dispatches action from the returned function, one for loading status and one for loaded status. &lt;/p&gt;

&lt;p&gt;With the redux toolkit, it becomes simpler. We first create a separate exported function outside of our slice, and call this function directly in react components whenever applicable (such as page load, navigation away from the page, on button click, etc).&lt;/p&gt;

&lt;p&gt;For this example, instead of fetching ingredients, I am fetching menus which I use to load data whenever the application first starts. We use createAsyncThunk provided by the toolkit, and keep the fetch request in a separate function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createAsyncThunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createSlice&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q4TpL77o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w5lfsh05pmxp5l4kg56g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q4TpL77o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w5lfsh05pmxp5l4kg56g.png" alt="fetch request" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then in the extraReducers key, I can handle the loading and loaded status, as well as any updates to state, as such: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8Avkj8Fx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4gutmepk3dx7mif6kqz0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8Avkj8Fx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4gutmepk3dx7mif6kqz0.png" alt="extraReducers" width="698" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are still two different cases for fetching menus, loading and fulfilled. Each changes state, but only fulfilled will update the state to include the menus returned from the fetchMenus function. This removes the need for applying the middleware explicitly, worrying about the promise not resolving before updating state. &lt;/p&gt;

</description>
      <category>redux</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cron Jobs and the Use of Rufus Scheduler Gem</title>
      <dc:creator>william-luck</dc:creator>
      <pubDate>Fri, 28 Apr 2023 20:15:53 +0000</pubDate>
      <link>https://dev.to/williamluck/cron-jobs-and-the-use-of-rufus-scheduler-gem-1ap4</link>
      <guid>https://dev.to/williamluck/cron-jobs-and-the-use-of-rufus-scheduler-gem-1ap4</guid>
      <description>&lt;p&gt;I recently completed a project for my final phase of Flatiron school. It's a software to keep track of the Blue Dollar Rate in Argentina, automatically update prices of food items included on a menu, and recommend pricing. &lt;/p&gt;

&lt;p&gt;The GitHub repo can be found &lt;a href="https://github.com/william-luck/blue-rate-tracker"&gt;here&lt;/a&gt;, and the project is also live at &lt;a href="https://blue-rate-tracker.onrender.com/"&gt;https://blue-rate-tracker.onrender.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This project depends on the use of a scheduler, and I used the &lt;a href="https://github.com/jmettraux/rufus-scheduler"&gt;Rufus Scheduler Gem&lt;/a&gt;. Schedulers were completely new to me when I first started this project, but the gem helped me to understand cron jobs and how they can be used in my applications. &lt;/p&gt;

&lt;p&gt;To update the prices of my menu items, I needed code that could make a call to an API every morning before the business day begins, and update all prices accordingly. I know the code necessary to update the price data, but I was missing code to actually run in the background and update automatically as a background process. &lt;/p&gt;

&lt;p&gt;After installing the gem, I added a scheduler file in under initializers in 'config/initializers/scheduler.rb'. Initializers in Rails help to configure your application, and are ran after the framework and gems are loaded. It is crucial to include the scheduling processes in the initializers because I want to the scheduler to run and be set in place before the actual application starts running, since I want recurrent changes everyday by default. &lt;/p&gt;

&lt;p&gt;In the newly created file, I first require the gem using &lt;code&gt;require 'rufus-scheduler'&lt;/code&gt; and then initiate a Rufus scheduler instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require 'rufus-scheduler'

scheduler = Rufus::Scheduler.new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next I need to write a cron job to execute everyday at a certain time. For the purposes of this application, I want to update the prices everyday at 6:00 AM Argentina Standard Time, which equates to 9:00 AM UTC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scheduler.cron '00 09 * * *' do


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

&lt;/div&gt;



&lt;p&gt;Put simply, cron jobs are used for scheduling certain tasks at a specified date (or time, a in this case). In my futile attempts to follow the installation and setup instructions to get this working, I did not fully understand the cron format in its elusive series of stars, blanks, zeros, and numbers. &lt;/p&gt;

&lt;p&gt;I used &lt;a href="https://crontab.guru/"&gt;Cron Guru&lt;/a&gt; to help me understand the format, where I played with the format until I had a more solid understanding. &lt;/p&gt;

&lt;p&gt;To summarize, the format accepts five digits, each used to specify a different time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first digit accepts a minute, from 0-59. &lt;/li&gt;
&lt;li&gt;The second digit accepts an hour, from 0-23.&lt;/li&gt;
&lt;li&gt;The third digits accepts a day of the month, from 1-31&lt;/li&gt;
&lt;li&gt;The fourth digit accepts a month, from 1-12&lt;/li&gt;
&lt;li&gt;The last digit works a little differently, accepting a day of the week, from 0-6. 0 refers to Sunday, while 6 refers to Saturday. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Asterisks / stars are important to tell the job to completely disregard any specifications to that day, week, or month. But in my case above, I need to specify "00 09 * * &lt;em&gt;', because if otherwise, putting "&lt;/em&gt; 09 * * *" will result in the cron job executing every minute during the 9:00 AM hour (9:00 - 9:59 AM).  &lt;/p&gt;

&lt;p&gt;Other schedules accepted by the Rufus Scheduler include &lt;code&gt;in&lt;/code&gt; and &lt;code&gt;at&lt;/code&gt; jobs, which only trigger once, during a specified time. For example, after initiating a Rufus scheduler instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scheduler.in '12h' do

end

// or

scheduler.at '2023/04/29 16:00:00' do

end

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

&lt;/div&gt;



&lt;p&gt;In each case, the task only executes once, in 12 hours from the time of initialization, and on April 29 at 4:00 PM, respectively. &lt;/p&gt;

&lt;p&gt;More useful jobs concerning my application are &lt;code&gt;every&lt;/code&gt; and &lt;code&gt;interval&lt;/code&gt;, as well as &lt;code&gt;chron&lt;/code&gt;. These tasks trigger repeatedly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scheduler.every '12' do

end

// Or

scheduler.interval '12' do

end

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

&lt;/div&gt;



&lt;p&gt;The difference between every and interval is that interval will immediately execute the task, then repeat those tasks at the specified interval. Every omits the initial trigger, unless specified using &lt;code&gt;first_in&lt;/code&gt; and &lt;code&gt;first_at&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;For example, using &lt;code&gt;first_in&lt;/code&gt;, I could have something as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scheduler.every '12h`, first_in '12h' do

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

&lt;/div&gt;



&lt;p&gt;While the initial trigger is still omitted from &lt;code&gt;every&lt;/code&gt;, I can customize a time to call the first execution. &lt;/p&gt;

&lt;p&gt;I can also use &lt;code&gt;first_in&lt;/code&gt; for the purposes of my application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scheduler.cron '00 09 * * *', first_in: '5d'  do


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

&lt;/div&gt;



&lt;p&gt;My full code for updating the prices of the products in my database looks like this: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vOhCCGBG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mjo34gzgo5pz4nuyd8qu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vOhCCGBG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mjo34gzgo5pz4nuyd8qu.png" alt="code" width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that the cron job accepts an argument &lt;code&gt;|job|&lt;/code&gt;. While I do not have any expanded use of this argument in my application, it comes with useful methods that I can use in conditional logic if there are considerable changes to the blue rate. For example, I can use &lt;code&gt;job.unschedule&lt;/code&gt;, 'job.pause', and &lt;code&gt;job.resume&lt;/code&gt; if there are changes above 10% a day, for example. This is not too common, but there have been recent jumps such as these. This could be useful to temporarily pause the cron tasks until the price stabilizes, as the rate is likely to fall back down after considerable hikes. &lt;/p&gt;

&lt;p&gt;Other useful methods that I could integrate into the application are &lt;code&gt;original&lt;/code&gt;, which returns the cron format of when the updates are scheduled; &lt;code&gt;paused?&lt;/code&gt;, which returns a boolean telling me if the scheduler is active; and &lt;code&gt;count&lt;/code&gt;, which returns the number of times the database has updated since starting. This could be useful to then pause the scheduler for a manual review of any changes to the prices of raw items every quarter, if the prices in markets have either not caught up with or exceeded the blue rate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xp-JocPD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yspgchrhls3ekcq263o2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xp-JocPD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yspgchrhls3ekcq263o2.png" alt="examples" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ruby</category>
      <category>cron</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Rails validations, Exceptions, and Error Handling</title>
      <dc:creator>william-luck</dc:creator>
      <pubDate>Thu, 26 Jan 2023 17:34:43 +0000</pubDate>
      <link>https://dev.to/williamluck/rails-validations-exceptions-and-error-handling-1g1h</link>
      <guid>https://dev.to/williamluck/rails-validations-exceptions-and-error-handling-1g1h</guid>
      <description>&lt;p&gt;What is the difference between .new/.save and .create, as well as their sister methods? (.save! and .create!) When should you use them and how do they relate to the validations in rails? How do you handle exceptions and invalid data when saving to a database? &lt;/p&gt;

&lt;p&gt;This blog post assumes some level of rails validation code present in your models. The simplest of validations is that an attribute has to exist on the instance before saving it to the database. For example, I created an application that has a household (or family) as one of the models. For the household to be created, the only thing that has to be supplied from the user is the address of the household.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fga089djw8x13o0c6qlkx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fga089djw8x13o0c6qlkx.png" alt="Image description" width="624" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can create a new instance of a household using `Household.new’ in the rails console. However, the return value of such is just an empty household instance without any attributes (all having nil values): &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gfag80h5wseai277zvl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gfag80h5wseai277zvl.png" alt="Image description" width="800" height="37"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even though I have the validations for address present in the Household model file, rails still allowed me to create the instance because only database activity triggers the validations. We are not attempting to save the household (yet) to the database. From the return value alone, there is not really a way to see if the instance could be saved to the database with these nil values. We could, however, run &lt;code&gt;Household.valid?&lt;/code&gt; to see if the data is valid: &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gbaeg6zmgrkmwltiz6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gbaeg6zmgrkmwltiz6n.png" alt="Image description" width="800" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The return value of this code is false, which indicates that the data is invalid. If I instead created a separate instance of a household while specifying the address, the data would be valid when saving to the database: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fztdqoyr5sj5t7ax2lsya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fztdqoyr5sj5t7ax2lsya.png" alt="Image description" width="800" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can imagine a use for this boolean return values in your control flow, using conditional statements. In your controller CRUD actions, for example, you could run the &lt;code&gt;.valid?&lt;/code&gt; method before continuing, or return an error otherwise that you could customize to the needs of your application. Continuing on with the two above examples. What will happen if I attempt to save the &lt;code&gt;household&lt;/code&gt; instance to the database? Remember that validations trigger upon database activity, so rails will check for the presence of address. &lt;/p&gt;

&lt;p&gt;Let’s start with the valid data:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdwh1hedlalmer7hiufc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdwh1hedlalmer7hiufc2.png" alt="Image description" width="800" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnqfd62j2jjpet16xebu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnqfd62j2jjpet16xebu.png" alt="Image description" width="800" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rails successfully saved our &lt;code&gt;household&lt;/code&gt; instance to the database, and calling &lt;code&gt;Household.last&lt;/code&gt; in the console will give us our newly created household. In my model, each household can also have a date of entry. However, since I did not include the validations for that attribute in my household model, the instance is still saved successfully in the database. &lt;/p&gt;

&lt;p&gt;For the invalid household instance, when attempting to save it to the database, something else happens: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn4b14q8o461x060l1hru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn4b14q8o461x060l1hru.png" alt="Image description" width="538" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We get a return value of &lt;code&gt;false&lt;/code&gt;. Rails does not give us the reason for the valid data by default without some error handling. Calling &lt;code&gt;household.create&lt;/code&gt; on this instance and using the return value would serve the same purpose as calling &lt;code&gt;household.valid?&lt;/code&gt; for your control flow, but there’s much more room for error, especially if you were expecting the data to be valid and were then calling other methods on this false return value. Unfortunately, with the return value by itself, there’s not much we can tell the user or our program, other than the instance was invalid. &lt;/p&gt;

&lt;p&gt;Having rails throw an exception would be more useful, along with an error message of exactly what went wrong when saving the instance to the database. Exceptions can be raised if we make use of &lt;code&gt;.save!&lt;/code&gt; and &lt;code&gt;.create!&lt;/code&gt; sister methods. &lt;code&gt;.create&lt;/code&gt; and &lt;code&gt;.create!&lt;/code&gt; combine the use of &lt;code&gt;.new&lt;/code&gt; and &lt;code&gt;.save&lt;/code&gt;, where rails attempts to create an instance of the household and save that instance to the database in one go. What happens if we use &lt;code&gt;.create!&lt;/code&gt; for a new household with invalid data (no address supplied)?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbvwceb892p50mt3erhy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbvwceb892p50mt3erhy.png" alt="Image description" width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rails will throw an RecordInvalid exception, along with a useful and simple error message of why the creation was unsuccessful: that the the address cannot be blank. But how do we plan for these errors and exceptions in our code? If we have multiple methods to create and update household data in the households controller, a useful way would be to include a &lt;code&gt;rescue_from ActiveRecord::RecordInvalid&lt;/code&gt; statement at the top of our controller, which would kick in if there are any RecordInvalid exceptions in any method, along with a custom class method to render JSON of the details of that error for our front end: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7nw52yxwk3zq3jo85gc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7nw52yxwk3zq3jo85gc.png" alt="Image description" width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2nu22mbaouu915oml743.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2nu22mbaouu915oml743.png" alt="Image description" width="800" height="65"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using the above code, any time that there is an RecordInvalid exception, the &lt;code&gt;render_invalid_data_error&lt;/code&gt; method will return JSON with some nicely formatted errors to use in the front end. We can obtain an object of the errors in the frontend with &lt;code&gt;invalid.record.errors&lt;/code&gt;, and put those errors in an array with &lt;code&gt;invalid.record.errors.full_messages&lt;/code&gt;: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fim46q8xp2kqoh3jkw04d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fim46q8xp2kqoh3jkw04d.png" alt="Image description" width="800" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the data was valid, my application would have returned JSON of the valid household from the server upon creation. Instead, a RecordInvalid exception was thrown, and the rescue_from statement along with the custom method returned JSON of the error itself, formatted into an array. Moreover, notice the 422 error code (unprocessable entity) returned from the server, which we specified with &lt;code&gt;status: :unprocessable_entity’ in the &lt;/code&gt;render_invalid_data_errors` method. &lt;/p&gt;

&lt;p&gt;These different error codes are helpful for control flow, as we have Javascript in the front end determine if the response was successful, and have our application perform different tasks depending on the error code of the response. For example, if the household creation was successful, I can set state with the details of the newly created household in React, or I could set state for front end error messages otherwise: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsj8isdnzhfi1vad9jktn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsj8isdnzhfi1vad9jktn.png" alt="Image description" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;else&lt;/code&gt; statement, I set state for the errors, which is the array of error(s) returned from the server. I can then display these errors in an alert message to the user, letting them know exactly what wrong, and what to fix in the form data before continuing and being pushed to other areas of the application. &lt;/p&gt;

</description>
      <category>postmark</category>
      <category>llm</category>
      <category>hiring</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Many-to-Many Associations in Active Record Example</title>
      <dc:creator>william-luck</dc:creator>
      <pubDate>Tue, 18 Oct 2022 17:49:25 +0000</pubDate>
      <link>https://dev.to/williamluck/many-to-many-associations-in-active-record-example-285h</link>
      <guid>https://dev.to/williamluck/many-to-many-associations-in-active-record-example-285h</guid>
      <description>&lt;h1&gt;
  
  
  Background
&lt;/h1&gt;

&lt;p&gt;Using Ruby, Active Record, Sinatra, and a React frontend, I created a traveler tracker for travelers in a country at a given time. Users can scroll through a list of all countries, see the number of travelers in that country, select the country for a list of current travelers, and see the individual visits for the traveler in that country. Additionally, users can see the traveler profile, and there are options to add a new traveler or a new visit for an existing traveler: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HDFPFmoL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cx61fm5yc64autsfhazz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HDFPFmoL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cx61fm5yc64autsfhazz.gif" alt="Image description" width="852" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The application makes use of three backend models, Country, Visit, and Traveler. A given country has many travelers, through the visits recorded in that country. Similarly, a traveler has many countries, through visits recorded in each of the countries they visited. Each visit belongs to both a country and a traveler (many-to-many association), and only one can traveler can stay at an an accommodation at a time (which is recorded as a visit):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Country&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;

    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:visits&lt;/span&gt;
    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:travelers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :visits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Traveler&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt; 

    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:visits&lt;/span&gt;
    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:countries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :visits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Visit&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
    &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:country&lt;/span&gt;
    &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:traveler&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Entity Relationship Diagram
&lt;/h1&gt;

&lt;p&gt;When I was thinking of ideas for the relationships needed to build this application, I originally came up with this ERD:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VcQCeLuu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xk3jpotr794zejsa539b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VcQCeLuu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xk3jpotr794zejsa539b.png" alt="Image description" width="880" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Visits are established correctly as the join table, but the Travelers has an unnecessary column as current_country_id, with no association to a country established other than the ID. However, each traveler will have a list of countries they have visited, and you could find the current country of a traveler by just calling &lt;code&gt;#countries[-1]&lt;/code&gt; on an instance of a traveler, as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Traveler&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt; 

    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:visits&lt;/span&gt;
    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:countries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :visits&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;current_country&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;countries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;'from_country_id' is a separate column, and this is used for nationality. I kept this an integer to correspond with the country IDs of the countries table, instead of having to match a nationality string exactly with the country name. We could just find a traveler's nationality by calling &lt;code&gt;#find(#traveler.from_country_id)&lt;/code&gt; on an instance of a country. This leaves us with the following ERD: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n2qBFHXi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bs732cfhf1b81gnog6oz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n2qBFHXi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bs732cfhf1b81gnog6oz.png" alt="Image description" width="880" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Finding travelers currently in a country
&lt;/h1&gt;

&lt;p&gt;While we could easily query which country a given traveler is currently in, it is a bit more difficult to find all the travelers that are currently in a given country. Calling &lt;code&gt;#travelers&lt;/code&gt; on an instance of a country will return all the travelers that were in that country &lt;em&gt;ever&lt;/em&gt;, through the series of visits belonging to each traveler in that country. Similarly, calling &lt;code&gt;#visits&lt;/code&gt; on an instance of a country will return all the visits in that country ever, not necessarily the visits of the travelers currently in that country. We can use the &lt;code&gt;#current_country&lt;/code&gt; method defined above to help with this. &lt;/p&gt;

&lt;p&gt;As calling &lt;code&gt;#travelers&lt;/code&gt; on an instance of a country returns all travelers in that country ever, we can iterate through that array of travelers to see if their last country_id corresponds with the country_id of the country instance. If this is the case, we can push those travelers to a new array, and return that array to get all the travelers currently in that country:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Country&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;

    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:visits&lt;/span&gt;
    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:travelers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :visits&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;travelers_currently_in_country&lt;/span&gt;
        &lt;span class="n"&gt;travelers_in_country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="n"&gt;all_travelers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;travelers&lt;/span&gt;
        &lt;span class="n"&gt;all_travelers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;traveler&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="n"&gt;current_country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;traveler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current_country&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_country&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;
                &lt;span class="n"&gt;travelers_in_country&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;traveler&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="n"&gt;travelers_in_country&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniq&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  How is this used in the application controller?
&lt;/h1&gt;

&lt;p&gt;When I click on a country in the application, we want the travelers in the country to display immediately below the list of countries. I have defined this route in the application controller for get requests to receive JSON of the travelers in a given country, using the above &lt;code&gt;#travelers_currently_in_country&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s1"&gt;'/travelers_in_country/:id'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;selected_country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Country&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;selected_country&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;travelers_currently_in_country&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We make use of the params hash here, so that the route is dynamic and accepts a country ID. The params hash is created when a request is made to that endpoint. As we are not sending any data in a post or patch request, the dynamic id is the only thing that we need to use with the params hash.  We use &lt;code&gt;Country.find(params[:id])&lt;/code&gt; to find the matching country in the database, and then call the &lt;code&gt;#travelers_currently_in_country&lt;/code&gt; method on that country.&lt;/p&gt;

&lt;p&gt;In the frontend, the fetch request looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`http://localhost:9292/travelers_in_country/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;selectedCountry&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;travelersInCountry&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTravelersInCountry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;travelersInCountry&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We pass the ID of the selected country in the url, the application receives the response from the API, and we set state to have the list of traveler's re-render in the frontend. We get an array of objects in this response, and we can then call &lt;code&gt;.map&lt;/code&gt; to return JSX to display the travelers in that country.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ruby</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Tutorial: communication between sibling components using state, and controlled forms</title>
      <dc:creator>william-luck</dc:creator>
      <pubDate>Mon, 18 Jul 2022 23:06:29 +0000</pubDate>
      <link>https://dev.to/williamluck/tutorial-communication-between-sibling-components-using-state-and-controlled-forms-1m77</link>
      <guid>https://dev.to/williamluck/tutorial-communication-between-sibling-components-using-state-and-controlled-forms-1m77</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiasro4o6a8d0ote8r91y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiasro4o6a8d0ote8r91y.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Component hierarchy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parent Component: App.js
... Child component: ExampleForm.js
... Child component: SubmittedFormInfo.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Goal
&lt;/h3&gt;

&lt;p&gt;I have an example form in the child component &lt;code&gt;ExampleForm&lt;/code&gt; to receive input on a name, image url, and a price for a new item. I want this information to immediately be displayed in another child component &lt;code&gt;SubmittedFormInfo&lt;/code&gt;, without the need to refresh the page.   &lt;/p&gt;

&lt;p&gt;Both of these components are children of &lt;code&gt;App&lt;/code&gt;, but information cannot be directly passed between sibling components such as these. How can we take the information from the form, and then immediately display that information in the other component? &lt;/p&gt;

&lt;h3&gt;
  
  
  Walkthrough
&lt;/h3&gt;

&lt;p&gt;This issue depends on the use of state and setter functions passed down as props to each of the components. Since information cannot be directly passed between sibling components, we need to make use of state in the parent component, which will pass down information to each of the two components so that the data can be displayed. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App component&lt;/strong&gt;&lt;br&gt;
Begin by utilizing the useState hook in the &lt;code&gt;App&lt;/code&gt; component, and use an initial value of an empty object, which will eventually contain the information from our example form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;newItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNewItem&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are not too concerned with the actual value of &lt;code&gt;newItem&lt;/code&gt; just yet. Instead, begin by passing down the setter function &lt;code&gt;setNewItem&lt;/code&gt; to the &lt;code&gt;ExampleForm&lt;/code&gt; component. The first goal here is that we want to change the value of &lt;code&gt;newItem&lt;/code&gt; upon form submission using the setter function passed down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ExampleForm&lt;/span&gt; &lt;span class="nx"&gt;setNewItem&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setNewItem&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ExampleForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;setNewItem&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ExampleForm component&lt;/strong&gt;&lt;br&gt;
Before going further, we need to use a controlled form to keep track of the data submitted by the user. For simplicity, declare three initial values as empty strings for each input field on the form using the useState hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ExampleForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;setNewItem&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setImage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPrice&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These will be used as values for each input in the example form, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Image URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For controlled forms, every change that the user makes to the input field should update state to keep track on the information entered by the user. This is especially useful for immediately making use of the information, such as when you want matching items to display in the DOM using a search bar as the user types. Even though we only need this information upon submission, it is still helpful to use a controlled form. To make this form controlled, begin by declaring three separate functions to handle a change to each of the input fields. Within each function, we want to make use of the &lt;code&gt;setName&lt;/code&gt;, &lt;code&gt;setImage&lt;/code&gt;, and &lt;code&gt;setPrice&lt;/code&gt; setter functions from the state in this component. Each function should update state using the event object, to access data on each letter entered to the form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleNameChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleImageChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handlePriceChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To call these functions when the user inputs data, use these functions as callbacks for onChange events in each of the form input fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleNameChange&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Image URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleImageChange&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handlePriceChange&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The general idea is that as the user types, each of these functions will be called to update state. Since we are using state variables as the input values in the form, the form values will update as the state updates with the use of the handle functions. Once the user finishes typing, we will have complete information available to use in each of the &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;image&lt;/code&gt;, and &lt;code&gt;price&lt;/code&gt; state variables.&lt;/p&gt;

&lt;p&gt;When the user submits the form, we want to change the value of newItem declared in &lt;code&gt;App&lt;/code&gt;, using the information entered by the user. We can do this by calling the setter function &lt;code&gt;setNewItem&lt;/code&gt;, which was passed down as a prop to the form component. Begin by declaring a handleSubmit function, which should be called when the user submits the form using onSubmit in the opening form tag. In the handleSubmit function, we want to create a new object, specifying key/value pairs using state variables as each value, as so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then call &lt;code&gt;setNewItem&lt;/code&gt;, using the formData object as the specified value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;setNewItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optionally, we can prevent a refresh of the page and set the form values back to empty strings to receive new data from the user. The final handleSubmit function should look something similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;setNewItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;setImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;setPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The primary line of code to focus on here is &lt;code&gt;setNewItem(formData)&lt;/code&gt;. This updates state in the parent &lt;code&gt;App&lt;/code&gt; component, which allows us to then pass that form data to &lt;code&gt;SubmittedFormInfo&lt;/code&gt; as a child of &lt;code&gt;App&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SubmittedFormInfo component&lt;/strong&gt;&lt;br&gt;
To finally display the form data in our application, in the &lt;code&gt;App&lt;/code&gt; component, pass down &lt;code&gt;newItem&lt;/code&gt; as a prop to &lt;code&gt;SubmittedFormInfo&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SubmittedFormInfo&lt;/span&gt; &lt;span class="nx"&gt;newItem&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newItem&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;newItem&lt;/code&gt; now contains an object with the name, image url, and price of the item added by the user.  Have &lt;code&gt;SubmittedFormInfo&lt;/code&gt; receive the prop, and optionally destructure newItem to more easily use the information contained in the newItem object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SubmittedFormInfo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;newItem&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newItem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All that is left to do is display the name, image, and price variables in the DOM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;Submitted&lt;/span&gt; &lt;span class="nx"&gt;Form&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Image&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/header&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this addition, once the user submits the form, the information entered by the user should now display automatically in the DOM. This occurs because of state updates. Since &lt;code&gt;SubmittedFormInfo&lt;/code&gt; depends on the variable &lt;code&gt;newItem&lt;/code&gt; in state, once the value of &lt;code&gt;newItem&lt;/code&gt; updates, this will cause the &lt;code&gt;SubmittedFormInfo&lt;/code&gt; component to re-render, immediately displaying the information entered by the user. &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;We used &lt;code&gt;newItem&lt;/code&gt; and its setter function to update the application. We began by passing down 'setNewItem' to &lt;code&gt;ExampleForm&lt;/code&gt;, which was called when the user submitted the form. As the user typed, state in the form component updated, keeping track of the values entered by the user. Upon submission, we set the value of &lt;code&gt;newItem&lt;/code&gt; to the data entered by the user. This caused a state update for &lt;code&gt;newItem&lt;/code&gt;, which was passed down to our display container as a prop. This component then re-rendered upon submission, displaying the information entered by the user immediately below the form, with no need to refresh the page. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>Navigating the JavaScript Event Object</title>
      <dc:creator>william-luck</dc:creator>
      <pubDate>Tue, 10 May 2022 19:28:50 +0000</pubDate>
      <link>https://dev.to/williamluck/navigating-the-javascript-event-object-2po8</link>
      <guid>https://dev.to/williamluck/navigating-the-javascript-event-object-2po8</guid>
      <description>&lt;h2&gt;
  
  
  Background:
&lt;/h2&gt;

&lt;p&gt;I just completed phase 1 of Flatiron's Software Engineering Flex program (I was supposed to complete this phase a few weeks ago, but that's the beauty of the flex program). I created a &lt;a href="https://github.com/william-luck/level-up"&gt;single-page application&lt;/a&gt; to keep track of those harder-to-realize accomplishments. The main idea is quite simple: complete tasks, level up corresponding skills, and earn rewards. A task log is located underneath the primary game bar to keep track of tasks completed: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qvr-y-Ib--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fn7bjkhwunsi0h7g3aib.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qvr-y-Ib--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fn7bjkhwunsi0h7g3aib.gif" alt="Image description" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most of this functionality was achieved with the help of event listeners, namely click, submit, and keydown. I relied heavily on the &lt;em&gt;event object&lt;/em&gt; to manipulate the DOM and get my application moving the way I wanted it to.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is the event object?
&lt;/h2&gt;

&lt;p&gt;From my own understanding, the event object is an object created once you satisfy the condition of the event listener. This event object is automatically passed into callback function, and you can access multiple points of useful information through that event object. &lt;/p&gt;

&lt;p&gt;In the callback function itself, define a parameter to receive the event object. The name of the parameter can be really be anything, but by convention and just for ease of use, it's typical to name this parameter "event", or just simply "e". When working with the event object, I find it helpful to just console log the event at the start to remind myself of what I can do with it: &lt;br&gt;
&lt;code&gt;document.addEventListener('click', e =&amp;gt; console.log(e))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Viewing the console, you get a seemingly endless amount of properties, with nested objects under certain keys:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D3RnBa1Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h8t2isnami8jtjmq4t5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D3RnBa1Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h8t2isnami8jtjmq4t5e.png" alt="Image description" width="579" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But of course, the event object generated by clicking on a random location on the page does not tell you much (well it does, but there's no information I'm concerned with at this point). Adding event listeners to specific elements on the page gives much more relevant information to play around with. &lt;/p&gt;
&lt;h2&gt;
  
  
  How I used the event object in my project
&lt;/h2&gt;

&lt;p&gt;For my project, I was primarily concerned with the information in the event object under &lt;code&gt;e.target&lt;/code&gt;. I was looking for the value of the ID attribute in the event object, which I defined in my HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button class='task-button' id="self-comp-1" &amp;gt;Took a break when I needed to&amp;lt;/button&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;button class='task-button' id="self-comp-2" &amp;gt;Used positive affirmations&amp;lt;/button&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;button class='task-button' id="pers-1"&amp;gt;Had an 'aha!' moment &amp;lt;/button&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;button class='task-button' id="pers-2"&amp;gt;All lab tests passing&amp;lt;/button&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;button class='task-button' id="gh-1"&amp;gt;Coded along during a lesson&amp;lt;/button&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;button class='task-button' id="gh-2"&amp;gt;Refactored code&amp;lt;/button&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;button class='task-button' id="supp-1"&amp;gt;Received / gave support on Slack&amp;lt;/button&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;button class='task-button' id="supp-2"&amp;gt;Paired with a technical coach&amp;lt;/button&amp;gt;&amp;lt;br/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using a for loop, I added a "click" event listener to each of eight task buttons on my application. In my callback function, I made use of a series of conditional statements to check the ID of the button that was clicked. If I click on the first button labeled "took a break when I needed to" &lt;code&gt;e.target.id&lt;/code&gt; evaluates to "self-comp-1", and a series of functions will execute from that point to update the corresponding skill of self compassion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (const node of taskButtons) {
    node.addEventListener('click', e =&amp;gt; {
        if ((e.target.id === 'self-comp-1') || (e.target.id === 'self-comp-2')) {
            if (selfCompPercentage &amp;lt; 100) {
                selfCompPercentage = updatePercentage(selfCompPercentageNode, selfCompPercentage, ' - Self Compassion');
                updateProgressBar(selfCompProgressBar, selfCompPercentage);
                addTaskCompleted(e);
            }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the last line of the above code block, I passed the event object to another function, &lt;code&gt;addTaskCompleted(e)&lt;/code&gt;, which updates the task log at the bottom of the page. I needed to do this because I needed to list the text contained in the button that was clicked by the user, like so: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kR3YN-Xq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yanbcgek80kljwzsi14c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kR3YN-Xq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yanbcgek80kljwzsi14c.png" alt="Image description" width="238" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using the same event object that was created when I clicked on the button, I first declared a variable &lt;code&gt;completedTask&lt;/code&gt; to create an element to store the name of the task. And to use the event object passed into the function, I set the &lt;code&gt;textContent&lt;/code&gt; of the &lt;code&gt;completedTask&lt;/code&gt; to &lt;code&gt;e.target.textContent&lt;/code&gt;, which corresponds with the text inside the button originally clicked. Lastly, I added the new element to a &lt;code&gt;completedTasksContainer&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function addTaskCompleted(e) {

    const completedTask = document.createElement('p')
    completedTask.textContent = e.target.textContent;
    completedTasksContainer.appendChild(completedTask)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also in the task log is an ability to add a comment, which also uses an event listener and a separate event object, as part of a 'submit' event. I created a form with a comment bar and a submit button, and then added an event listener upon submission of the simple form, with its own callback function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// creates form next to the completed task
    const inputForm = document.createElement('form')
    inputForm.id = 'input-form'
    completedTask.appendChild(inputForm)

    // Adds comment bar
    const inputText = document.createElement('input')
    inputText.type = 'text'
    inputText.value = ''
    inputText.placeholder = 'Add comment..'
    inputText.id = 'comment'
    inputForm.appendChild(inputText)

    // Adds submit button 
    const submitButton = document.createElement('input')
    submitButton.type = 'submit'
    submitButton.name = 'submit'
    submitButton.value = 'Add'
    inputForm.appendChild(submitButton)

    // Adds comment to task completed upon submission of form
    inputForm.addEventListener('submit', addCommentToTask)    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When adding the comment bar itself, the most important thing to note here is &lt;code&gt;inputText.id = 'comment'&lt;/code&gt;. This allows me to access the text that was entered in the form in my callback function, once again with &lt;code&gt;e.target&lt;/code&gt;, and add that text as a bullet point under the completed task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function addCommentToTask(e) {

    e.preventDefault()

    const comment = e.target.comment.value
    const completedTask = e.target.parentNode  

    e.target.remove()

    const commentNode = document.createElement('ul')
    const commentText = document.createElement('li')
    commentNode.appendChild(commentText)

    commentText.textContent = `Comment: ${comment}`

    completedTask.appendChild(commentNode)
  }  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things to note here: &lt;br&gt;
&lt;code&gt;e.preventDefault()&lt;/code&gt; prevents the page from refreshing upon submission of the form. &lt;br&gt;
&lt;code&gt;const comment = e.target.comment.value&lt;/code&gt; stores the value of the inputted text in a comment variable, using the ID of the comment bar itself.&lt;br&gt;
&lt;code&gt;const completedTask = e.target.parentNode&lt;/code&gt; saves a reference to the task completed, to use a header for an bullet point&lt;br&gt;
&lt;code&gt;e.target.remove()&lt;/code&gt; removes the comment bar and submit button from the task log.&lt;/p&gt;

&lt;p&gt;After adding an unordered list bullet point, I set the text content of the bullet point to the &lt;code&gt;comment&lt;/code&gt; variable with some string interpolation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;commentText.textContent = `Comment: ${comment}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ISyoies---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/18vxencbaf3xedeo9l0r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ISyoies---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/18vxencbaf3xedeo9l0r.png" alt="Image description" width="432" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The third and final event object I worked with was one created by a 'keydown' event. Upon reaching 100% in a skill, a function is called to display an emoji award. I implemented a completely useless but fun feature that allows you to rotate the axe awarded to the user upon completion of the persistence skill. The axe can be rotated plus or minus 45 degrees, depending on whether the left or right arrow is pressed down. To do this, I added a 'keydown' listener to the window (not to the axe itself, because I want the user to be able to rotate the axe at all times if the user has last clicked on the window itself):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function displayAward(node) {
    rewardsTile.textContent = "Earned rewards:"

    if (node.id === 'self-comp-percentage') {
        addHeart();
    } else if (node.id === 'pers-percentage') {
        addAxe();
        window.addEventListener('keydown', rotateAxe)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For 'keydown' events, a different event object is created, which includes the key that was pressed down as a property. Similar to the way I console logged the event object in response to the 'click' event, console logging the event object here leads me toward some conditional logic to use: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7_I-0QGZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2vrg8fhv3pob3qpmskcx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7_I-0QGZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2vrg8fhv3pob3qpmskcx.png" alt="Image description" width="326" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the &lt;code&gt;key:&lt;/code&gt; and &lt;code&gt;"ArrowLeft"&lt;/code&gt; property. Along with the event object automatically passed into the callback function, in which I use 'e' as a parameter in the callback function itself, I toyed with &lt;code&gt;e.key&lt;/code&gt; to determine which direction the axe should rotate, using conditional logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function rotateAxe(e) {
    const axeNode = document.getElementById('axe')

    if (e.key === 'ArrowLeft') {
        axeRotation-=45
    } else if (e.key === 'ArrowRight') {
        axeRotation+=45
    }

    axeNode.style.transform = `rotate(${axeRotation}deg)`
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Note
&lt;/h2&gt;

&lt;p&gt;Event objects are confusing. When I was first introduced to this topic, I couldn't wrap my head around how an object was automatically created and passed into callback functions. How was it passed into the callback function if i didn't explicitly pass it in? Why call it 'e' or 'event'? What is all this information dump that I have to work with? What else can I use in &lt;code&gt;e.target&lt;/code&gt;? These questions are okay, and to not have immediate answers to them is more than okay. I did learn a lot of technical mumbo jumbo through this mini-project, but most importantly, I learned to not be intimidated by the questions that lead to other questions. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>html</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
