A Beginner’s Guide to Managing React State with Hooks

Managing state can be one of the more complex aspects of working with React as beginner.

What data should be managed by state versus props, which components need to access state and where state should live are all questions I ask myself when planning a new React project.

Redux is an alternative for managing `state` it may be a lot to add for a small or simple project.

While building an app that queries the Spotify API for an artist, based on the user input, it made since to store that input in state. That input value could be passed to the API, referenced in the UI (“Showing results for: adele”) or elsewhere in the app.

I learned to set up state as an object (state = { key: value}) but did not know this only works in class components! And mine were set up as functional.

Yikes.

I did not want to make the conversion right away, so I did a quick Google search for an alternative. I landed on the useState React Hook and had to give it a try.

Implementation

Hooks are a somewhat mysterious aspect of React. I had not used one until now. Similar to other features in React like componentDidMount, Hooks are built-in, modular functions of React. That’s it!

To get started using the useState Hook, it needs to be imported into your React file.

import React, { useState } from 'react';

Define State

Once useState had been imported into your file, you can create and set state values. For my app, I want to store the input from a text field in state.

Here’s what setting that up looks like:

import React, { useState } from "react";

function App() {
  const [input, setInput] = useState("");
}

What useState does is it sets up a state variable and a function that will update that variable. In my case, the variable is named input and the function that updates input is called setInput. The empty string (“) within useState is the default value for input.

From my understanding of the Using the State Hook docs, the state variable and it’s update function can be named anything. But, it makes sense to name them what they are/what they do, especially if there are multiple state variables.

Now, we’re ready to access and manipulate state within our app!

Reference State

Since state has been set up outside of a class, we do not need this.state to reference within our app. In the return() statement for App(), input is referenced as `{input}`.

Given the following example:

import React, { useState } from "react";

function App() {

  const [input, setInput] = useState("")

  // TODO: Write handleOnChange function

  return (
    <main className="App">
        <h1>Search for an artist</h1>

        <form>
            <input type="text" name="input" id="input" onChange={(e) => handleOnChange(e)} />
        </form>

        <h2>Showing results for: "{input}"</h2>
        
    </main>
  );

}

If the current value of the input was “adele”, the h2 tag would render Showing results for: "adele" to the page.

Update State

To update the input variable in state, we’ll use the setState variable we set up earlier.

In the code sample above, you see that the text input field has an onChange event. Each time the value of the text field changes (the user types in the field) a handleOnChange function is fired. This function will house the update function.

setInput could be used inline, but in my case it made more since to separate it into a handleOnChange function, since that function would perform additional operations.

To update state, we call setInput() and pass in the new value that will replace the current state.

Here’s what handleOnChange looks like in my example:

 function handleOnChange(e) {
        
    e.preventDefault();
    setInput(e.target.value)
    // TODO: Perform other operations
}

That’s it. The value of input has been updated.

Recap

To recap everything we’ve done:

  1. We imported useState into our functional component.
  2. Declared state variables *and* a function to update that variable with useState.
  3. Referenced the value of our state variable input in our and rendered on to the page.
  4. Updated input using our setInput function with the new value as the argument

And here’s what our App.js file looks like now:

import React, { useState } from "react";

function App() {

  const [input, setInput] = useState("")

   function handleOnChange(e) {
        
    e.preventDefault();
    setInput(e.target.value)

    // TODO: Query the Spotify API with the value of "input"
    }

  return (
    <main className="App">
        <h1>Search for an artist</h1>

        <form>
            <input type="text" name="input" id="input" onChange={(e) => handleOnChange(e)} />
        </form>

        <h2>Showing results for: "{input}"</h2>

        // TODO: Render results of API call to the page
        
    </main>
  );

}

This is the very beginning of what React Hooks can do. There are some limitations, rules and take some getting used to. I highly reccomend reading through their docs on Using the State Hook to see how useState compares to setting state in a class component.

Resources

Switching Themes Based on the Current Month

Recently, I’ve been experimenting with Javascript Date objects. I wanted to see if I could dynamically change the theme of a webpage, based on the current date.

For example, if it was October, the spookiest month of the year, I could have an orange, purple and black theme to remind them of Halloween.

Let’s try implementing this.

Create a New Date Object

The MDN web docs describes a Javascript Date object as:

“…[an] instance that represents a single moment in time in a platform-independent format. Date objects contain a Number that represents milliseconds since 1 January 1970 UTC.”

A new date object can be created with new Date(). The value of a date object will look something like this.

Sat Oct 17 2020 22:56:11 GMT-0400 (Eastern Daylight Time)

That’s a lot of information we can play around with.

Methods for Date Objects

While it looks like a string, keep in mind that the date is an object, not a string. Running console.log(typeof new Date()); would return false.

Luckily, the date prototype comes with built-in methods. These methods allow us to focus on specific parts of the date object.

For this example, I want to focus on the current month. Instead of converting the value of the date object to a string, comparing it to calendar months (October, November, etc), we can use the getMonth() method.
getMonth() returns an integer, that corresponds to the months of the year. The months of the year are zero index, so January would be 0, February 1 and so on.

Let’s see what it returns given the new Date() referenced above.

let now = new Date() // Sat Oct 17 2020 22:56:11 GMT-0400 (Eastern Daylight Time)
now.getMonth() // 9

It is currently October 17th. October is the 10th month of the year and since January would return 0 this is returning what we need.

Theme Names

Now that I know the current month, I can use it to influence changes in the CSS. I’ll use a switch case to change the value of a themeToAdd variable that I’ll later apply to the body tag.

My switch case looks something like this.

let now = new Date() // Sat Oct 17 2020 22:56:11 GMT-0400 (Eastern Daylight Time)
now.getMonth() // 9

// Placeholder for theme name that we'll add later
let themeToAdd = ""

// Evaluates the current, zero-indexed month based off of the now date object

switch(now.getMonth()) { 
    case 9:
       themeToAdd = "dark-and-spooky" 
    break; 
    default: 
       themeToAdd = "dark"
}

The logic goes something like this.

  • If the current month is October, apply the dark-and-spooky theme.
  • If the current month is not October, apply the dark theme

A bonus to having a default case is that if a date object cannot be created, we have a fallback style.

Speaking of styles, let’s set up the CSS variables for our default, dark and dark-and-spooky themes.

:root { 
--background-color: #efefef;
--font-color: #444444; 
...
}

body[data-theme="dark"] { 
--background-color: #032b43; 
--font-color: #efefef;
...}

body[data-theme="dark-and-spooky"] {
--background-color: #010101;
--font-color: #BA4A00;
...
}

...

body {
background-color: var(--background-color); 
color: var(--font-color);
...}

Changing the Theme

Now that we know which month is it, and have a theme name, and the styles set, it’s time to implement it.

Borrowing from the data attribute demo from a few months ago, we’ll implement the theme as a checkbox.

Given an HTML file that looks like this:

<html>
    <head>
    ...
    </head>
    <body>
        <label>
            Dark Mode?
            <input type="checkbox">
        </label>
    ...
    </body>
</html>

With Javascript we can target the checkbox and wait for it to be checked. If it’s checked during the month of October, implement the dark-and-spooky data attribute. Otherwise, add dark. And, if either theme is already a set attribute on the `body` tag (it was already checked), remove the data-theme attribute entirely and show the default theme.

...
let checkbox = document.querySelector("input")
    let body = document.querySelector("body")
    
    checkbox.addEventListener('change', (event) => {
        event.target.checked ? body.setAttribute('data-theme', themeToAdd) : body.removeAttribute("data-theme")
    });

Putting everything together, we have something that looks like this.

See the Pen Switching Theme Based on the Current Month by Shannon Crabill (@scrabill) on CodePen.

Note that you’ll see specific styles of the current month is October, February, or December.

Time Travel is Fun

If you enable the checkbox during the month of October, and see a dark background with orange text, it’s working!

But, you may be wondering how you can test to see if your themes are working without waiting for the right month or resetting your computer’s clock.

What’s powerful about the date constructor is that is can take in optional parameters.

If a valid date value is passed into new Date() it “…returns a Date object whose component values (year, month, day, hour, minute, second, and millisecond) all come from the [given] parameters”.

So, if we wanted to test if a lovey-dovey theme would work in the month of February, we can create a new date object for testing, like this.

