Ethereum for the React developer
Takeaways from building an overnight GO game with react
Recently I’ve joined forces with a great team of some gaming veterans in the development of a super-cool, first-ever, breakthrough game of GO, 100% based on the Ethereum blockchain. The game (which is actually classified as a dapp in the professional jargon) comprised of Ethereum smart contracts where the logic resided, and on the Front-end a React client where the game’s UI was brought into life.
Ah yes, there was also a minor super-easy non-brainer out-of-the-box integration to develop between React and the blockchain. Really, it was nothing and we already had everything prepared and figured out.
Or did we?…
As the deadline we’ve set for ourselves was quite demanding (we were looking to get feedback out of the MVP with minimum effort), and the entire app / game comprised of only 2 pages and some calls to the smart contract, no thorough architecture designs were in place and as soon as we got the UI designs we just started coding the React Front-end.
Let’s just get it done in no time
Well, time it took alright. We were using create-react-app so it wasn’t that bad on the bootstrapping and project config tasks. We quickly got to our basic set of components:
However, the real issue started when we had to integrate with the blockchain.
To give some context, we used Metamask to connect us to the blockchain. From the Front-end app viewpoint, you get a web3 component on the window object which facilitates your communication with the blockchain:
Metamask takes care of the transactions approval process so that all you have to do is make API calls to the contract and each payable contract method gets a Metamask payment popover before actually committing the transaction to the blockchain:
To get a nice API to the native web3 object exposed by Metamask we used the npm web3 package (not to be confused with the Metamask web3 object) which wraps the native web3 component and lets you call contract methods easily (more on that in a separate post).
Happy happy joy joy! We’re sending out events on the blockchain, things are moving, transactions are committed and everybody’s happy!
The fun lasted alright while we were using the local ganache development server, however when we switched to using the Ropsten test network, is when we realized we’re in dire need of state management.
You see, the blockchain is slow, much slower than any server you, as a React developer, have ever worked against. That makes notifying the user on the progress of any server calls ultra-important.
Moreover, a user playing the game should know the current score, current balance, time left for turn etc. All this data is coming from the blockchain and reading from the network is free.
So, how do we know when transactions are completed?
So up to here we have:
- React components
- Asynchnously calling methods on the blockchain, getting back a TX (Transaction ID) for each call.
- Getting data back from these methods once the transaction is complete.
- Watching events for completed transactions and notifying the user the transaction is complete.
- Storing all that into our state and our notification system.
- Managing all the above for multiple boards, each with its own state.
Taking all that into account on day 1 would simply spell out Redux, mobx or the like.
But, what do you do when you originally planned points 1&2 done in no-time and the rest maybe done later, in order to just get to your MVP ASAP with minimum effort?
What you do is you improvise. And you improvise on and on until… you build your own state management! Which is the worst and most time-wasteful thing you could do.
But again, it’s going to be ready tomorrow and there’s no sense to spend a full day adding state management & re-testing all you’ve built, right?
After working with Redux for almost 2 years, you can’t really build an on-the-go state management system that looks much different. So this is what you come up with:
Looks familiar? Yes, it’s mobx without observables, or redux without immutability, actions, or reducers.
Is it any good? Well, it solves your basic question of “where do I keep my state”.
Does it have any scalability coming with it? Central logging? Time Travel? No, and that’s the problem.
Initial values, null objects, refreshing components on props changing – all that has to be re-invented. And tested, and fixed.
The advantage of quickly scaffolding a game is long gone by the time you’re sitting late at night fixing bugs with your made-up state management system, instead of adding features to the game at hand.
Moreover, “ready tomorrow” becomes a cliché even you don’t believe in anymore.
So, is scaffolding-your-state-management-on-the-go a good thing or a bad thing?
Well, that depends. On the context.
Tell me that about any of my other React apps and I’ll tell you that you’re nuts and did all the classic mistakes of building a React app with no state management.
However, if you told me you’re looking to release an app within a few days and really you’re interested to first see how it catches fire and get validation first, I’d say splurge on it, you can always refractor / rewrite later.
Let me know your thoughts in the comments below!