{"id":21404,"date":"2018-04-11T12:15:50","date_gmt":"2018-04-11T09:15:50","guid":{"rendered":"https:\/\/www.webcodegeeks.com\/?p=21404"},"modified":"2018-04-11T10:28:20","modified_gmt":"2018-04-11T07:28:20","slug":"making-dumb-components-smart-refactoring","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/","title":{"rendered":"Making Dumb Components Smart: Refactoring"},"content":{"rendered":"<p>Learning new skills is how we as programmers stay sharp and stay employable. I recently started a gig that gave me an opportunity to learn something new, but I had to develop a few workarounds to learn a new framework and make it do what I needed it to do.<\/p>\n<p>Boilerplate code can help jump-start a project. You can find these starter packages for a variety of different languages and frameworks; they provide many common features of applications and websites, for example, login pages, database connections, and menu structures.<\/p>\n<p>In fact, these packages are fully functional on their own. You, as a developer, just need to build them out to your specifications.<\/p>\n<p>Another great use of these boilerplate code templates is when you are learning a new framework. They provide real-world working examples. However, they usually have a downfall: They can be too basic.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/Making-Dumb-Components-Smart-Refactoring-square-300x300.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-21407\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/Making-Dumb-Components-Smart-Refactoring-square-300x300.png\" alt=\"\" width=\"300\" height=\"300\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/Making-Dumb-Components-Smart-Refactoring-square-300x300.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/Making-Dumb-Components-Smart-Refactoring-square-300x300-150x150.png 150w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/Making-Dumb-Components-Smart-Refactoring-square-300x300-70x70.png 70w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>A popular backend JavaScript framework, MeteorJS (Meteor), recently decided to expand its front-end templating frameworks to include ReactJS (React) and Angular. This was a huge and welcoming change. React is one of the more popular front-end frameworks. It was also a great framework for my new gig, so it was high time that I broadened my skill set by learning this new JavaScript framework.<\/p>\n<p>To help start my learning, I turned to a great resource for Meteor called TheMeteorChef.com. This group published a boilerplate for Meteor\/React projects called <a href=\"https:\/\/github.com\/cleverbeagle\/pup\">Pup<\/a>. It is a great starter application, but like most boilerplate code bases, the interactivity that I needed my application to have wasn\u2019t built in. I had to expand my knowledge of React so that I could satisfy all stakeholders in this project.<\/p>\n<p>I was lucky enough to not only land this gig, but it was small enough that I was able to choose the technology stack. I\u2019ve been developing in Meteor for over a year and have come to really like how quick a working prototype can be up and running. So I jumped at the chance to do this project in Meteor and its new support of React.<\/p>\n<p>Let me tell you how I went about making React\u2019s presentational, or \u201cdumb\u201d components, into React\u2019s \u201csmart\u201d components so that my project would succeed.<\/p>\n<h2>The Difference Between \u201cSmart\u201d and \u201cDumb\u201d Components<\/h2>\n<p>It\u2019s a lot easier to understand what dumb and smart React components are when referring to these unofficial descriptive names.<\/p>\n<p>Dumb components are how your application presents HTML. They\u2019re how your website looks. You feed them some data (via props) and they spit out that formatted data to the browser. They\u2019re not very smart. They\u2019re a one-trick pony. They do their job and go away.<\/p>\n<p>Smart components, on the other hand, are what make your application work. Not only do smart components accept data (via props as well) like dumb components, they also monitor and capture any change in data that has been initiated by the end user.<\/p>\n<p>The real-time monitoring that React would capture includes, for example, updates in an admin section, a change to the product quantity in a shopping cart, or even just clicking on a drop down description box. You use smart components to update databases, keep track of the state of objects, and bind actions to one another.<\/p>\n<p>The following is a very basic, or dumb, component that takes in a value (via props) as an object that contains the year, which is then output in the HTML code. Nothing extraordinary here. It\u2019s a good old-fashioned function.<\/p>\n<pre class=\"brush:php\">  \r\n const Footer = (props) =&gt; {  \r\n  return (\r\n    &lt;div&gt;Footer Info&lt;\/div&gt;\r\n    &lt;div&gt;&amp;copy; 2004 - {props.year}&lt;\/div&gt;\r\n  )\r\n};<\/pre>\n<p>You might recognize this same functionality in the older, although still valid, ES5 JavaScript syntax:<\/p>\n<pre class=\"brush:js\">  \r\n function Footer(props){\r\n  var year = props.year;\r\n  var output = \"\r\n    &lt;div&gt;Footer Info&lt;\/div&gt;\r\n    &lt;div&gt;&amp;copy; 2004 - \" + year + \"&lt;\/div&gt;\";\r\n  return output;\r\n}<\/pre>\n<p>Just because a component is dumb, doesn\u2019t mean it can\u2019t be complex. Here\u2019s an example that not only spits out data fed to it, but it can loop over database records, calculate values, and provide a very slick and functional application. But it is not smart.<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring1.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-21408\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring1.png\" alt=\"\" width=\"720\" height=\"404\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring1.png 720w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring1-300x168.png 300w\" sizes=\"(max-width: 720px) 100vw, 720px\" \/><\/a><\/p>\n<pre class=\"brush:php\">  \r\nconst Output = ({ loading, images, counter, }) =&gt; (\r\n       !loading ? (\r\n          &lt;div&gt;\r\n            &lt;Table responsive&gt;\r\n              &lt;thead&gt;\r\n                &lt;tr&gt;\r\n                  &lt;th \/&gt;\r\n                  &lt;th&gt;Image&lt;\/th&gt;\r\n                  &lt;th&gt;File Name&lt;\/th&gt;\r\n                  &lt;th&gt;Size&lt;\/th&gt;\r\n                &lt;\/tr&gt;\r\n              &lt;\/thead&gt;\r\n              &lt;tbody&gt;\r\n                {images.map(({ _id, fileName, size, src, counter, }) =&gt; {\r\n                  counter++;\r\n                  (&lt;tr key={_id}&gt;\r\n                    &lt;td&gt;{counter}.&lt;\/td&gt;\r\n                    &lt;td&gt;&lt;img src={src}{fileName} \/&gt;&lt;\/td&gt;\r\n                    &lt;td&gt;{fileName}&lt;\/td&gt;\r\n                    &lt;td&gt;{size}&lt;\/td&gt;\r\n                  &lt;\/tr&gt;\r\n                )})}\r\n              &lt;\/tbody&gt;\r\n            &lt;\/Table&gt; : &lt;Alert bsStyle=\"warning\"&gt;No Images&lt;\/Alert&gt;}\r\n          &lt;\/div&gt;\r\n       ) : &lt;Loading \/&gt; );\r\n    )<\/pre>\n<h2>Breaking Down Complex Dumb Components<\/h2>\n<p>So let\u2019s walk through this dumb component and see how it\u2019s more complex than the previous example. Just because it\u2019s a dumb component, doesn\u2019t mean that it\u2019s not useful. Far from it.<\/p>\n<p>This is a prime example of a product page: a list of product attributes retrieved from a database. Now instead of some \u201csmart\u201d interactivity, this type of output would usually link to a product description page where one could actually place the product in a shopping cart, for example.<\/p>\n<p>It\u2019s just a basic function that is fed some data (the \u2018loading&#8217; and \u2018images&#8217; objects) and returns some formatted HTML to the browser\u2019s Document Object Model (DOM), which the end user sees.<\/p>\n<pre class=\"brush:php\">  \r\nconst Output = ({ loading, images, counter, }) =&gt; {}<\/pre>\n<p>The name of this function is \u2018Output&#8217; and the values within the \u2018loading&#8217; (typically a Boolean), \u2018images&#8217; (an array of objects), and counter (a number) objects are passed to the function so that they can be placed in the HTML that is returned. Collectively, these inputs are referred to as \u2018props&#8217; in the React framework vernacular. This is the ES6 syntax for a function, sometimes called a \u201cfat arrow function.\u201d In the old way of ES5, it would be written as:<\/p>\n<pre class=\"brush:php\">  \r\nfunction Output(loading, images, counter) {}<\/pre>\n<p>The first parameter being passed into the function is the \u2018loading&#8217; object. This is a pretty common design pattern. As your application is loading this view, or page, it\u2019s making an asynchronous call to the database to fetch all of the image data and package it up in a nice array of objects.<\/p>\n<p>This page\/view\/component is also retrieving all of the images and other elements to display on the page. While this action is happening, \u2018loading=true&#8217;, which tells your application that it doesn\u2019t have all of the necessary building blocks of your current page\/view\/component.<\/p>\n<p>Therefore, display a spinner until it has all of the information, at which point the \u2018Loading Component&#8217; (&lt;Loading \/&gt;) changes the value of \u2018loading&#8217; from true to false (it\u2019s up to you to determine if you should use <a href=\"https:\/\/awesomeautomation.com\/blog\/2-minute-tool-tip-spinner-or-progress-bar\">a percentage progress bar or a plain spinner<\/a>).<\/p>\n<p>The second parameter, or prop, passed to the function is the \u2018images&#8217; object, which, as noted, is an array of objects that was returned from the database. These could be products, comments, blog posts, or any list of items that have the same data structure. Let\u2019s check out what this data might look like.<\/p>\n<h3>Retrieving and Displaying Database Records<\/h3>\n<p>Each object contains a unique database record identifier (_id), a name for the image file (fileName), the size of the image, in bytes (size), and the Universal Resource Identifier (URI) where the image can be accessed over the internet (src).<\/p>\n<pre class=\"brush:php\">  \r\nimageObject1 = {\r\n       _id: 01,\r\n       fileName: 'MyImage.jpg',\r\n       size: 168,\r\n       src: 'http:\/\/example.com\/images\/',\r\n    }  \r\n    \r\n    imageObject2 = {\r\n      _id: 02,\r\n      fileName: 'AnotherImage.png',\r\n      size: 1450,\r\n      src: 'http:\/\/imgfiles.net\/',\r\n    }<\/pre>\n<p>Those are two objects containing individual image data. It\u2019s probably coming from a database call in a different function, which will take all of the resultant database objects and \u201cgroup\u201d them into an array, which is then passed into our \u2018Output&#8217; function.<\/p>\n<pre class=\"brush:php\">  \r\n\/\/ database call which returns the `images` object which contains an array of objects\r\n    images: ImagesCollection.find().fetch()<\/pre>\n<p>Or you could create the array manually. You\u2019ll see manually created database objects in many boilerplate frameworks, because their creators don\u2019t hook up a database and provide filler data for various, albeit in my opinion, bogus, reasons. This shortcut can be very frustrating when you are trying to learn a <a href=\"https:\/\/simpleprogrammer.com\/top-10-programming-languages-learn-2018-javascript-c-python\/\">new language<\/a> or framework.<\/p>\n<p>So, if you see something like the code below, it\u2019s usually because there\u2019s no database connected.<\/p>\n<pre class=\"brush:php\">  \r\nimages = [];\r\nimages.push(imageObject1);\r\nimages.push(imageObject2);<\/pre>\n<p>Both results provide the function of an array looking like this:<\/p>\n<pre class=\"brush:php\">  \r\n    images = [\r\n      { _id: 01, fileName: 'MyImage.jpg', size: 168, src: 'http:\/\/example.com\/images',}\r\n      { _id: 02, filename: 'AnotherImage.png', size: 1450, src: 'http:\/\/imgfiles.net\/',}\r\n    ];<\/pre>\n<p>If you wanted to access each database record, or object, you could call each like:<\/p>\n<pre class=\"brush:php\">  \r\nlet imageName1 = images[0].fileName;\r\nlet imageName2 = images[1].fileName;<\/pre>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/t-1-300x300.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-21409\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/t-1-300x300.png\" alt=\"\" width=\"300\" height=\"300\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/t-1-300x300.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/t-1-300x300-150x150.png 150w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/t-1-300x300-70x70.png 70w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nThe third prop passing to the \u2018Output&#8217; function is \u2018counter&#8217;. This prop is just a number, in this case, a zero. There are other, more elegant ways to count the iterations of a loop, but for illustrative purposes, it is included so that I can show how a dumb component can still do advanced procedures.<\/p>\n<p>So now we know what data to expect when the function is called and its output returned and rendered by the DOM. When we refactor this dumb component into a smart container, we\u2019ll use the same data, but enhance what the component can do as well as what the component allows the end user to accomplish with a better User Experience (UX).<\/p>\n<p>Now that the function has the data, let\u2019s use the \u2018loading&#8217; variable and see if we should show the HTML output or the spinner. This is an if-else shorthand statement in the form of:<\/p>\n<p>condition ? if true do this : if false do this<\/p>\n<p>x == 2 ? \u2018Yes\u2019 : \u2018No\u2019;<\/p>\n<p>We\u2019ll read it as: \u201cnot loading,\u201d is this true or false?<\/p>\n<pre class=\"brush:php\">  \r\n!loading ? (<\/pre>\n<p>This syntax might make a bit more sense in the more verbose ES5 syntax: If the database has returned the dataset, show it; otherwise, show the spinner.<\/p>\n<pre class=\"brush:php\">  \r\n\/\/ Old ES5 syntax\r\n    if( loading === false ) {\r\n     return (\r\n        \/\/ HTML\/JSX output here with database contents\r\n      )\r\n    } else {\r\n      return &lt;Loading \/&gt;\r\n    }<\/pre>\n<h2>Dumb Output<\/h2>\n<p>So now that the function has some parameters to work with, let\u2019s start to construct the HTML (or in this case, JSX, React\u2019s XML preprocessor to JavaScript) to output to the DOM for rendering. If we can understand how this dumb output works, our process for converting to a smart container will be much easier.<\/p>\n<p>The code has some basic Bootstrap \u2018&lt;table&gt;&#8217; tags (actually, the table is a ReactJS component, as identified by the capitalized word). Then common HTML \u2018&lt;tr&gt;&#8217; and header tags \u2018&lt;th&gt;Original File Name&lt;\/th&gt;&#8217;, etc.<\/p>\n<p>Then comes the database output. This code is pretty typical and not unique to React; it just outputs one database record per row. There are many ways in the older ES5 JavaScript syntax to iterate through a set of database records (\u2018for&#8217;, \u2018while&#8217; etc.), but in ES6, we use the \u2018map()&#8217; method.<\/p>\n<pre class=\"brush:php\">  \r\n{images.map( ({_id, fileName, size, src, }) =&gt; ()\r\n   \/\/ HTML\/JSX here\r\n)};<\/pre>\n<p>This section of code is pretty important for this function. It tells the JavaScript engine in your browser that you are going to loop over a set of database records. The outermost curly-brackets \u2018{}&#8217; denote that this is dynamic code.<\/p>\n<p>Let\u2019s take the \u2018images&#8217; object that was passed into our function and deconstruct it\u2014we are going to pull out the individual data points (_id, fileName, size, src) from each object (imageObject1, imageObject2, etc.) in the array. We can then use these as output in the HTML\/JSX.<\/p>\n<pre class=\"brush:php\">  \r\n  {images.map( ({_id, fileName, size, src, }) =&gt; {\r\n      counter++;\r\n      (&lt;tr key={_id}&gt;\r\n        &lt;td&gt;{counter}.&lt;\/td&gt;\r\n        &lt;td&gt;&lt;img src={src}{fileName} \/&gt;&lt;\/td&gt;\r\n        &lt;td&gt;{fileName}&lt;\/td&gt;\r\n        &lt;td&gt;{size}&lt;\/td&gt;\r\n      &lt;\/tr&gt;\r\n      ) }\r\n    }<\/pre>\n<p>This dynamic \u2018&lt;tr&gt;&#8217; block within the \u2018map()&#8217; method will be output to the DOM once for every record returned from that database within the result set \u2018images&#8217;.<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring2.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-21410\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring2.png\" alt=\"\" width=\"720\" height=\"404\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring2.png 720w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring2-300x168.png 300w\" sizes=\"(max-width: 720px) 100vw, 720px\" \/><\/a><\/p>\n<h2>That\u2019s Great, But You Can\u2019t Interact With It (It\u2019s Dumb)<\/h2>\n<p>Now that we fully understand what this dumb component does, let\u2019s think for a moment about what it doesn\u2019t do.<\/p>\n<p>Why do we output a simple table with rows and columns? To convey information, right?<\/p>\n<p>Think baseball scores; stock equity data; warehouse inventory. Now, how often do we just ingest that data? Don\u2019t we want to watch that game? Trade that stock? Update the inventory with a new shipment?<\/p>\n<p>Most of the time, you\u2019d like to offer CRUD (Create, Read, Update, Delete) methods for each row so that end users can interact with the data. Today\u2019s technologies allow end users the ability to be more productive, and web technologies are no different.<\/p>\n<p>Ten years ago, all of the interactivity had to take place on the server, so you\u2019d click a product from a list, and that would tell the server to send a product detail page to the browser where the user could then put the product in their shopping cart. Modern web technologies have the ability to go to the product detail page like before, but now we can also just add it to the shopping cart right from the listing page. That\u2019s more complex, and smart.<\/p>\n<h2>Let\u2019s Make This Component Smart!<\/h2>\n<p>I needed to have my rows of image data to be acted upon by the end user. Rows would need to be deletable, but there is also a date field that the user could alter.<\/p>\n<p>Here\u2019s a screenshot of the User Interface (UI). There\u2019s a simple Delete button that upon clicking, will, obviously, delete the row from the database.<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring3.png\"><img decoding=\"async\" class=\"aligncenter wp-image-21411\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring3.png\" alt=\"\" width=\"860\" height=\"244\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring3.png 1600w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring3-300x85.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring3-768x218.png 768w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/refactoring3-1024x291.png 1024w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>The design specs required the date to be displayed as text and not in an \u2018input&#8217; box (see first row). To indicate that it could be edited, a pencil icon would be clickable and turn the text into an \u2018input&#8217; tag that could then be editable (see the second row, and note that the pencil icon is replaced with a clickable check mark that would submit the changed date).<\/p>\n<p>The code for the Delete button is relatively easy. You just need to associate the unique row identifier, in many cases the database record number, with the \u2018onClick&#8217; event.<\/p>\n<pre class=\"brush:php\">  \r\n{images.map( ({_id, fileName, size, src, }) =&gt; (\r\n  &lt;tr key={_id}&gt;\r\n    &lt;td&gt;&lt;img src={src}{fileName} \/&gt;&lt;\/td&gt;\r\n    &lt;td&gt;{fileName}&lt;\/td&gt;\r\n    &lt;td&gt;{size}&lt;\/td&gt;\r\n    &lt;td&gt;&lt;Button onClick={() =&gt; handleDelete(_id)} &gt; Delete &lt;\/Button&gt;&lt;\/td&gt;\r\n  &lt;\/tr&gt;\r\n) }<\/pre>\n<p>When the Button component (&lt;Button \/&gt;) is clicked, it calls a new function, \u2018handleDelete()&#8217;, which actually does the deleting from the database.<\/p>\n<pre class=\"brush:php\">  \r\n const handleDelete = (imageId) =&gt; {\r\n  if (confirm('Are you sure? This is permanent!') ) {\r\n    \/\/ call to database to delete and catch any errors\r\n    try {\r\n      images: ImagesCollection.remove(imageId);\r\n    } catch (exception) {\r\n      throw new Error('500', exception);\r\n    }\r\n  }\r\n}<\/pre>\n<p>Notice that by adding the functionality of the Delete button, we\u2019ve started our refactoring of the dumb component. This action is \u201csmart\u201d because we are binding the action of the Delete button to the function that does something: tells the database to remove a record.<\/p>\n<p>Recall our definition of a smart container: code that makes your application work. It\u2019s doing something. It\u2019s deleting a record.<\/p>\n<p>To be honest, this functionality was included in the boilerplate code. It\u2019s not that hard, you\u2019re just having your code call another function that talks to the database and gives some feedback to the user upon completion, like an alert box.<\/p>\n<h3>Enhancing End-User Experience<\/h3>\n<p>Now, let\u2019s step it up a notch. When we click on a button (the pencil icon), we\u2019re not going to talk to the database from some other abstracted piece of code; instead, we are altering the DOM, what the end user sees right then and there.<\/p>\n<pre class=\"brush:xml\">  \r\n&lt;tr key={_id}&gt;\r\n  &lt;td&gt;&lt;img src={src}{fileName} height=50\" \/&gt; {fileName}&lt;\/td&gt;\r\n  &lt;td&gt;{src}&lt;\/td&gt;\r\n  &lt;td&gt;{createdAt}&lt;\/td&gt;\r\n  &lt;td&gt;{deleteDate}\r\n    { this.state.editDate \r\n    ? &lt;FontAwesomeIcon icon={faPencilAlt} onClick={() =&gt; this.changeFontAwesome()} \/&gt;\r\n    : &lt;span&gt;\r\n       &lt;DatePicker\r\n          onChange={(event) =&gt; this.handleDateChange(event)}\r\n          selected={moment(this.state.startDate)}\r\n       \/&gt; &lt;FontAwesomeIcon icon={faCheckCircle} onClick={() =&gt; this.saveNewDeleteDate()} \/&gt;&lt;\/span&gt; }\r\n  &lt;\/td&gt;\r\n  &lt;td&gt;&lt;Button bsStyle=\"danger\"\r\n         onClick={() =&gt; this.handleRemove(_id)}\r\n         Block\r\n      &gt; Delete &lt;\/Button&gt;\r\n  &lt;\/td&gt;\r\n&lt;\/tr&gt;<\/pre>\n<p>There\u2019s a bit of noise in the above code snippet, but it\u2019s just the same dynamic &lt;tr&gt; block that we\u2019ve been using to output a row of the database result. What we added are two icons (Font Awesome Pencil and CheckCircle). A basic if-then shorthand statement (\u2018this.state.editDate ? x : y&#8217;) separates them and determines which to show.<\/p>\n<p>\u2018this.state.editDate&#8217; is a \u201csmart\u201d way to keep track of what\u2019s happening in your application. It\u2019s called State. Basically, it\u2019s a session variable. \u2018editDate&#8217; is initialized with \u2018false&#8217; because the date is not being edited. Notice in the Pencil icon component, there is an \u2018onClick&#8217; event that calls the function \u2018changeFontAwesome()&#8217;, which changes this state.<\/p>\n<pre class=\"brush:php\">  \r\nchangeFontAwesome() {\r\n \tthis.setState({ editDate: !this.state.editDate });\r\n}<\/pre>\n<p>Behind the scenes, built into the React Framework, this \u201csmart\u201d component will notice that the value changed, because it\u2019s listening for all sorts of changes. The component will then re-evaluate the if-then shorthand statement and show the \u2018then&#8217; statement based on the new value (\u2018true&#8217;).<\/p>\n<p>So in the code above, the appearance of the row changes from looking like the top row with the Pencil icon, to the second row with the \u2018input&#8217; text box and CircleCheck icon.<\/p>\n<p>In addition to the change in the Font Awesome icon, we\u2019ve enhanced the \u2018input&#8217; box to show a calendar (\u2018&lt;DatePick \/&gt;&#8217;) when it has focus, to aid in changing the date. This is a pretty common enhancement in applications today.<\/p>\n<p>I saved this code and ran the application. It looked great. All of the date fields were displayed as text, and each had a pencil icon next to it. But then, guess what happened?<\/p>\n<p>I clicked on the pencil and all of the dates changed over to \u2018input&#8217; boxes\u2014not just the row I\u2019d clicked on. Ugh. Makes sense in hindsight. The \u2018changeFontAwesome()&#8217; function wasn\u2019t bound to any specific row. It didn\u2019t know which row to target, which row to change. Not what the specs called for. I really needed a \u201csmarter\u201d component so it would know which pencil was clicked and, therefore, which \u2018input&#8217; box to show.<\/p>\n<h2>Refactoring Into Self-Contained Smart Code<\/h2>\n<p>One of the nice aspects of modern day frameworks is the tendency to create small chunks of code that do one thing, and only one thing. Like this code\u2019s \u2018handleDelete()&#8217; function.<\/p>\n<p>As we\u2019ve been refactoring our dumb component, we\u2019ve been adding more functionality. Our code base is doing more than one thing, more than just outputting database rows. We\u2019re deleting rows and changing dates.<\/p>\n<p>So what are we going to do? Let\u2019s have our \u2018Output&#8217; component handle the non-dynamic output. It\u2019ll contain all of the HTML that sets up the &lt;Table \/&gt;. And then, between the &lt;tbody&gt; tags where the dynamic database rows would go, we\u2019ll call a new function (&lt;CustomRow \/&gt; Component) that deals with just one row of data.<\/p>\n<pre class=\"brush:php\">  \r\n &lt;tbody&gt;\r\n  {images.map(({ _id, fileName, createdAt, src, deleteDate, }) =&gt; (\r\n       &lt;CustomRow id={_id} key={_id}\r\n          fileName={fileName}\r\n          createdAt={createdAt}\r\n          url={src}\r\n          deleteDate={deleteDate}\r\n       \/&gt;\r\n  ))}\r\n&lt;\/tbody&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/Refactoring-Into-Self-Contained-Smart-Code-300x300.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-21412\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/Refactoring-Into-Self-Contained-Smart-Code-300x300.png\" alt=\"\" width=\"300\" height=\"300\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/Refactoring-Into-Self-Contained-Smart-Code-300x300.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/Refactoring-Into-Self-Contained-Smart-Code-300x300-150x150.png 150w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/04\/Refactoring-Into-Self-Contained-Smart-Code-300x300-70x70.png 70w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nThis is still the same dynamic &lt;tr&gt; tag within the \u2018map()&#8217; method that we\u2019ve been dealing with. We\u2019ve just abstracted it out to its own code base. This new snippet is much easier to read: We have a loop going over a database record set and passing the values to a component called CustomRow, which would seem like it would return a row of data (which it does).<\/p>\n<p>All of that code that we moved remained the same. We just moved it. A nice benefit is that code in the CustomRow component is now self-contained.<\/p>\n<p>So what now, you ask? Well now, when we click on the Pencil icon, there\u2019s only one possible &lt;FontAwesome \/&gt; component to change, because the &lt;CustomRow \/&gt; component doesn\u2019t know about any other rows, just the one row with the one &lt;FontAwesome \/&gt; component to change.<\/p>\n<p>Even though this component is called many times over, each output is self-contained. Yay.<\/p>\n<h2>Housekeeping and Final Steps<\/h2>\n<p>Let\u2019s finish this refactoring. Recall that the \u2018handleDelete()&#8217; function we called, which was outside of the \u2018Output&#8217; function, made this component \u201csmart.\u201d Since the &lt;CustomRow \/&gt; component is self-contained, we\u2019ll need to move any functions that do something on a row, into the &lt;CustomRow \/&gt; component.<\/p>\n<p>A common way to group the functions, which is now available with ES6 syntax, is to convert the component to a Class. This is the final step in making a smart container. A Class allows all of the interior functions and components to easily talk to each other, pass data around, get and set things (getters\/setters), and keep track of State.<\/p>\n<h2>Now That\u2019s a Smart Component<\/h2>\n<p>Refactoring a dumb component into a smart one isn\u2019t too difficult once you understand the differences between the two. There are some boilerplate sections that are needed, like custom methods and functions that add functionality as well as keep track of props and state, for example.<\/p>\n<p>Expanding your skill set can be very frustrating when tools and learning aids don\u2019t go into enough explanation. I know that when I tried to make a boilerplate code base fit my project, the basic explanation wasn\u2019t enough for me.<\/p>\n<p>Going through the exercise I outlined above helped me complete my new project and learn a lot more about how React keeps your complex codebase simpler without sacrificing UX.<\/p>\n<p>If you\u2019re looking to expand <a href=\"https:\/\/simpleprogrammer.com\/honestly-evaluating-your-skills\/\">your skills<\/a>, learn a new framework. And if you\u2019re looking to turn dumb components into smart ones, I hope my experience helps you find your way, too.<\/p>\n<p>If you are interested in the full before and after code bases, please visit these Github Gists:<\/p>\n<p>Before, Dumb Component (link 1).<\/p>\n<pre class=\"brush:xml; wrap-lines:false\"> \r\n const Output = ({ loading, images, counter, }) =&gt; (\r\n       !loading ? (\r\n          &lt;div&gt;\r\n            &lt;Table responsive&gt;\r\n              &lt;thead&gt;\r\n                &lt;tr&gt;\r\n                  &lt;th \/&gt;\r\n                  &lt;th&gt;Image&lt;\/th&gt;\r\n                  &lt;th&gt;File Name&lt;\/th&gt;\r\n                  &lt;th&gt;Size&lt;\/th&gt;\r\n                &lt;\/tr&gt;\r\n              &lt;\/thead&gt;\r\n              &lt;tbody&gt;\r\n                {images.map(({ _id, fileName, size, src, counter, }) =&gt; {\r\n                  counter++;\r\n                  (&lt;tr key={_id}&gt;\r\n                    &lt;td&gt;{counter}.&lt;\/td&gt;\r\n                    &lt;td&gt;&lt;img src={src}{fileName} \/&gt;&lt;\/td&gt;\r\n                    &lt;td&gt;{fileName}&lt;\/td&gt;\r\n                    &lt;td&gt;{size}&lt;\/td&gt;\r\n                  &lt;\/tr&gt;\r\n                )})}\r\n              &lt;\/tbody&gt;\r\n            &lt;\/Table&gt; : &lt;Alert bsStyle=\"warning\"&gt;No Images&lt;\/Alert&gt;}\r\n          &lt;\/div&gt;\r\n       ) : &lt;Loading \/&gt; );\r\n    )<\/pre>\n<p>After, Smart Component (link 2).<\/p>\n<pre class=\"brush:xml\">  \r\nimport React from 'react';\r\nimport PropTypes from 'prop-types';\r\nimport { Table, Alert, Button } from 'react-bootstrap';\r\nimport { Meteor } from 'meteor\/meteor';\r\nimport { withTracker } from 'meteor\/react-meteor-data';\r\nimport UploadsCollection from '\/api\/Uploads\/Uploads'; \/\/ mongo schema\r\nimport DatePicker from 'react-datepicker';\r\nimport 'react-datepicker\/dist\/react-datepicker.css';\r\n\r\nimport Loading from '..\/..\/components\/Loading\/Loading';\r\nimport FontAwesomeIcon from '@fortawesome\/react-fontawesome';\r\nimport { faPencilAlt } from '@fortawesome\/fontawesome-pro-light';\r\nimport { faCheckCircle } from '@fortawesome\/fontawesome-pro-light';\r\nimport { faTimesCircle } from '@fortawesome\/fontawesome-pro-light';\r\n\r\nimport '.\/Images.scss';\r\n\r\nclass Images extends React.Component {\r\n  constructor(props){\r\n      super(props);\r\n  }\r\n\r\n  render(){\r\n    let { loading, match, images, history } = this.props;\r\n    return(\r\n      &lt;CollectionDisplay\r\n        loading={loading} match={match} images={images} history={history}\r\n      \/&gt;\r\n    )\r\n  }\r\n}; \/\/ end class\r\n\r\nclass CollectionDisplay extends React.Component {\r\n  constructor(props) {\r\n    super(props);\r\n  }\r\n\r\n  render(){\r\n    let { loading, match, images, history, state, onDeleteClick, } = this.props;\r\n    return (\r\n        &lt;div className=\"Images\"&gt;\r\n          {images.length ?\r\n            &lt;Table responsive&gt;\r\n              &lt;thead&gt;\r\n                &lt;tr&gt;\r\n                  &lt;th&gt;Original File Name&lt;\/th&gt;\r\n                  &lt;th&gt;URL Link&lt;\/th&gt;\r\n                  &lt;th&gt;Created&lt;\/th&gt;\r\n                  &lt;th&gt;Delete&lt;\/th&gt;\r\n                  &lt;th \/&gt;\r\n                  &lt;th \/&gt;\r\n                &lt;\/tr&gt;\r\n              &lt;\/thead&gt;\r\n              &lt;tbody&gt;\r\n                {images.map(({\r\n                  _id, originalFilename, createdAt, url, deleteDate,\r\n                }) =&gt; (\r\n\r\n                 &lt;CustomRow id={_id} key={_id}\r\n                  originalFilename={originalFilename}\r\n                  createdAt={createdAt}\r\n                  url={url}\r\n                  deleteDate={deleteDate}\r\n                \/&gt;\r\n                ))}\r\n              &lt;\/tbody&gt;\r\n            &lt;\/Table&gt; : &lt;Alert bsStyle=\"warning\"&gt;No images yet!&lt;\/Alert&gt;}\r\n        &lt;\/div&gt;\r\n    )\r\n  } \/\/ end render\r\n} \/\/ end class\r\n\r\nclass CustomRow extends React.Component {\r\n  constructor(props) {\r\n    super(props);\r\n    this.state = {\r\n      startDate: props.deleteDate,\r\n      editDate: true,\r\n      dbDate: props.deleteDate,\r\n    };\r\n    this.changeFontAwesome = this.changeFontAwesome.bind(this);\r\n    this.handleRemove = this.handleRemove.bind(this);\r\n    this.saveNewDeleteDate = this.saveNewDeleteDate.bind(this);\r\n    this.cancelNewDeleteDate = this.cancelNewDeleteDate.bind(this);\r\n    this.handleDateChange = this.handleDateChange.bind(this);\r\n\r\n  }\r\n\r\n  changeFontAwesome(){\r\n    this.setState({editDate:!this.state.editDate});\r\n  }\r\n  \r\n  handleRemove(imageId) {\r\n    if (confirm('Are you sure? This is permanent!\\n' + imageId)) {\r\n      Meteor.call('images.remove', imageId, (error) =&gt; {\r\n        if (error) {\r\n          Bert.alert(error.reason, 'danger');\r\n        } else {\r\n          Bert.alert('Image deleted!', 'success');\r\n        }\r\n      });\r\n    };\r\n  };\r\n\r\n  saveNewDeleteDate(imageId) {\r\n    this.setState({editDate:!this.state.editDate});\r\n    let imageObj = {_id: imageId,\r\n                owner: Meteor.userId(),\r\n                deleteDate: this.state.startDate, }\r\n\r\n    Meteor.call('images.update', imageId, this.state.startDate, (error) =&gt; {\r\n      if (error) {\r\n        Bert.alert(error.reason, 'danger');\r\n        console.log('Error uploads.keeper: ' + error.reason);\r\n      } else {\r\n        Bert.alert('Delete Date updated.', 'success');\r\n      }\r\n    })\r\n  }\r\n\r\n  cancelNewDeleteDate(imageId) {\r\n    this.setState({startDate: this.state.dbDate, editDate:!this.state.editDate});\r\n  }\r\n\r\n  handleDateChange(value) {\r\n    this.setState({startDate:value});\r\n  }\r\n\r\n  render(){\r\n    let { id, originalFilename, createdAt, url, deleteDate, } = this.props;\r\n    return(\r\n                  &lt;tr key={id}&gt;\r\n                    &lt;td&gt;&lt;img src={url} height=\"50\" \/&gt; {originalFilename}&lt;\/td&gt;\r\n                    &lt;td&gt;{url}&lt;\/td&gt;\r\n                    &lt;td&gt;{dateSlash(createdAt)}&lt;\/td&gt;\r\n                    &lt;td&gt;{daysUntil(deleteDate)}\r\n                    { this.state.editDate\r\n                       ? &lt;FontAwesomeIcon icon={faPencilAlt} onClick={() =&gt; this.changeFontAwesome()} \/&gt;\r\n                       : &lt;span&gt;\r\n                        &lt;DatePicker\r\n                          onChange={(event) =&gt; this.handleDateChange(event)}\r\n                          selected={this.state.startDate}\r\n                          minDate={Date()}\r\n                          maxDate={Date().add(90, \"days\")}\r\n                         \/&gt; &lt;FontAwesomeIcon icon={faCheckCircle} onClick={() =&gt; this.saveNewDeleteDate(id)} \/&gt;\r\n                            &lt;FontAwesomeIcon icon={faTimesCircle} onClick={() =&gt; this.cancelNewDeleteDate()} \/&gt;\r\n                         &lt;\/span&gt; }\r\n                    &lt;\/td&gt;\r\n                    &lt;td&gt;\r\n\r\n                    &lt;\/td&gt;\r\n                    &lt;td&gt;\r\n                      &lt;Button\r\n                        bsStyle=\"danger\"\r\n                        onClick={() =&gt; this.handleRemove(_id)}\r\n                        block\r\n                      &gt;\r\n                        Delete\r\n                      &lt;\/Button&gt;\r\n                    &lt;\/td&gt;\r\n                  &lt;\/tr&gt;\r\n\r\n    )\r\n  }\r\n};\r\n\r\n\r\nImages.propTypes = {\r\n  loading: PropTypes.bool.isRequired,\r\n  images: PropTypes.arrayOf(PropTypes.object).isRequired,\r\n  match: PropTypes.object.isRequired,\r\n  history: PropTypes.object.isRequired,\r\n};\r\n\r\nexport default withTracker((props) =&gt; {\r\n  const subscription = Meteor.subscribe('images');\r\n  return {\r\n    loading: !subscription.ready(),\r\n    images: ImagesCollection.find().fetch(),\r\n  };\r\n})(Images);<\/pre>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td>Published on Web Code Geeks with permission by Dobb Mayo, partner at our <a href=\"\/\/www.webcodegeeks.com\/join-us\/wcg\/\" target=\"_blank\" rel=\"noopener\">WCG program<\/a>. See the original article here: <a href=\"https:\/\/simpleprogrammer.com\/dumb-components-smart-refactoring\/\" target=\"_blank\" rel=\"noopener\">Making Dumb Components Smart: Refactoring<\/a><\/p>\n<p>Opinions expressed by Web Code Geeks contributors are their own.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Learning new skills is how we as programmers stay sharp and stay employable. I recently started a gig that gave me an opportunity to learn something new, but I had to develop a few workarounds to learn a new framework and make it do what I needed it to do. Boilerplate code can help jump-start &hellip;<\/p>\n","protected":false},"author":4965,"featured_media":927,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[],"class_list":["post-21404","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-development"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Making Dumb Components Smart: Refactoring - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"Learning new skills is how we as programmers stay sharp and stay employable. I recently started a gig that gave me an opportunity to learn something new,\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Making Dumb Components Smart: Refactoring - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"Learning new skills is how we as programmers stay sharp and stay employable. I recently started a gig that gave me an opportunity to learn something new,\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2018-04-11T09:15:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Dobb Mayo\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@dmayo2\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Dobb Mayo\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"23 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/\"},\"author\":{\"name\":\"Dobb Mayo\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/d39943537efe6137dff884c6fe9f748c\"},\"headline\":\"Making Dumb Components Smart: Refactoring\",\"datePublished\":\"2018-04-11T09:15:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/\"},\"wordCount\":3289,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"articleSection\":[\"Web Dev\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/\",\"name\":\"Making Dumb Components Smart: Refactoring - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"datePublished\":\"2018-04-11T09:15:50+00:00\",\"description\":\"Learning new skills is how we as programmers stay sharp and stay employable. I recently started a gig that gave me an opportunity to learn something new,\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Web Dev\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/web-development\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Making Dumb Components Smart: Refactoring\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/d39943537efe6137dff884c6fe9f748c\",\"name\":\"Dobb Mayo\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/dda825314b070e2781a99f006d3c0ab1ae0a61c04982120cfc042e6800b26aa5?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/dda825314b070e2781a99f006d3c0ab1ae0a61c04982120cfc042e6800b26aa5?s=96&d=mm&r=g\",\"caption\":\"Dobb Mayo\"},\"description\":\"Dobb Mayo is the leader at Awesome Automation whose passion is to help teams become more efficient. Known as a Toolsmith and utility writer that solves problems and saves companies money\",\"sameAs\":[\"https:\/\/simpleprogrammer.com\",\"https:\/\/x.com\/dmayo2\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/dobb-mayo\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Making Dumb Components Smart: Refactoring - Web Code Geeks - 2026","description":"Learning new skills is how we as programmers stay sharp and stay employable. I recently started a gig that gave me an opportunity to learn something new,","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/","og_locale":"en_US","og_type":"article","og_title":"Making Dumb Components Smart: Refactoring - Web Code Geeks - 2026","og_description":"Learning new skills is how we as programmers stay sharp and stay employable. I recently started a gig that gave me an opportunity to learn something new,","og_url":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2018-04-11T09:15:50+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","type":"image\/jpeg"}],"author":"Dobb Mayo","twitter_card":"summary_large_image","twitter_creator":"@dmayo2","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Dobb Mayo","Est. reading time":"23 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/"},"author":{"name":"Dobb Mayo","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/d39943537efe6137dff884c6fe9f748c"},"headline":"Making Dumb Components Smart: Refactoring","datePublished":"2018-04-11T09:15:50+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/"},"wordCount":3289,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","articleSection":["Web Dev"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/","url":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/","name":"Making Dumb Components Smart: Refactoring - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","datePublished":"2018-04-11T09:15:50+00:00","description":"Learning new skills is how we as programmers stay sharp and stay employable. I recently started a gig that gave me an opportunity to learn something new,","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/web-development\/making-dumb-components-smart-refactoring\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Web Dev","item":"https:\/\/www.webcodegeeks.com\/category\/web-development\/"},{"@type":"ListItem","position":3,"name":"Making Dumb Components Smart: Refactoring"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/d39943537efe6137dff884c6fe9f748c","name":"Dobb Mayo","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/dda825314b070e2781a99f006d3c0ab1ae0a61c04982120cfc042e6800b26aa5?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/dda825314b070e2781a99f006d3c0ab1ae0a61c04982120cfc042e6800b26aa5?s=96&d=mm&r=g","caption":"Dobb Mayo"},"description":"Dobb Mayo is the leader at Awesome Automation whose passion is to help teams become more efficient. Known as a Toolsmith and utility writer that solves problems and saves companies money","sameAs":["https:\/\/simpleprogrammer.com","https:\/\/x.com\/dmayo2"],"url":"https:\/\/www.webcodegeeks.com\/author\/dobb-mayo\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/21404","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/4965"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=21404"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/21404\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/927"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=21404"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=21404"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=21404"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}