let now = new Date('February 2020') // Sat Feb 01 2020 00:00:00 GMT-0500 (Eastern Standard Time)

now.getMonth() // 1

Resources

Opting Out of Hacktoberfest

For 2020, I made the decision not to opt my How Many Days Until Halloween? project in as part of Hacktoberfest.

Here’s why.

Time

I did some mental math recently. I have realized that isn’t enough time in the day to get done what I need to get done, want to get done, plus sleep, eat, etc. As I wrote about in You Don’t Have to Participate in Hacktoberfest, self-care > coding, and I need to follow my advice.

As fun as this project has over the past 3 years, it does take a lot of time and energy that I do not have to spare at this time. I’ve had ideas on how to expand on this project, what I would like to do, etc. But haven’t been able to get it to a place that I would like, that would sustain multiple, external contributions.

The Spirit of Hacktoberfest

Ha. Spirit.

Hacktoberfest is now in its 7th year. It has evolved some overtime. Recently, the idea of “quality vs quantity” has been highlighted as a core value. This year, the language reads as follows:

Quantity is fun, quality is key. Participating in Hacktoberfest leads to personal growth, professional opportunities, and community building. However, it all begins with meaningful contributions to open-source software.

And I get it. Quality is better than quantity.

This line also had me debating if a countdown timer to Halloween meets the quality criteria. It’s not a spammy project—or…is it?—but the uncertainty helped me to solidify my decision.

There Are Bigger Fish Out There

What I love about coding is that it doesn’t *have* to make a big change in the world.

But it can.

And with everything going on in the world right now, I want to make space for the open-source projects that matter.

If you are unsure what this could mean or where to start, here are some COVID-19 and climate change related projects to contribute to.

What Does This Mean?

If any questions are not covered here, please DM me on Twitter.

In the meantime, stay spooky my friend.

👻

Photo by Mathew Schwartz on Unsplash

You Don’t Have to Participate in Hacktoberfest

The first of October. The official start of spooky season. And, if you follow the tech community, the beginning of Hacktoberfest.

Hacktoberfest is an annual event that encourages participation and contribution to open source projects. Sign up during the month of October, make at least 4 valid pull requests in public repos on Github and you can receive stickers and limited edition t-shirt.

I’ve participated in Hacktoberfest for the past 3 years and it can be a lot of fun.

It can also be a lot of work.

This is especially true if you maintain a project. Tag issues with hacktoberfest for visibility and your project will gain traffic and pull requests. Most of them may be considered “spammy”.

Each year, in September (or Preptember) the “get ready for Hacktoberfest”, “who’s looking for contributors” and “101 open source projects for beginners” posts go live, the emails to sign up come in. And it can all be a little overwhelming.

Especially with everything going on in the world right now.

This is why I’ll step in as your internet friend by telling you it is ok not to participate in Hacktoberfest.

Here are two reasons why.

Spare Time is a Luxury

I have a lot of feelings about personal projects and coding outside of work. On one hand, personal projects are good for learning a new skill, or as a side hustle. Any reason that you want to code outside of your 9-5 is valid.

But. Not everyone has the privilege of spare time.

Family commitments, second jobs, whatever. Extra time at a computer isn’t realistic for everyone. And that is ok. There can be pressure, even if it’s from ourselves, to try and do all-of-the-things. But it’s not always possible.

Please be realistic about what is important to you, your career, your family, etc. Be realistic about how much time exists in a day, week, month, etc and what time you can commit to.

Which brings me to my next point.

Self-care > Coding

Coding is a big part of my life. I love it. I do it as part of my job. I code in my spare time and yet…I find myself needing and wanting to spend more time away from the computer.

Perhaps you feel the same way.

As the days get shorter and the longest year of our lives comes to an end…reflect on how you are feeling. If you feel as tired and exhausted as I do. It may be time to focus on self-care, recharging, and coming back refreshed.

Self-care is whatever you need to do to recharge. As developers, I feel like there’s pressure to always be working on something, work/life balance tends to slip and, if you aren’t careful, burnout will set in.

Trust me, time away from a computer will allow you to come back with fresh eyes, a fresh perspective, and ready to pick up where you left off.

Please Take Care of Yourself

