Building a Beat Machine With React

Recently I completed my third hackathon with Mintbean.io. The challenge was to build a Beat Machine in 1 week. The application had to be a front end web application, no backend or server/serverless components were allowed to be used.

You can play with BeatJuice here 👉 : https://lnkd.in/gTE8iU9

The tech stack that was used was #JavaScript #reactjs #HowlerJS #MaterialUI & #FeaturePeek

BeatJuice in action

One of the first things we implemented as a group was a pull request workflow using gh pr create (github CLI):

This was a hugely beneficial workflow to follow as it gave each other a chance to review our code collectively and approve and fix merge conflicts ahead of time.

I also continued learning React and setting state using setInterval. One of the trickier aspects of the project was setting up the playhead and synchronising this with the playback of the music.

Something I would like to improve on is the modularity of code and passing props and state around. A lot of times with a project my intention is to make different components and keep the modular however one file always seems to take most of the load.

Long files! Okay for a hackathon but not following the single responsibility principle well! I want to improve upon this.

Originally I wanted to separate the BeatTracker component (playhead) and the patches however the issue was the counter couldn’t be passed down as props as it was just sticking on 0 and not iterating up. I think that was due to the setInterval logic acting too quickly dependent on the tempo.

I had to move all the components handling the playhead visuals to the app.js out of BeatTracker as well as the ResetSquares() function and GetPreviousSquare().

We had a component setup called useBPM to hold this function in a modular way.

There could have been other solutions to tackle the BPM such as using Howler.js’ inbuilt loop or webAudioAPI but I decided to try controlling the step with stateful logic:

The arrays above worked as a toggle for the playhead squares with a 0 = inactive and a 1=active

This was the underlying logic put into a useEffect to control the player. Originally as stated above I wanted more modularity with the code and to keep the animation and samples seperate however we were running into sync issues so I had to merge the logic in this file. With more time we could refactor the logic out of our app.js.

Folder structure and components

I’d like to draw attention to this line:

This line in particular is troublesome as React state should not be directly updated inside a component this way. The correct usage is

Our useEffect logic would follow this pattern:

Although the combining that with the setInterval like this:

also made the counter sporadically stick at 0 and not tick up to 16 at the speed of our formula (60 * 1000 / 4) / bpm so for 120 BPM this would be

(60 * 1000 / 4) / 120 = 125ms

I think the reason the counter doesn’t iterate upwards is because the logic may loop quicker than React can update the state hence the output would always be

I wasn’t able to find a way to put in the correct logic this would be one improvement I would like to make in refactoring. I think learning about other hooks like useContext, useRef and useMemo would be a workaround for this problem.

This project helped get me more practise with Functions Objects Conditionals, Loops and Arrays in JavaScript with objects and arrays to manage and access in the form of the squares and also whilst building our instrument bank:

I also used materialUI and CSS diving into the inbuilt properties to customise the buttons, sliders and icons.

MaterialUI provides inbuilt methods accessible via a theme object where you can change properties of the element you want to customise. In this case I am changing the default colour of a button, the outline colour and also changing the colour properties on hover.

MaterialUI button properties — changing button colours on hover

Future Improvements

As well as some of refactors I suggested above future versions of beatJuice could easily implement:

A clear pattern function — that clears the current pattern (without having to refresh)

A waveform visualizer — Howler.JS provides some methods to link into an audio visualiser so it would be cool to see the waveform as sound is playing.

JSON export /import— we already have the object set up to save out the 1s and 0s for our pattern so I think it would be easy to implement this so you could save the pattern.

Audio render — I think this would be another easy thing to accomplish with another npm package to give the user an MP3 file of their sample.

I had such a great time this on this hackathon and it was a pleasure to work with Yimeng Yu and Edward Smith via google meet. please check them both out on Linkedin!

Play with the beatJuice here: https://dashboard.featurepeek.com/peek/k5zh70zl#/

See the repo here: https://github.com/AndrewRLloyd88/beat-machine-hackathon

About the Author

Andrew is a dynamic full-stack developer and passionate learner who is comfortable speaking to clients as well as fellow developers. Eager to use cutting-edge technologies, alongside building long lasting applications and websites.

He is a graduate from Lighthouse Lab’s web development bootcamp, and is a part of the mintbean.io community.

He has learned and implemented various skills including

  • HTML5
  • JavaScript
  • JQuery
  • CSS3
  • MySQL/PostgreSQL
  • Bootstrap
  • MaterialUI
  • React
  • Redux

Prior to attending bootcamp in August 2020 his areas of work have been: administration, lecturing, film production and post-production and customer service across various sectors.

He would love to connect for opportunities and find a way to bring his knowledge and enthusiasm to your projects!

The Startup

Get smarter at building your thing. Join The Startup’s +786K followers.

Sign up for Top 10 Stories

By The Startup

Get smarter at building your thing. Subscribe to receive The Startup's top 10 most read stories — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +786K followers.

Andrew Lloyd

Written by

www.arlmedia.ca https://github.com/AndrewRLloyd88

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +786K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app