Bean There: An app to rate coffee shops
I made an app to rate coffee shops as an exercise to learn React Native. The app allows users to rate locations based on customisable categories. Whilst it was designed for coffee and coffee shops, it could be used to rate any kind of place. The ratings are stored locally on the device and not uploaded anywhere.
The original idea was to implement the same app in React Native, Jetpack Compose, and Flutter, but I’ve only made the React Native version so far. I’ve started the Jetpack Compose version and will hopefully have time to finish it at some point.
But why? #
For the last few years, a friend and I have been on a mission to find the best cafe in our city. I’m a big fan of coffee; she likes hot chocolate. Whenever we meet up, we’ve been trying somewhere new and keeping a spreadsheet of scores for each place. You see, you can’t just have an opinion. You gotta back it up with hard subjective evidence. I rate based on the coffee’s appearance, bitterness, taste and the shop’s location and comfort. I like to work in coffee shops so that last part is important to me.
Last year, I wrote about native Android development and why I want to learn cross-platform. I’m quite a project-motivated person, I find it hard to learn something when I don’t have a project in mind. I’ve been on the lookout for app ideas since writing that article.
Whilst perhaps of limited appeal, I realised that an app to replace my coffee rating spreadsheet is something that I might find useful. It’s also a large enough app to be useful as a project to learn and compare React Native and Flutter.
Using the app #
When you open the app, you see a dashboard with an overview of recent ratings. You can also search for a location anywhere in the world from this page. For ease of use, results are biased by distance to your current location.
The Chains tab allows you to see a list of coffee shops grouped by chain. You can sort the list by A-Z or rating. Tapping a chain reveals a list of locations for that chain.
The location screen shows a gallery of photos and ratings. You can rate a location based on customisable categories.
React-Native and Expo #
React-Native itself is quite a bare framework. Expo is a platform built on React-Native that makes it much easier to develop apps, including support for generating the native code, live reloading of the app, and many helpful utilities. I chose to use Expo for these benefits.
Expo heavily promotes Expo Application Services (EAS) - a commercial cloud service for building and deploying Expo-based apps. I chose not to use this as I don’t like having hard dependencies on proprietary services. I don’t like how heavily Expo’s documentation promotes EAS and how little they document building and publishing apps yourself.
I use Redux and AsyncStorage to persist data. This stores select Redux state in a JSON-like NoSQL way. I am a big fan of relational databases; I like database-level constraints and easy relational queries. Using something so barebones was a little disappointing but it is simple and just works. This method does load the entire data into memory at start up, which becomes more of a problem the more I use the app. I also discovered that it has a timeout when loading the data, causing data loss when the saved data reached a certain size - luckily I had backups.
Achieving a native look and feel #
I want to be able to make apps for Android and iOS that look and feel native but actually use a single codebase. Matching Android’s Material Design and iOS’s Human Interface Guidelines is therefore quite important to me.
Each platform has different conventions for navigation and components. Whilst matching the look and feel of native components is nice, the most important thing is to match the feel and behaviour of native navigation conventions:
Whilst React-Native claims to use native UI elements, I found that they do not look or behave like native components by default. I ended up using a library called React-Native-Paper to do Material Design in the app, but this failed my goal as the app looks like Material Design on iOS. I believe the better approach is to develop your own library of reusable components that change based on the target platform. I am now leading a React Native project at work and I’m finding this to be much more effective.
Testing #
I used Detox for end-to-end UI testing. It was quite a pain to use. This is a common problem with e2e UI testing and it limits the number and quality of tests. Testing needs to be as easy as possible to be most effective.
I also used React Native component tests - these are unit tests for React components, allowing you to simulate user actions on a component and mock dependencies. I found this to be much more effective at exhaustively testing a lot of components, although it was a pain for anything that used async behaviour.
In the future, I’d like to look into using Storybook as an alternative to component tests. I’ve been recommended it a few times by people with more experience in React Native than me.
Conclusion #
This was a nice project to learn React Native and put me in a good position to start a React Native project at work. The speed at which you can introduce new user interfaces is quite addicting.
I could do without the pain of JavaScript land, the number of strange errors you get is just quite tiring. I also wish that React Native made it easier to make native-themed apps by default. I’d love to see a UI library for React Native with this as a goal.
Comments