Mini Calendar: React Components, Props and Project Structure

Search for a command to run...

Very cool!
In this series, I plan on documenting my React learning journey.
React stopped being scary by now and that's very good news. Now, we can turn any HTML code into React components, isn't that something? We've made it this far and now it's time to take a step further and get to play around with something awesome! Sta...
Working with our root user on all our databases is not a smart move and we all know it. We are going to learn how to use the command line to create a new MySQL user and grant him all the permissions and privileges needed to work independently. I am a...

We have been learning and creating lots of fun stuff and I believe we have a good idea on how to build React apps. It's time for us to know how to deploy those apps and have a live URL to show our progress off! We have been using Create React App to ...

Signing up and signing in are parts of our indispensable web routine and if we plan on using React for creating complex web applications, we need to know how we are going to approach authentication in React. We know by now, React handles communicatin...

Hosting is expiring and some serious panicking needs to take place! I had very basic hosting for my personal website and I was not satisfied with it. Once you realize you're not satisfied with your hosting, you think you're going to do proper researc...

We have been using React to develop Single Page Applications, so far and it's not that we don't like SPAs, we love them, but we tend to get involved in more complex applications that require multiple pages, don't we? So we need to be prepared if we h...

Still React-ing! Now that we are more confident in our JSX skills and we know how to set up a development environment to work with, it's time to take a step further and get to know what React is really made of.
Apparently, the component is the main building unit in React so we need to get a good grasp on how it works, as our lives would be pretty much revolving around it.
I found 2 types of Components:
I have tried to find out which is better or which is more used and why, but couldn't find solid information.
Some say class components give access to additional features like state, but others reply that the same functionality can be compensated for by hooks in function components. I found lots of arguments, but nothing real, so, as agreed these are more advanced topics for future Rana to decide upon. For present Rana the only difference between them both is the syntax, so let's check it out!
Just your normal Javascript function, but returns a JSX element, the only unusual thing about it, is that the first letter of its name will be capitalized in order for us to be able to distinguish it from other markup tags, when it's called.
function MyFunctionComponent(){
return (
<div>
<h1>Hello, Function Component!</h1>
</div>
);
}
OR if you're an ES6 or later person
const MyFunctionalComponent=()=>(
<div>
<h1>Hello, Function Component!</h1>
</div>
);
Your usual class, but it has to extend the React.Component class to get all the React perks. Also, the JSX code to be rendered has to be returned by, obviously, the render method.
class MyClassComponent extends React.Component {
render() {
return (
<div>
<h1>Hello, Class Component!</h1>
</div>
);
}
}
A horrible mistake I did earlier is, I insisted on rendering multiple sibling elements at once and that's not possible, so remember kids, always wrap all your elements in one and only one element OR I found another magic trick where we can enclose all our elements in a React.Fragment element
<React.Fragment>
<div>1</div>
<div>2</div>
<div>3</div>
</ React.Fragment>
But what if I want to render a component within a component? Nest away!
If I were a component, either a function or a class and was called, I would look like this:
<Rana />
I have a self closing tag, because I am writing on an empty stomach, but there is a sexy pasta alfredo component sitting right beside me looking like this:
<PastaAlfredo />
Of course, who am I to resist? The pasta component and I need to become one so it stopped sitting beside me and it is now sitting in my stomach, so now I look like this:
<Rana>
<PastaAlfredo />
</Rana>
If you want to nest components you're probably going to want to pass those poor children some data to modify their behavior. That's where props come in handy.
For function components we just pass a props variable (it could be any name of our choice, but that's how the convention goes) as an argument and for class components we can access the props using this.props
So far so good we have nice concepts in hand. Now let's try and use them to build something!
Last time, thanks to our marvelous React coding skills, we were capable of knowing what day today is, now we will take what we already have a tad further and mix it to build a mini calendar for the whole month.

Let's start by running npx create-react-app . in our root folder of choice!
Previously, we postponed going through the create-react-app project structure for the future and the future is now!
Or what I like to call things that doesn't really concern me folder.
So, we will rarely need to change anything in that folder.
That's probably where we will be living while developing. I was checking how I was going to structure the folders for adding components to keep myself organized and there were multiple options from which I liked a couple. Both of them start by creating a components folder within the src folder and then:
I chose to go with the later for now to make it easier for me to move components from project to project until I dig deeper in component reusability.
Let's try and define the components we need!
First of all, we will need a convenient space to contain all our days, so let's call our first component Month.
Second, we will need a Day component to represent each day in our month, so there goes our second component!
We will include the unique day brands in the Day component and we will include all our Day components in our Month component. That's a solid plan.
I will be using function components for now and save class components for later. Let me start by creating a components folder and inside it create a Day folder that includes an empty Day.js file.
Baby steps, so for now let's just add the date inside our Day component. I'll just put a dummy 1 until we figure out our next step.
import React from "react";
function Day() {
return <div className="day">1</div>;
}
export default Day;
We will create a folder structure for the Month component similar to our Day component.
In our Month.js file we will import our Day component and add elements for the month heading and the days.
import React from "react";
import Day from "../Day/Day";
function Month() {
return (
<div className="month">
<div className="heading">June</div>
<div className="days">
<Day />
</div>
</div>
);
}
export default Month;
In our App.js file let's clean up what we don't need and add our Month component to view our progress on screen as we go.
import React from "react";
import "./App.css";
import Month from "./components/Month/Month";
function App() {
return (
<div className="app">
<Month />
</div>
);
}
export default App;
I cleared the App.css file and just set the styles that will affect the elements globally.
@import url("https://fonts.googleapis.com/css2?family=Great+Vibes&display=swap");
* {
box-sizing: border-box;
}
html,
body,
#root,
.app {
height: 100%;
}
Great! Everything is rendered. Now we only have 1 day and we need to add all the days. I am definitely not going to add about 30 days manually, so it's loop O'clock.. But how?
React loves arrays and so do we! We are going to loop normally from 1 to the last day of the current month and for each loop we're going to push a Day component in our days array.
To render the days array we will just wrap it with curly braces and they'll take care of everything.
function Month() {
let days = [];
const currentDate = new Date();
const daysOfMonth = new Date(
currentDate.getFullYear(),
currentDate.getMonth() + 1,
0
).getDate();
for (let i = 1; i <= daysOfMonth; i++) {
days.push(<Day />);
}
return (
<div className="month">
<div className="heading">June</div>
<div className="days">
{days}
</div>
</div>
);
}
Before we sail any further, let me just throw some grid view styling in a Month.css file and import it into our component to be able to get a better understanding of what goes where.
.month {
height: 100%;
display: grid;
grid-template-rows: 5% auto;
padding: 1rem;
}
.month .heading {
text-align: center;
align-self: center;
font-family: "Great Vibes", cursive;
font-size: 42px;
color: #ab1111;
font-weight: 600;
}
.month .days {
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-gap: 2px;
}
@media screen and (max-width: 950px) {
.month .days {
grid-template-columns: repeat(5, 1fr);
}
}
@media screen and (max-width: 800px) {
.month .days {
grid-template-columns: repeat(3, 1fr);
}
}
@media screen and (max-width: 400px) {
.month .days {
grid-template-columns: 1fr;
}
}
Lovely! Now we have 30 ones rendered to the screen and now we need to replace them with the actual dates. Props to the rescue!
In our loop let's send the date as a prop in our loop
for (let i = 1; i <= daysOfMonth; i++) {
days.push(<Day date={i} />);
}
In our Day component let's replace our dummy text with the actual date.
function Day(props) {
return <div className="day">{props.date}</div>;
}
Everything is working well, but I got prompted a warning in the console: Warning: Each child in a list should have a unique "key" prop.
To get rid of that I added a key prop for the Day component and set it with an incremental unique key for each.
Great! Now that everything is set, we need to add our unique day brands we implemented previously in
To be able to do that we need to send what day of the week it is to our Day component as a prop and while we're at it let's get the month in the heading dynamically, as well.
let months = [];
months[0] = "January";
months[1] = "February";
months[2] = "March";
months[3] = "April";
months[4] = "May";
months[5] = "June";
months[6] = "July";
months[7] = "August";
months[8] = "September";
months[9] = "October";
months[10] = "November";
months[11] = "December";
function Month(){
let days = [];
const currentDate = new Date();
const daysOfMonth = new Date(
currentDate.getFullYear(),
currentDate.getMonth() + 1,
0
).getDate();
for (let i = 1; i <= daysOfMonth; i++) {
let weekDay = new Date(
currentDate.getFullYear(),
currentDate.getMonth(),
i
).getDay();
days.push(<Day key={"day" + i} date={i} weekDay={weekDay} />);
}
return (
<div className="month">
<div className="heading">{months[currentDate.getMonth()]}</div>
<div className="days">{days}</div>
</div>
);
}
For our Day component we will add an array of days and use it to assign classes for custom styling.
let week = [];
week[0] = "Sunday";
week[1] = "Monday";
week[2] = "Tuesday";
week[3] = "Wednesday";
week[4] = "Thursday";
week[5] = "Friday";
week[6] = "Saturday";
function Day(props) {
return (
<div className={"day " + week[props.weekDay].toLowerCase()}>
<div className="date">{props.date}</div>
<div className="weekday">{week[props.weekDay]}</div>
</div>
);
}
Now we have all the data we need so let's add our SVG images to our Day folder and fill a Day.css with magic and import it!
.day {
padding: 1.5rem;
background-repeat: no-repeat;
background-size: 50%;
background-position: bottom;
opacity: 0.7;
box-shadow: 1px 1px 6px 0px black;
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.day.sunday {
background-size: 40%;
}
.sunday {
background-image: url("./sunday.svg");
}
.monday {
background-image: url("./monday.svg");
}
.tuesday {
background-image: url("./tuesday.svg");
}
.wednesday {
background-image: url("./wednesday.svg");
}
.thursday {
background-image: url("./thursday.svg");
}
.friday {
background-image: url("./friday.svg");
}
.saturday {
background-image: url("./saturday.svg");
}
.weekday {
margin: 0 auto;
font-family: "Great Vibes", cursive;
font-size: 1.5rem;
}
.wednesday .weekday {
color: #f9a727;
text-shadow: 1px 1px #3f3d55;
}
.saturday .weekday {
color: #e50914;
text-shadow: 1px 1px #00bfa6;
}
.thursday .weekday {
color: #2f2f41;
text-shadow: 1px 1px #00b0ff;
}
.friday .weekday {
color: #d83e75;
text-shadow: 1px 1px #2f2f41;
}
.sunday .weekday {
color: #ff6584;
text-shadow: 1px 1px #3f3d55;
}
.monday .weekday {
color: #0e01bf;
text-shadow: 1px 1px #ffb8b8;
}
.tuesday .weekday {
color: #36799a;
text-shadow: 1px 1px #ffb8b8;
}
Hooray! Our calendar is all set, but I am getting a little greedy. I want to highlight today so that I won't be lost.
In our Month.js file let's send a prop to set that.
for (let i = 1; i <= daysOfMonth; i++) {
let weekDay = new Date(
currentDate.getFullYear(),
currentDate.getMonth(),
i
).getDay();
let today = "";
if (i === currentDate.getDate()) {
today = " today ";
}
days.push(<Day key={"day" + i} date={i} weekDay={weekDay} today={today} />);
}
In our Day.js file let's read that prop and set it as a class.
function Day(props) {
return (
<div className={"day " + props.today + week[props.weekDay].toLowerCase()}>
<div className="date">{props.date}</div>
<div className="weekday">{week[props.weekDay]}</div>
</div>
);
}
Finally, let's add styling in Day.css to highlight today.
.today {
box-shadow: 0px 0px 5px 2px #770909;
opacity: 1;
}
Voila! We have our calendar!
By this mini calendar I shall end my second baby step towards React greatness, until we meet in another one.
Any feedback or advice is always welcome. Reach out to me here, on Twitter, there and everywhere!