<?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: ChristianC93</title>
    <description>The latest articles on DEV Community by ChristianC93 (@christianc93).</description>
    <link>https://dev.to/christianc93</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%2F827432%2Fd3688662-3643-4b9e-98e1-32fc6c24f64a.png</url>
      <title>DEV Community: ChristianC93</title>
      <link>https://dev.to/christianc93</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/christianc93"/>
    <language>en</language>
    <item>
      <title>Leveraging Active Storage for Efficient File Management in a Calorie Tracker Application</title>
      <dc:creator>ChristianC93</dc:creator>
      <pubDate>Mon, 10 Apr 2023 21:42:19 +0000</pubDate>
      <link>https://dev.to/christianc93/leveraging-active-storage-for-efficient-file-management-in-a-calorie-tracker-application-39lb</link>
      <guid>https://dev.to/christianc93/leveraging-active-storage-for-efficient-file-management-in-a-calorie-tracker-application-39lb</guid>
      <description>&lt;p&gt;Active Storage for Efficient File Management in a Calorie Tracker Application&lt;/p&gt;

&lt;p&gt;Active Storage is a powerful and flexible file management solution for Ruby on Rails applications. It facilitates the process of uploading, storing, and processing files by abstracting away the complexities of dealing with various storage services. In my calorie tracker application I incorporated Active Storage in order to manage user uploaded meal images. &lt;/p&gt;

&lt;p&gt;Getting started with active storage begins with running the following command: &lt;br&gt;
rails active_storage:install &lt;br&gt;
This command generates a migration that creates three tables named active_storage_blobs, active_storage_variant_records, and active_storage_attachments. &lt;br&gt;
Next we have to let active storage know where we are storing the user uploaded files. For the purposes of this application I chose local. &lt;br&gt;
config.active_storage.service = :local&lt;/p&gt;

&lt;p&gt;Upon creating my Meal model I added an :image attribute that will represent the user uploaded image.&lt;br&gt;
rails g model meal name, calories, image&lt;br&gt;
In my meal model I now have access to the macro has_one_attached which lets each meal have one file attached to it. &lt;br&gt;
class Meal &amp;lt; ApplicationRecord&lt;br&gt;
   has_one_attached :image&lt;/p&gt;

&lt;p&gt;Next in my Meals Controller I permit the :image attribute in my meals params method,&lt;br&gt;
def meal_params&lt;br&gt;
       params.require(:meal).permit(:name, :calories, :image)&lt;br&gt;
end&lt;/p&gt;

&lt;p&gt;Now that I have the backend setup for meals, I can now create a form in my frontend that accepts an image upload. &lt;/p&gt;

&lt;h1&gt;Add Today's Meals&lt;/h1&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       &amp;lt;form className='form' encType="multipart/form-data" onSubmit={handleSubmit }&amp;gt;
           &amp;lt;div&amp;gt;
               &amp;lt;label htmlFor="name"&amp;gt;Name:&amp;lt;/label&amp;gt;
               &amp;lt;input type="text" id="name" name="name" value={ formData.name } onChange={ handleChange } /&amp;gt;
           &amp;lt;/div&amp;gt;
           &amp;lt;div&amp;gt;
               &amp;lt;label htmlFor="calories"&amp;gt;Calories:&amp;lt;/label&amp;gt;
               &amp;lt;input type="number" id="calories" name="calories" value={ formData.calories } onChange={ handleChange } /&amp;gt;
           &amp;lt;/div&amp;gt;
           &amp;lt;div&amp;gt;
               &amp;lt;label htmlFor="image"&amp;gt;Upload an image:&amp;lt;/label&amp;gt;
               &amp;lt;input type="file" id="image" name="image" accept="image/*" onChange={ handleChange } /&amp;gt;
           &amp;lt;/div&amp;gt;
           &amp;lt;div&amp;gt;
               &amp;lt;input type="submit" value="Add Meal" /&amp;gt;
           &amp;lt;/div&amp;gt;
       &amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now when a user submits the form with an image, it will be automatically associated with the meal using Active Storage. &lt;br&gt;
