Ladies and Gentelmen. Below is a story of love, hate and hope.
The development of moonpiano has been stalled for over a month due to my big move to Germany for a Data Science Position at vialytics.
In case you didn’t know, MoonPiano was developed in React and Electron. The project was smooth as long as the user was supposed to play easy songs. But in case he starts to smash the keys on this piano, the app performance would get worse, playback would be crappy and unhearable, let alone the UI freezes.
Technically, I have been using Redux to manage every state. The user can practice well, but pressing way too many buttons would lead to poor app performance due to slow UI updates. This happens especially in the new challenge mode that I have been working on, where keys that the user should press were highlighted but also the keys that he pressed already. This fires 2x more updates.
I have been stuck for a couple of days to solve the issue, no solution to be found. I have moved event handling outside of Redux back the normal react props way, where a master component would listen to the events and spread them to each keyboard key, but that also had me passing the props down a couple of components to reach the Key object of the UI Keyboard.
Now I am not the best React developer out there, but I have tried a lot of things. And this was a more than a month ago.
Solution? Switch from React to something else. Maybe
preact? Sure! There is even a compatibility layer with React. Neat. But even the compat layer does not fully support the react features the libraries I use. I even considered rewriting things from scratch with preact.
A final solution I had before my brain would explode is to try other Redux alternatives. A quick google search led me to this article: https://blog.logrocket.com/redux-vs-mobx/. I did read quiet a bit to be honest, but look at the final comment
This guy claims an incredible performance. With React? No way. Gotta see it with my own eyes. Quick look at the Demo and this example already got me very impressed: https://hookstate.netlify.com/performance-demo-large-table
It supports hooks from everywhere. My code does use Controllers that dispatch actions. Also this library allowed me to create unmounted hooks from my controller, and fire events from there which will be probagated down the keys. I have used this library for both highlighting keys that the user should press as well as coloring the pressed keys. The performance? Incredible. The app works smoother than I ever wanted it to be. And ofcourse, it can do much better now that I have this secret weapon.
This entire post, is to spread the word and make everyone aware of this awesome tool. I think it deserves more attention. Special thanks to @avkonst for making this happen.
Update (7 Nov. 2019):
As requested by in the comments, here a code that demonstrates the redux version performance. The libraries I have used are a bit outdated (I forked an existing redux code-sandbox), but the performance I encountred is pretty much the same. The update procedure is a bit naive, and the optimization I did using Hookstate is the same as this example: https://hookstate.netlify.com/performance-demo-large-form. The state holds an array but each value of the array updates a single Key on the Keyboard. Thus I had to tweak the
react-piano component for this, and defintely each Piano Key recieves a new props of its index in the array state gets updated.
Warning: Overusing the demo below will overheat your Mac and probably crash your browser tab (or all tabs).
Update (8 Nov. 2019):
New video demonstrating the performance boost: