React-Reusable Components
Tags: react, jsx, javascript
Published: 2021-05-01 20:08:23

I'll admit I'm only a year into professionally writing React but I've been working on a production codebase that was written with hardly any reusable components among other conventions that I find odd.

That said I am going to share my general philosophy on the value and importance of custom components which I picked up from a different codebase prior to working on the current one.

In the current codebase I'm working in, custom components are sparse. More-so, the UI is built with native html tags (i.e. `<div>`, `<span>`, etc.) in the main component (i.e. CheckoutPage). Furthermore, sometimes values are not stored in a local variable when fetched from an api call; rather rendered as:
 
```js
<div className="total__price">${item.total_cents.toFixed(2)}</div>
```

As a one-liner it seems innocently benign but as the file grows for the entire UI on a particular feature, all you see are divs, spans, all over the place that becomes too noisy as I'm having to read `className`s to begin to understand what's going on. For example....

####Common markup I see on a daily:
`LineItems.js`
```js
<div className="flex col space-between container">
  <div className="flex line-item line-item__container">
    <span>Subtotal</span>
    <span>${(checkout.sub_total_cents / 100).toFixed(2)}</span>
  </div>
 <div className="flex line-item line-item__container">
    <span>Tax</span>
    <span>${(item.tax_total_cents / 100).toFixed(2)}</span>
  </div>
  {checkout.discount_total_cents > 0 && 
    <div className="flex line-item line-item__container">
      <span className="margin-right-auto">Discounts</span>
       <span className="line-through">{checkout.previous_price / 100).toFixed(2)}</span> 
       <span>${(checkout.total_discounts_cents / 100).toFixed(2)}</span>
    </div>
  }
  /* and many more line items ... */
</div>

```

When I see the above snippet, I see a few optimizations that can make this more readable and reusable should requirements change (as they usually do). Oh and I forgot to mention there is one global stylesheet for all components in the application that is 6000+ lines long with tons and tons and tons of nesting. 😔

###Quick Assessment

  - the line item can be a _componentized_ 
  - I like to use the classnames package along with css modules
  - store values in a variable

###My proposed optimization: 

 1) Abstract the line item

`LineItem.js`
```js
import {flex, space_between} from 'assets/css/flex.module.scss';
import {strikeThrough, textBold} from 'assets/css/utils.module.scss';
import {secondary} from 'components/common/text/text.module.scss';
import {formatPrice} from 'helpers';
import classnames from 'classnames';

const LineItem = ({label, value, hasDiscount, previousPrice, bold}) => {
    return (
      <div className={classnames(flex, space_between, {[textBold]: bold})}>
        <p className={classnames({[margin_right_auto]: hasDiscount})}>{label}</p>
        {hasDiscount && (
            <p className={classnames(strikeThrough, secondary)}>${formatPrice(previousPrice)}</p>
         )}
        <p>${value}</p>
      </div>
    )}

export default LineItem;
``` 
 2) Use the Line Item component

`LineItems.js` 
```js
import {flex, space_between} from 'assets/css/flex.module.scss';
import {formatPrice} from 'helpers';
import LineItem from './LineItem';

const LineItems = ({checkout}) => {
  const subtotal = formatPrice(checkout?.sub_total)
  const discounts = formatPrice(checkout?.discount_total_cents)
  const hasDiscount = checkout?.discount_total_cents > 0
  const previousPrice = formatPrice(checkout?.total_cents - checkout?.discount_total_cents)
  const tax = formatPrice(checkout?.tax_cents)
  const total = formatPrice(checkout.total_cents)

  <div>
    <LineItem label="Subtotal" value={subtotal}/>
    <LineItem label="Tax" value={tax}/>
    {hasDiscounts && (
      <LineItem 
         label="Discounts" 
         value={discounts} 
         previousPrice={previousPrice} 
         hasDiscount 
      /> 
    )}
    <LineItem label="Total" value={total} bold/>
  </div>
  /* and many more line items ... */
}
```

###Why, in my opinion, this is a better approach

After _componentizing_ the line item, reading `LineItems.js` is much more clear as to what is being rendered and is noise-free. The user of `LineItem` merely has to look at what `LineItem` expects `(props)` or look at how it's currently being used to simply add a new Service Charge line item should The Product team wish to add it to "Checkout" _AND_ the "Order Receipt".

### Conclusion

Bear in mind – this is a simplified code snippet to get my point across. I understand some people are of the school of thought that abstracting the line item to a reusable component is over abstracting; I don't believe so. It is my belief that once the component is created and well-defined, any new dev that joins the team can easily understand what `LineItems` is rendering and add a new line item `LineItem.js` within a matter of seconds. Efficiency..... Efficiency is the value and importance of this approach. 

Please let me know what you guys think. Is this over abstracting or do you think this is good practice? Also, are you still using Class components versus Functional Components in 2021? Let me know. Thanks.