The main point I am trying to make here is that you do not have to participate in Hacktoberfest. You are no less of a developer if you sit out this year (or next year, or never participate). Do what you feels right to you and you will not be disappointed.

Photo by Mathew Schwartz on Unsplash

In Defense of Tutorial Hell (and How to Escape It)

Ahhhhhhhhhhhhh!

Tutorial hell! It’s a terrifying, terrifying place to be as a developer

Or…is it?

I am on the fence on if being in tutorial hell is really as bad as the internet makes it out to be.

What Is Tutorial Hell?

“Tutorial hell” means participating in tutorial-based content to create projects or apps. Most of your time is spent building what other people are telling you to build, instead of new, original concepts.

Now, I’ll dive into my thoughts on the good and bad aspects of tutorial hell

The Good

As someone who is mostly a self-taught developer, I 100% get the appeal of tutorials. They are a good instructional device to learn or get familiar with a new framework or programming language.

An example I like is the tic-tac-toe game as part of the Intro to React documentation. The tutorial says, it well, in why you should rethink skipping the tutorial.

We will build a small game during this tutorial. You might be tempted to skip it because you’re not building games — but give it a chance. The techniques you’ll learn in the tutorial are fundamental to building any React app, and mastering it will give you a deep understanding of React.

Yes to learning the fundamentals before diving into the more complex aspects of React! Since tic-tac-toe is a relatively easy game to play, and most people know how to play it, it’s a good reference for building on the fundamentals of React (or whichever framework, language, etc you are trying to learn). Someone going through this tutorial can focus on “how do I pass props again?” instead of having to come up with a brand new concept (which is like having to learn two things at once).

Another point I would like to make is that tutorials (like building a simple game) are great for people to learn concepts better by doing, as opposed to reading documentation. I’m one of those people and have no problems going through a tutorial to help solidify core concept when I feel like am lacking in that area.

The Bad

From my perspective, there are two less-than-ideal aspects of doing too many tutorials

  1. You are jumping around to too many things / not going deep in a topic
  2. You end up with a lot of small projects that look very similar to everyone else

Jumping Around

I’ll start this off with a positive note. Doing multiple tutorials in multiple frameworks/languages/etc is fine. You’re allowed to try different things, to change your mind, to find a tutorial that helps you learn what you want to learn.

Where the problem tends to pop up, is that tutorials are—usually, but not always—aimed at a beginner/novice skillset. Again a tutorial as a learning tool is great. But you’ll get to a point where you’ve learned that all you can from tutorials and need to start deepening your programming knowledge.

Again, as a mostly self-taught person who codes, I’ve done a lot of tutorials. I love them. Sometimes I do them for fun. But for the longest time, I felt like I stuck in learning the “100 levels” concepts, but did not know how to move to the “200 and 300 level” concepts.

Your Project List Looks Like Everyone Else’s

There are strong opinions on either side if it’s ok to showcase tutorial apps or projects in your portfolio. On one hand, showing that you know how to code a thing in insert-cool-framework is great, especially if you are getting started or trying to break into tech. I’d argue that some work to show is better than no work to show.

At the same time, yes you can code a thing, but employers or hiring managers may not feel the same way. Without supporting context, it can be difficult to tell how much code was provided as part of the tutorial versus how much you coded.

And if you did code it. What does that mean? Did you type it line for line as it was explained in the tutorial? Or did you go off a prompt—like, create a function that returns a random integer—and figure out your own solution?

Think about it this way. Do you understand the fundamentals of what each line of code does and why it works? Or just that it does work and you can’t articulate how it works?

Escape From Tutorial Hell

I’ve talked a lot about the ehh and ok aspects of doing tutorials. If you’ve come to the conclusion that you are trapped in tutorial hell, but aren’t sure how to escape from it, here are things to think about.

  • Build your own thing, without following a tutorial. Example: Make up a new game and build that in your favorite programming language
  • Add new features to something you built-in a tutorial. Example:
  • Refactor a tutorial project or an older project of yours. Example: Incorporate array functions, swap var instances for let or const, hide your API keys.
  • Add some styling. Example: Better rendering for mobile, dark/light mode toggle, make sure it’s accessible.
  • Deploy your app/project/game to the cloud: Example: Migrate your backend database to Postgres and host on Heroku.
  • Add additional CRUD