What React is NOT Made For

React is designed for data-driven dynamic sites — but it can make the process lengthier for smaller projects. Learn when not to use React.

Michaelpgalen
JavaScript in Plain English

--

When a certain tool becomes incredibly popular, it’s easy to fall into the trap of choosing the tool before knowing the problem. It’s like buying a hammer before seeing if the plans call for screws or nails.

A hammer and a bent screw

SUMMARY

I’ve been enthusiastically learning React, without quite understanding what it was designed for and what it wasn’t. So, I tried building numerous small apps in vanilla JavaScript AND React, to understand how things translate from one to the other. Here is what I learned!

What is React designed for?

React is designed for data-driven dynamic sites, commonly single-page apps, where data is requested from a server and then used by the browser to render pages. React helps break down apps into lots of little UI components, making it easier to map mentally as well as share components across large teams. Facebook is a perfect example (the creators of React).

What did I try to build?

A metronome app with no server-side programming or data to fetch from a database. Just complex client-side metronome logic to create a tool for musicians.

Was I successful?

Yes, actually! But using React was more difficult, and required more lines of code, and more dependencies.

The Project

My goal is to rebuild my SwingDivsion Metronome in React with the aim of learning more about React’s weaknesses and how to overcome them.

My Challenges, Where I found Help, and Solutions!

Challenge 1: Where to put the metronome constructor function?

For the vanilla JS version, I created a timer constructor function (inspired by the creator of Music and Coding on YouTube). Then, I declared an instance of the timer function using my metronome’s callback and error functions. This helped me divide some of the complexity into smaller chunks. In React, I couldn’t figure out where to write my constructor function code so that it was usable for my metronome. The constructor function relied on the ‘this’ keyword, which seemed to be lost in React with everything broken up into modules.

Javascript code snippet of the metronome constructor function.
The vanilla JS constructor function for my metronome

Solution

I never figured out where to write a constructor function like this, and how to use it in React, but instead, I realized I didn’t need multiple instances of the function. So, I just wrote the functional logic directly into my startStopBtn component without needing the ‘this’ keyword.

Challenge 2: Where do states need to be managed?

My vanilla JS version didn’t need to think about state management so much because all my UI was coded in one file. Regular JS variables were declared and bound to user input via event handlers, then read into the metronome logic and UI.

In React, every UI component is its own module. So, after creating a static version of the UI, I had to consider the state. Which variables need to change and which components need to receive those changes?

Solution

I mapped the component architecture and then labeled which components needed to manage which state variable by identifying the nearest common ancestor for all components reading a particular state.

Component architecture map including where state management lives.
Component Architecture Map
Code snippet of user input react module managing state for variables Rhythm and Beat Count
UserInput module, managing state for rhythm and beatCount

Challenge 3: How to clearTimeout when each new render loses the timeoutID?

This was my biggest hurdle! I searched far and wide for solutions, using google, StackOverflow, slack groups, and more. At least half the answers were using the older class model of React, so I had to refine my search to React with Hooks. All the solutions/examples I found were for single timeouts that needed an automatic clearTimeout in case the user didn’t actively cancel the task. My problem was different in that I had a recursive timeout and I wanted clearTimeout to be triggered by an onClick event. None of these particulars matched the solutions I found.

The problem: each state change — and thus re-render — caused me to lose the timeout Id. So, when the user clicked ‘STOP’, React rendered the UI component again and lost the timeout ID, making the clearTimeout function useless. I tried useContext to maintain the timeout ID which I was losing, but that didn’t work. All of this searching prompted me to learn a lot about useState, useContext, and useEffect.

Solution

Digging deeper into the React Hooks documentation, I learned that although the useEffect hook doesn’t need to return anything (that’s typical), one can have their useEffect block return an arrow function and it will be called at the end of the component's lifecycle. So, just BEFORE the next render, when the component unmounts, the useEffect is returned. With this discovery, I was able to put my metronome logic into useEffect, and return clearTimeout. That way, when the user clicked ‘STOP’, it triggered a state change, but before unmounting the component and mounting a new instance, the previous useEffect is returned, clearing the timeout before the timeout ID is lost.

Code snippet of the useEffect block and its return.
The useEffect() block and the return() with all my essential metronome logic.
A flow diagram illustrating the order of execution for state, use effect, and mounting components in React.
The order of execution for State and useEffect in React

Challenge 4: How to use HowlJS — is it even needed?

HowlJS is a great javascript library solving many web audio challenges. It was a helpful tool in my vanilla JS version of the app that allowed my audio files to interrupt themselves and replay. Without Howl, metronome clicks would be skipped until the current audio file was finished playing. NOT GOOD!

Unfortunately, my Howl audio objects were not playing in the React version. I dug into the HowlJS documentation as well as google for information and examples of how to incorporate HowlJS in a React project.

I discovered people have developed necessary React Hooks to successfully incorporate HowlJS.

Solution

Before learning the API for a new HowlJS Hook, I thought about the magic of React. How it creates a virtual DOM and renders only the UI components that change state. I tested out making the metronome without Howl, and after some hurdles, it worked! The issue vanilla JS had with re-playing an audio file over itself was already solved by React’s state magic.

Conclusion

React is designed for dynamic data-driven sites, where data is requested from a server and then used by the client’s browser to render pages. React enables engineers to encapsulate UI components into modules that can manage their own state. This helps large organizations manage apps with lots of components. My metronome app isn’t requiring a large team to collaborate, nor does it need to pull data from a server. So, React was not the best tool for the job. However, I do recommend this study method for learning React or any other JavaScript framework/library.

First, build a project in vanilla JS, since at the core, that’s what all these front-end frameworks are transpiling to. The better you understand vanilla JS, the easier you will be able to work with higher-level frameworks.

Second, try and rebuild the app using React or whatever framework you want to study. Be patient with the challenges. Remember, your goal isn’t the finished product, it is to learn. So, welcome the challenges and all the solution digging they require!

More content at PlainEnglish.io. Sign up for our free weekly newsletter. Follow us on Twitter, LinkedIn, YouTube, and Discord. Interested in Growth Hacking? Check out Circuit.

--

--