Here is the handleSubmit function for submitting the form,&lt;br&gt;
const handleSubmit = (e) =&amp;gt; {&lt;br&gt;
       e.preventDefault();&lt;br&gt;
       dispatch(clearErrors());&lt;br&gt;
       const data = new FormData();&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   data.append("meal[name]", e.target.name.value);
   data.append("meal[calories]", e.target.calories.value);


   if (e.target.image.files[0] !== undefined ) {
       data.append("meal[image]", e.target.image.files[0]);
   }

   dispatch(addMeal(data))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Since we are making a post to an API, using the new FormData provides an easy way to handle file uploads without needing to encode the file data manually and packaging it into a format that can be sent to the server using fetch api. &lt;/p&gt;

&lt;p&gt;For my application I want to display these images for the user, however one thing active storage doesn’t do automatically is create urls for the images that can be used as the src for image tags. &lt;/p&gt;

&lt;p&gt;In order to do this, I created a custom method in the meal model,&lt;br&gt;
class Meal &amp;lt; ApplicationRecord&lt;br&gt;
   has_one_attached :image&lt;/p&gt;

&lt;p&gt;has_many :user_meals, dependent: :destroy&lt;br&gt;
   has_many :users, through: :user_meals&lt;/p&gt;

&lt;p&gt;validates :name, :calories, presence: true&lt;br&gt;
   validates :calories, numericality: { only_integer: true }&lt;/p&gt;

&lt;p&gt;def image_url&lt;br&gt;
       Rails.application.routes.url_helpers.url_for(image) if image.attached?&lt;br&gt;
   end&lt;br&gt;
end&lt;/p&gt;

&lt;p&gt;Image_url generates a full url for an attached image if it exists.&lt;br&gt;
If I now take a look at all the meals that are added I can see that there is an image_url key,&lt;br&gt;
  "id": 9,&lt;br&gt;
       "name": "Rice, Spaghetti, and Chicken bites",&lt;br&gt;
       "calories": 850,&lt;br&gt;
       "created_at": "2023-04-04T13:48:23.407Z",&lt;br&gt;
       "image_url": "&lt;a href="http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--2ac2835b2e1a0f3604c23770ab5eff527e690d4c/Rice,%20Spaghetti,%20Chicken.jpg"&gt;http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--2ac2835b2e1a0f3604c23770ab5eff527e690d4c/Rice,%20Spaghetti,%20Chicken.jpg&lt;/a&gt;",&lt;/p&gt;

&lt;p&gt;With that image_url key there I can render the image by using meal.image_url as the src value for an img tag.&lt;/p&gt;

&lt;p&gt;function Meal({ meal }) {&lt;br&gt;
    return (&lt;br&gt;
        &lt;/p&gt;
&lt;br&gt;
            &lt;h2&gt;{meal.name}&lt;/h2&gt;
&lt;br&gt;
            &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dwIE1F1a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/%7Bmeal.image_url%7D" alt="{meal.name}" width="" height=""&gt;&lt;br&gt;
            &lt;p&gt;Date: {new Date(meal.created_at).toLocaleDateString()}&lt;/p&gt;
&lt;br&gt;
            &lt;p&gt;Calories: {meal.calories}&lt;/p&gt;
&lt;br&gt;
        &lt;br&gt;
    )&lt;br&gt;
}

&lt;p&gt;export default Meal;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Rails Bcrypt Gem</title>
      <dc:creator>ChristianC93</dc:creator>
      <pubDate>Tue, 31 Jan 2023 21:44:00 +0000</pubDate>
      <link>https://dev.to/christianc93/rails-bcrypt-gem-2pm</link>
      <guid>https://dev.to/christianc93/rails-bcrypt-gem-2pm</guid>
      <description>&lt;p&gt;Rails’ Bcrypt Gem&lt;/p&gt;

&lt;p&gt;As developers, when we  are making web applications we always dream about other people using them. We think about how users will interact with our applications, and how they will ultimately use it to make their lives better. One important aspect, maybe the most important, is the security of our users. Whenever we make software we must always think about the security of our user’s information. Wrongdoers are always ready to take advantage of applications that have little to no security. When using Rails for the backend of your web application we can use the Bcrypt gem to better protect our user’s password. &lt;/p&gt;

&lt;p&gt;How does Bcrypt work? The bcrypt gem uses a password hashing function that is computationally slow which makes it difficult for malicious hackers to attack our users’ passwords. When a new user signs up for our application bcrypt hashes their password and stores that hash in the database. From that point on when the user wants to login, they input their password, it then gets hashed and compared to the hashed password in the database, and if it matches the hashed password in the database they are then signed in. &lt;/p&gt;

&lt;p&gt;In order to apply this to our rails application we first make sure that our user model has the macro has_secure_password. This macro gives us access to the password and password_confirmation methods as well as the authenticate method. Our user model must also have a password_digest attribute and that is what automatically adds the password and password_confirmation fields to our database. &lt;/p&gt;

&lt;p&gt;class User &amp;lt; ApplicationRecord&lt;br&gt;
   has_secure_password&lt;br&gt;
   validates :username, presence: true, uniqueness: true&lt;br&gt;
end&lt;/p&gt;

&lt;p&gt;def create&lt;br&gt;
       user = User.create!(user_params)&lt;br&gt;
       render json: user, status: :created&lt;br&gt;
   end&lt;/p&gt;

&lt;p&gt;private&lt;/p&gt;

&lt;p&gt;def user_params&lt;br&gt;
       params.permit(:username, :password, :password_confirmation, :image_url)&lt;br&gt;
   end&lt;/p&gt;

&lt;p&gt;Take a look at the user_params method. This method is using strong params to permit username, image_url but also password, and password_confirmation. This is due to the password_digest attribute on the user model. &lt;/p&gt;

&lt;p&gt;Now that the create action is set up we can move on to setting up the login functionality. Think about how this process would work step by step. A user would input their username and password and if the information is correct they are then signed in. &lt;/p&gt;

&lt;p&gt;def create&lt;br&gt;
       user = User.find_by(username: params[:username])&lt;br&gt;
       if user&amp;amp;.authenticate(params[:password])&lt;br&gt;
           session[:user_id] = user.id&lt;br&gt;
           render json: user, status: :created&lt;br&gt;
       else&lt;br&gt;
           render json: { errors: ["Incorrect username or password"] }, status: :unauthorized&lt;br&gt;
       end&lt;br&gt;
   end&lt;/p&gt;

&lt;p&gt;The create action in our sessions controller completes the first step, find a user in our database with the username the user input. If that user exists and their password is authenticated they are then logged in. The authenticate method is doing the final step of checking to see if the password that the user input matches the one in the database. If for whatever reason authentication fails the user will not be logged in and instead will see the error “Incorrect username or password”. &lt;/p&gt;

&lt;p&gt;Now we have everything in place to have users that can sign up, log in and use our applications all with a strong level of security thanks to bcrypt. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>software</category>
      <category>deployment</category>
      <category>caching</category>
    </item>
    <item>
      <title>Keyword Arguments</title>
      <dc:creator>ChristianC93</dc:creator>
      <pubDate>Fri, 18 Nov 2022 23:05:09 +0000</pubDate>
      <link>https://dev.to/christianc93/keyword-arguments-13gl</link>
      <guid>https://dev.to/christianc93/keyword-arguments-13gl</guid>
      <description>&lt;p&gt;Keyword Arguments, What are they? Why should we use them?&lt;/p&gt;

&lt;p&gt;Keyword arguments are a more specific way to pass arguments to a method. They allow you to set parameters as keys and the arguments as the values of those keys, similar to a hash. Take for instance we have a Person class. class Person&lt;br&gt;
  attr_accessor :name, :greeting&lt;br&gt;
 def initialize(name, greeting)&lt;br&gt;
   &lt;a class="mentioned-user" href="https://dev.to/name"&gt;@name&lt;/a&gt; = name&lt;br&gt;
   @greeting = greeting&lt;br&gt;
 end&lt;/p&gt;

&lt;p&gt;def introduction&lt;br&gt;
   puts "#{@greeting} my name is #{&lt;a class="mentioned-user" href="https://dev.to/name"&gt;@name&lt;/a&gt;} "&lt;br&gt;
 end&lt;br&gt;
end&lt;/p&gt;

&lt;p&gt;chris = Person.new("chris", "hi there");&lt;br&gt;
joe = Person.new("hello", "joe");&lt;/p&gt;

&lt;p&gt;Now we see here that Chris instance of the Person class, has a name of “chris” and a greeting of “hi there”. When we call the introduction method it prints out correctly “hi there my name is chris” to the terminal. &lt;br&gt;
However if we move over to the joe instance of this Person class we see that the arguments are in a different order. When we call the introduction method on the joe instance it prints out “joe my name is hello”. This doesn’t make much sense and represents an issue that positional arguments can create. Now this example would be obvious to most people. What if we had a situation where we were instead working with two sets of names, a first and last name.&lt;/p&gt;

&lt;p&gt;class Person&lt;br&gt;
  attr_accessor :first_name, :last_name&lt;br&gt;
 def initialize(first_name, last_name)&lt;br&gt;
   @first_name = first_name&lt;br&gt;
   @last_name = last_name&lt;br&gt;
 end&lt;/p&gt;

&lt;p&gt;def introduction&lt;br&gt;
   puts "Hello #{first_name} #{last_name} is present."&lt;br&gt;
 end&lt;br&gt;
end&lt;/p&gt;

&lt;p&gt;person1 = Person.new("jackson", "harper");&lt;br&gt;
person2 = Person.new("riley", "lincoln");&lt;/p&gt;

&lt;p&gt;Here’s an example where we have two arguments, a first and last name. Person1 is initialized with “jackson” and “harper”, so when we call the introduction method on person1 we get “Hello jackson harper is present.”. However these two names are actually pretty common and can be used interchangeably, so how can we be sure that it’s not supposed to be Harper Jackson? The same can be said for person2 it can either be lincoln riley or riley lincoln. These examples are admittedly contrived but they illustrate the point that using positional arguments isn’t always the best way to handle our arguments. &lt;br&gt;
These shortcomings can be fixed by using keyword arguments. Keyword arguments make it so that we do not have to worry about which order we passed our arguments. &lt;/p&gt;

&lt;p&gt;class Person&lt;br&gt;
  attr_accessor :first_name, :last_name&lt;br&gt;
 def initialize(first_name: , last_name:)&lt;br&gt;
   @first_name = first_name&lt;br&gt;
   @last_name = last_name&lt;br&gt;
 end&lt;/p&gt;

&lt;p&gt;def introduction&lt;br&gt;
   puts "Hello #{first_name} #{last_name} is present."&lt;br&gt;
 end&lt;br&gt;
end&lt;/p&gt;

&lt;p&gt;person1 = Person.new(first_name:"jackson", last_name:"harper");&lt;br&gt;
person2 = Person.new(first_name:"lincoln", last_name:"riley");&lt;br&gt;
person3 = Person.new(last_name:"carter", first_name:"james");&lt;/p&gt;

&lt;p&gt;As we can see now each instance of the person class is now initialized with keyword arguments named first_name and last_name. This makes it clear what information belongs in each argument to not just me but also whomever may be working or looking at my code. If you take a look at person3 you can also see that order does not matter. I initialized person3 by passing in the last name keyword argument first but when we call the introduction method on person3 we still get the information in the right order as it still prints the first name and then the last name. &lt;br&gt;
Keyword arguments are a great tool to use especially when you’re working with Classes. They can be a hint as to what kind of data type each argument is expecting, and it makes it so that you are less prone to inputting the wrong information. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Understanding the component tree and re-renders in React.</title>
      <dc:creator>ChristianC93</dc:creator>
      <pubDate>Tue, 16 Aug 2022 15:30:00 +0000</pubDate>
      <link>https://dev.to/christianc93/understanding-the-component-tree-and-re-renders-in-react-3bpn</link>
      <guid>https://dev.to/christianc93/understanding-the-component-tree-and-re-renders-in-react-3bpn</guid>
      <description>&lt;p&gt;When working in React, it is crucial to understand how your component tree is organized. Usually you would have the top most level component and child components of said top most level component. Many cases the child components would also have their own set of child components as well. Understanding how your component tree is organized is crucial so that you can send the right information to the right components.&lt;/p&gt;

&lt;p&gt;Let’s take, for example, a component hierarchy such as this,&lt;br&gt;
App&lt;br&gt;
|_Header&lt;br&gt;
|_Main Container&lt;br&gt;
  |_SearchBar&lt;br&gt;
  |_StockContainer&lt;br&gt;
  |  |_Stock&lt;br&gt;
  |_PortfolioContainer&lt;br&gt;
     |_Stock&lt;/p&gt;

&lt;p&gt;If, for example, I wanted to send an array of stocks from my App component to my StockContainer component, I could pass that data as props to my MainContainer and again down to the StockContainer. StockContainer could then render those individual stocks by using the Stock component because it now has the relevant data due to my knowledge of the component hierarchy.  &lt;/p&gt;

&lt;p&gt;Another thing to consider regarding the component tree is the relationship between components. If a component returns another component. The component that’s returning is considered a parent and the returned component is considered a child of that component. As seen prior, if we want to send data down to a child component, we use props. If we want to send information up the component tree however, we would need to pass a callback function from the parent component to the child component and invoke it in the child component. &lt;/p&gt;

&lt;p&gt;function App() {&lt;br&gt;
 const [stocks, setStocks] = useState([]);&lt;/p&gt;

&lt;p&gt;useEffect(() =&amp;gt; {&lt;br&gt;
   fetch(" &lt;a href="http://localhost:3001/stocks%22"&gt;http://localhost:3001/stocks"&lt;/a&gt;)&lt;br&gt;
   .then((resp) =&amp;gt; resp.json())&lt;br&gt;
   .then((stocks) =&amp;gt; setStocks(stocks))&lt;br&gt;
 }, [])&lt;/p&gt;

&lt;p&gt;function sortStockByTicker() {&lt;br&gt;
   const sortedStocks = [...stocks].sort((a, b) =&amp;gt; {&lt;br&gt;
     if(a.ticker &amp;lt; b.ticker) { return -1; }&lt;br&gt;
     if(a.ticker &amp;gt; b.ticker) { return 1; }&lt;br&gt;
     return 0;&lt;br&gt;
   })&lt;br&gt;
   setStocks(sortedStocks);&lt;br&gt;
 }&lt;/p&gt;

&lt;p&gt;function sortByPrice() {&lt;br&gt;
   const sortedStocks = [...stocks].sort((a, b) =&amp;gt; {&lt;br&gt;
     if(a.price &amp;lt; b.price) { return -1; }&lt;br&gt;
     if(a.price &amp;gt; b.price) { return 1; }&lt;br&gt;
     return 0;&lt;br&gt;
   })&lt;br&gt;
   setStocks(sortedStocks);&lt;br&gt;
 }&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
   &lt;/p&gt;
&lt;br&gt;
     &lt;br&gt;
     &lt;br&gt;
   &lt;br&gt;
 );&lt;br&gt;
}

&lt;p&gt;function SearchBar({sortByTicker, sortByPrice, onCategoryChange}) {&lt;br&gt;
  return (&lt;br&gt;
   &lt;/p&gt;
&lt;br&gt;
     &lt;strong&gt;Sort by:&lt;/strong&gt;&lt;br&gt;
     &lt;br&gt;
       
         type="radio"&lt;br&gt;
         value="Alphabetically"&lt;br&gt;
         name="sort"&lt;br&gt;
         checked={null}&lt;br&gt;
         onChange={null}&lt;br&gt;
         onClick={sortByTicker}&lt;br&gt;
       /&amp;gt;&lt;br&gt;
       Alphabetically&lt;br&gt;
     &lt;br&gt;
     &lt;br&gt;
       
         type="radio"&lt;br&gt;
         value="Price"&lt;br&gt;
         name="sort"&lt;br&gt;
         checked={null}&lt;br&gt;
         onChange={null}&lt;br&gt;
         onClick={sortByPrice}&lt;br&gt;
       /&amp;gt;&lt;br&gt;
       Price

&lt;p&gt;Passing the callback functions, defined in the App component, down the component tree to the SearchBar component, and binding it to an event to be invoked as a result of a specific user interaction, lets the App component have access to the information the child component has. &lt;/p&gt;

&lt;p&gt;In React, re-renders are triggered due to a change in state or new props being passed to another component. &lt;/p&gt;

&lt;p&gt;function App() {&lt;br&gt;
 const [stocks, setStocks] = useState([]);&lt;/p&gt;

&lt;p&gt;useEffect(() =&amp;gt; {&lt;br&gt;
   fetch(" &lt;a href="http://localhost:3001/stocks%22"&gt;http://localhost:3001/stocks"&lt;/a&gt;)&lt;br&gt;
   .then((resp) =&amp;gt; resp.json())&lt;br&gt;
   .then((data) =&amp;gt; setStocks(data))&lt;br&gt;
 }, [])&lt;/p&gt;

&lt;p&gt;As you can see we have an initial state of an empty array, and after fetching data from the url we set our state to the data we got back from the resolved promise. Our stocks variable can now be passed down as a prop to any component that needs it. &lt;/p&gt;

&lt;p&gt;Let’s say we have rendered all the data from our stocks variable on the page. Each individual stock has an onclick event. This is where knowledge of how re-renders work really helps. We want two things to happen each depending on where in the page the event took place. If the stock was clicked in the StockContainer we want that stock to appear in the PortfolioContainer. If the stock was clicked in the PortfolioContainer we want that stock to be deleted. &lt;/p&gt;

&lt;p&gt;We know we need a separate state for the portfolio because it's going to change. We’re also going to need callback functions in order to communicate to the parent component that there has been a change in the PortfolioContainer and or the StockContainer. &lt;/p&gt;

&lt;p&gt;function MainContainer({stocks, sortByTicker, sortByPrice}) {&lt;br&gt;
 const [portfolio, setPortfolio] = useState([]);&lt;/p&gt;

&lt;p&gt;function handleAddStock(stock) {&lt;br&gt;
   const clickedStock = stocks.find((s) =&amp;gt; s === stock)&lt;br&gt;
   if (portfolio.includes(clickedStock)) {&lt;/p&gt;

&lt;p&gt;} else {&lt;br&gt;
     setPortfolio([...portfolio, clickedStock]);&lt;br&gt;
   }&lt;br&gt;
 }&lt;/p&gt;

&lt;p&gt;function handleRemoveStock(stock) {&lt;br&gt;
   const newPortfolio = portfolio.filter((p) =&amp;gt; p !== stock)&lt;br&gt;
   setPortfolio(newPortfolio);&lt;br&gt;
 }&lt;/p&gt;

&lt;p&gt;function onCategoryChange(e) {&lt;br&gt;
   setCategory(e.target.value);&lt;br&gt;
 }&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
   &lt;/p&gt;
&lt;br&gt;
     &lt;br&gt;
     &lt;br&gt;
       &lt;br&gt;
         &lt;br&gt;
       &lt;br&gt;
       &lt;br&gt;
         &lt;br&gt;
       &lt;br&gt;
     &lt;br&gt;
   &lt;br&gt;
 );&lt;br&gt;
}

&lt;p&gt;MainContainer is the parent to both StockContainer and PortfolioContainer so we set our portfolio state there. We also define our callback functions and pass them to their respective components as props. &lt;/p&gt;

&lt;p&gt;function PortfolioContainer({portfolio, onRemoveStock}) {&lt;br&gt;
  return (&lt;br&gt;
   &lt;/p&gt;
&lt;br&gt;
     &lt;h2&gt;My Portfolio&lt;/h2&gt;
&lt;br&gt;
     {portfolio.map((stock) =&amp;gt; {&lt;br&gt;
       return (&lt;br&gt;
         &lt;br&gt;
       )&lt;br&gt;
     })}&lt;br&gt;
   &lt;br&gt;
 );&lt;br&gt;
}&lt;br&gt;
function StockContainer({stocks, onAddStock, category}) {

&lt;p&gt;const stocksToDisplay = stocks.filter((stock) =&amp;gt; {&lt;br&gt;
   if (category === "") {&lt;br&gt;
     return stocks;&lt;br&gt;
   } else {&lt;br&gt;
     return stock.type === category;&lt;br&gt;
   }&lt;br&gt;
 })&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
   &lt;/p&gt;
&lt;br&gt;
     &lt;h2&gt;Stocks&lt;/h2&gt;
&lt;br&gt;
     {stocksToDisplay.map((stock) =&amp;gt; {&lt;br&gt;
       return (&lt;br&gt;
       &lt;br&gt;
     )})}&lt;br&gt;
   &lt;br&gt;
 );&lt;br&gt;
}

&lt;p&gt;Something neat about a re-render is that a generically named prop like onStockClick can have different values depending on which route down the component tree the information traveled. So for instance if the re-render happened as a result of a change in the StockContainer, onStockClick will have a value of onAddStock. If the re-render happened as a result of a change in the PortfolioContainer onStockClick will have a value of onRemoveStock. &lt;/p&gt;

&lt;p&gt;This was the biggest takeaway for me on how a re-render truly works. The same prop can have a different value depending on where functions or variables are defined in the component tree. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>The first stop in my coding journey-The First Project</title>
      <dc:creator>ChristianC93</dc:creator>
      <pubDate>Thu, 21 Apr 2022 13:33:08 +0000</pubDate>
      <link>https://dev.to/christianc93/the-first-stop-in-my-coding-journey-the-first-project-3no3</link>
      <guid>https://dev.to/christianc93/the-first-stop-in-my-coding-journey-the-first-project-3no3</guid>
      <description>&lt;p&gt;As I began my journey into the coding landscape, I arrived at the point where I would create my first project. After looking through various APIs, I was informed of the PokeAPI. I love Pokemon, so when I saw the PokeAPI, I instantly knew I wanted to use it as well as how I wanted to use it. I have always wanted to build some sort of Pokemon randomizer after seeing many play throughs of Pokemon Randomizer Nuzlockes on youtube. I now had my vision as well as the resources and knowledge I needed to build it. &lt;/p&gt;

&lt;p&gt;First thing I needed of course was a randomizer. Luckily getting a Pokemon was simple, I just had to get the url and select the id at the end of it to get a Pokemon. Since all the id’s are integers I had to have a function that could give me a random number as an integer. I used a function&lt;br&gt;
that was available at MDN, which is a really helpful resource in general, to create my random integers. I attached that function at the end of my fetch url passing in 1 and 809 as my arguments. This allowed me to get random Pokemon from generation 1 to generation 8.&lt;/p&gt;

&lt;p&gt;function randomId(min, max) {&lt;br&gt;
   min = Math.ceil(min);&lt;br&gt;
   max = Math.floor(max);&lt;br&gt;
   return Math.floor(Math.random() * (max - min) + min);&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;function getRandomPokemon() {&lt;br&gt;
   fetch(&lt;code&gt;https://pokeapi.co/api/v2/pokemon/${randomId(1,809)}&lt;/code&gt;)&lt;br&gt;
   .then(resp =&amp;gt; resp.json())&lt;br&gt;
   .then(pokemon =&amp;gt; renderPokemonCard(pokemon))&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;As for what information from the API I wanted to include on the page, the name and image of the Pokemon was obvious. However I thought there was so much more information available to me that would help someone if they did not know some of the Pokemon introduced in later generations. I decided to grab the pokedex number, as well as their typing. Therefore, I created a renderPokemonCard function which would take a Pokemon object as its argument. The renderPokemonCard function would then create html elements for the pokemon’s name, official artwork, pokedex number, and its types. I also added a heart button so that someone could “like” the pokemon if it was one of their favorites. Afterwards, that content would be the html content of the pokemonDiv that was created. Lastly the pokemonDiv would be appended to the pokemonContainer.&lt;/p&gt;

&lt;p&gt;In order to render the Pokemon on the page, I created a function called getRandomPokemon which would make the fetch call, convert the information to a JSON object and pass it to my renderPokemonCard as an argument.&lt;/p&gt;

&lt;p&gt;It was all looking great, however I could not attach an event listener to the heart button. This was because the cards were being created dynamically. I would get an error when I tried grabbing the element before it was rendered on the page. In order to solve this issue, I used event delegation to target the heart button. By using event delegation I was able to attach the event listener to the parent div that was already created. This allowed me to then create my callback function, which would run only when the element matched the condition I had created. Another added benefit of using event delegation was not having to write out code for every heart button that could potentially be rendered. &lt;/p&gt;

&lt;p&gt;function renderPokemonCard(pokemon) {&lt;br&gt;
   const pokemonDiv = document.createElement("div");&lt;br&gt;
   const pokemonCard = ` &lt;br&gt;
   &lt;br&gt;
       &lt;/p&gt;
&lt;h2&gt;${pokemon.name[0].toUpperCase() + pokemon.name.slice(1)}&lt;/h2&gt;
&lt;br&gt;
   &lt;br&gt;
   &lt;br&gt;
   &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--872TwP3e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/%2524%257Bpokemon.id%257D.png" alt="${pokemon.name}" width="" height=""&gt;&lt;br&gt;
   

favorite&lt;br&gt;
   &lt;br&gt;
   &lt;br&gt;
       &lt;p&gt;#${pokemon.id.toString().padStart(3, "0")}&lt;/p&gt;
&lt;br&gt;
   &lt;br&gt;
   ${pokemonTypes(pokemon.types)}&lt;br&gt;
   `&lt;br&gt;
   pokemonDiv.innerHTML = pokemonCard;&lt;br&gt;
   pokemonDiv.addEventListener("mouseover", highlightCard);&lt;br&gt;
   pokemonDiv.addEventListener("mouseout", normalizeCard);&lt;br&gt;
   pokemonDiv.addEventListener("click", getHeartButton);&lt;br&gt;
   pokemonContainer.appendChild(pokemonDiv);&lt;br&gt;
}

&lt;p&gt;To wrap it all up, the last thing I wanted to do was to highlight the card if a user hovered over it. To do this I attached an event listener to the pokemonDiv and used event delegation to target the card and changed its color to a light yellow.&lt;br&gt;&lt;br&gt;
function highlightCard(e) {&lt;br&gt;
   if (e.target.matches(".card")) {&lt;br&gt;
       e.target.style.backgroundColor = "lightyellow";&lt;br&gt;
   }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;function normalizeCard(e) {&lt;br&gt;
   if (e.target.matches(".card")) {&lt;br&gt;
       e.target.style.backgroundColor = "";&lt;br&gt;
   }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Creating this randomizer was such a fun way to really put what I have learned so far to the test. There were moments where I needed to stop myself and refocus because I wanted to add more. I’m sure I’ll go back to this project and update it with all the knowledge I gain as I dive deeper into coding. The journey has only just begun and it’s one I’m sure glad I have decided to take. &lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
