DEV Community

Audiophile
Audiophile

Posted on • Updated on

Learning how to be lazy in React: A guide for beginners.

If you're someone who reads a lot of dev articles, you've probably heard it once or twice(or ad nauseam depending on the crowd) that the best devs are the lazy ones! They get as much done with as little complexity as possible, while keeping their code readable.

Luckily for us, the react way of preferring composition over inheritance(i.e using components) encourages us to be as lazy (and efficient) as we can be.

So what are components, in English?

Components are tools. A component is that spanner you use to tighten the terminals on your car battery when you need to fix it, sometimes you need a size 12, so you pass it a '12' prop. Other times, you require a slightly bigger or smaller size depending on the problem.

On slightly slow days, a component is a pot or a frying pan, if you will. If you need to fry two eggs, then you don't need a large pan (or in react-speak, you don't need the 'large' prop). You pass it the 'small' prop, 'fry' your eggs as needed, and have yourself a nice reacty delight.

It's in the little things you see, if you're a beginner, just learning the ropes of 'thinking in react', it may take a couple of weeks or even months to fully grasp and begin to leverage the power of reusable components.

This article-cum-tutorial will help you on your journey by building a reusable component.

The Spacer Component a.k.a "Shift-abeg" .

Don't worry if you don't understand the alias, it's a Nigerian slang for "gimme some space". I've found that making your code as relatable as possible makes it stick faster.

Two foxes fighting

Two foxes telling each other to "Shift abeg"
Photo by cloudvisual.co.uk on Unsplash

So you're a front end developer who needs to add margin to a lot of things. On a good day, most popular css libraries will handle that for you. But then again, you don't want to be that guy that brings a bazooka to a knife-fight...sometimes a simple native margin property would do.

So you sprinkle the margin property here and there, adding it to your component classes and all, you hate the extra typing, but what can you do? The short answer is: "get lazy!"

What if you could make a component that accepted a prop which would determine how much space you wanted with minimal instructions?

Step 1: Create our component scaffolding.

import React from 'react'

export default Spacer = () => {}


Enter fullscreen mode Exit fullscreen mode

Step 2: Give it a behaviour

import React from 'react'

export default Spacer = () => {
return(
<div style={{margin: ""}}></div>
)
}


Enter fullscreen mode Exit fullscreen mode

In this case, we don't want our component to fix our car for us or fry two eggs...even though those would be great right now, we just want some space whenever we apply it.

Step 3: Pass some props.

In case your mind gets foggy when you hear props, it's just short for property...like how an object has a property(or key) and a value associated with that prop?

import React from 'react'

export default Spacer = (props) => {
return(
<div style={{margin: props.unit }}>{props.children}</div>
)
}


Enter fullscreen mode Exit fullscreen mode

Wait hold-up, I thought we wanted space, why is our component having kids?!

Let's be calm now, so the reason our component needs to have children is because we don't want our component to care about what it applies its space-creating powers to. We just want it to be an unbiased, incorrupt Shift-abeg(er). So "children" in essence says, you're not going to know what you'll get before-hand, but whatever it is, apply a margin property to it.

Next up, our unit props, is where the magic happens. Now we want our Shift-abeg Component to give us a margin of whatever number is passed to it(in pixels). Now our Spacer doesn't know that this property is supposed to be a number yet, so we solicit the help of a package that used to 'date' react before but then they broke up. Sad, I know.

The package is called 'prop-types'. It helps to check the data type of your props, so your component knows when the right props are passed to it, and vice-versa.

Install prop-types...

 npm install prop-types  || yarn add prop-types
Enter fullscreen mode Exit fullscreen mode

When we're done installing, we add it to our component, to give it some understanding of what it's supposed to receive as a unit prop.

import React from 'react';
import PropTypes from 'prop-types';

export default Spacer = (props) => {
return(
<div style={{margin: props.unit }}>{props.children}</div>
)
}


Spacer.propTypes = {
   unit: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
}

Enter fullscreen mode Exit fullscreen mode

Don't panic! We're just telling our component to expect either a string, on days when we want to add things like unit="5px" or unit="5em", etc... and it should expect a number on days when we just want to do this: unit={5}.

Our Spacer component is almost done!

Now, our spacer component has the ability to give us a margin quite alright but what if we want a margin-left? or a margin-right? It fails at that. And we're trying our best to lazy things up right?

Let's go one step further:

import React from 'react';
import PropTypes from 'prop-types';

export default Spacer = (props) => {
return(
<div style={{
   margin: props.unit,
   marginLeft: props.left,
   marginRight: props.right,
}}>
   {props.children}
</div>
)
}


Spacer.propTypes = {
   unit: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
   left: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
   right: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
   children: PropTypes.elementType
}

Enter fullscreen mode Exit fullscreen mode

Proptypes.elementType means: "hey Spacer, expect your children props to be react elements"

Mad ooo!(slang for "wonderful!" in this context) We're almost there. Now our Spacer can give whatever children components are passed to it an ability to move to the left or to the right.

But there's one tiny problem...

What if no values are passed? We have no fall back for that event. For instance, if we give a margin-left because that's the behaviour we're looking for, what happens to the margin and margin-right style props that are expecting values?

Let's fix that:

import React from 'react';
import PropTypes from 'prop-types';

export default Spacer = (props) => {
return(
<div style={{
   margin: props.unit || "",
   marginLeft: props.left || "",
   marginRight: props.right || "",
}}>
   {props.children}
</div>
)
}


Spacer.propTypes = {
   unit: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
   left: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
   right: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
   children: PropTypes.elementType
}

Enter fullscreen mode Exit fullscreen mode

Ta-da! We've ensured that our component won't throw bugs in case nothing is passed to any of its style properties.

What about margin-top and bottom sir?

Here's the beautiful thing, if you want space at the top or bottom of your component, you don't have to pass it any children. You can just pass it a unit prop, specifying how much space you want in pixels, and place it on top or below your target component.

Spacer in action:

import React from 'react';
import Spacer from './components/common/Spacer'; 

const App = () => {

return (
  <div>
  <Spacer unit={40}/>
  <ComponentThatNeedsAMarginTopProperty />
  </div>
)

}


export default App;
Enter fullscreen mode Exit fullscreen mode

For the normal margin powers:

import React from 'react';
import Spacer from './components/common/Spacer'; 

const App = () => {
//This would give it space to the left side of the component!
return (
  <div>
  <Spacer left={40}>
  <ComponentThatNeedsAMarginLeftProperty /> 
  </Spacer>
  </div>
)

}


export default App;
Enter fullscreen mode Exit fullscreen mode



A side note(updated):
Please note that using the style property of jsx tags give them more power over your styles than classes. This could lead to issues that make css hard to debug, classes are better as rightly pointed out in the comments section. However for the purpose of keeping this tutorial as beginner-friendly as possible, I'll leave as is.
</code> 


##Laziness is Achieved!
Congrats dear beginner! You've made a reusable component! Now the amount of time you spend writing margin-this or margin-that for classes have reduced significantly. You can now spend more time on other parts of your code! This is just a brief introduction to the power of re-usability to the uninitiated in React. Hope this helped. 

Stay lazy.
Enter fullscreen mode Exit fullscreen mode

Discussion (4)

Collapse
chico1992 profile image
chico1992

Seriously i think this is bad advice since this will only polute the dom to add some margin. If you want to be lazy just use some css utility classes to add the class that has the right margin that you want and keeps your dom clean and keeps your margins consistent

Collapse
itz_giddy profile image
Audiophile Author

You are right chico. I have updated the side note section to point this out. I was really thinking of the simplest way to convey the concept of reusable components and I couldn't find a simpler example at the time of writing this. Thanks for pointing it out!

Collapse
chico1992 profile image
chico1992

Actually i was talking about the useless div’s that the spacer component produces
And i know it’s hard to find a good and easy example to explain this concept

Thread Thread
itz_giddy profile image
Audiophile Author

Oh okay, I get you now