Building Zribbble, a Dribbble client for iOS

How I built my first iOS app using React Native, Redux, React Router Flux, CodePush and FeathersJS.

Catalin MIRON
5 min readAug 24, 2016

I have to say that from start to finish I had a great experience building this app even if I had some troubles and obstacles to overcome.

You can get Zribbble from the AppStore.

The first stage of the app was an OpenSource project on github and it was featured here by Mybridge. I’d also like to thank to @andreipicus for giving me access to react-native early beta (you know the super secret zip archive).

I’ll split this article in multiple sections since I’m going to cover almost everything from start to finish, from finding the right resources, building my own components, how I‘ve structured the app state and building the backend using FeathersJS last but not least the problems occurred during the app development.

Resources

I’m a dev that’s looking and searching for new things on a daily basis so, for this part I knew what will fits best for me, so let’s create the list with all the resources, plugins and snippets that I’ve used:

I’d like to thanks you all for sharing such great plugins :kudos:

Dribbble authentication

I have to say that my experience with NativeModules is zero and I didn’t had enough time to implement a wrapper for Dribbble auth natively. I do have some experience with Swift but not enough to build the entire bridge. I know that there are blog posts and resources but I thought that FeathersJS will fit perfectly for this app and it’s very simple.

The authentication with FeathersJS it’s simple, I made a path for the oauth http://domain/auth/dribbble that will set a cookie for JWT token that I’ll use to get the user info from the database. You can check more details about FeatherJS authentication.

Since the backend wasn’t a problem, the tricky part was establishing the connection between the app and the backend and that’s because I needed the JWT token from the FeathersJS in my app and now react-native-cookies comes into play. I’ll go through the whole process below:

  1. User clicks on `Sign in with Dribbble`
  2. A modal window with a webview pointing to /auth/dribbble will open
  3. I’ll listen to url changes using `onNavigationStateChange`
  4. If the `navState.url` is `success` and we have the JWT token is cookie (`CookieManager.getAll()`) I’ll establish the connection between my app and the backend using feathers().authenticate({type: ‘token’}).
  5. Otherwise I’ll close the modal window and let the user know that something went wrong.

Below you can find the snippet that does the authentication:

Managing the state with Redux

Managing state with Redux it’s very simple, especially when you want infinite scrolling, fetching data from the server, authentication but keeping the state organised it’s difficult, in my opinion.

I had some issues with the props and router history, when a user go from a shot to another and back and this is because I kept the shot to a key that I mutate over time so whenever a user decide to go back, I rendered the shot details with the last shot props.

Popular shots => Shot no.1 => Player detail => Shot no.2 => Player detail => Shot no.3 => Back(Player detail)=> Back(Shot no.2) had the same props from Shot no.3.

I fixed this by adding each shot details to shot.id key and get the shot details based on it without affecting the history or mutating the same object over and over and second there’s no need to refetch the shot details if the shot already exists.

This helped me a lot when I integrate the sharing feature and the only thing that I needed to do is to call `ShareAction.share(shot.id)` since I have the collection of shots, getting the shot title, description and author was just a simple mapping `{title, description, author} = shot_collection[shot.id]`.

Hot reloading

For me, this is one of the great features in react native because it lets you modify the code so deep in routing system without reloading the whole app. You can check the below gif where I’m showing you the power of hot reloading.

Routing

I’ve used react-native-router-flux just because I was comfortable with and I’ve used in my previous apps. The powerful thing in this lib is that you can change the route from any part of your application without extra work and nested routes by calling router-flux `Actions`.

Almost 60fps on infinite scrolling

I can optimise more that in this and in the future update you’ll all have access to better performance, there is no 60fps because the images are large 200KB+. The reducer code for the PullToRefresh and InfiniteScrolling:

Why $0.99 and not Open Source

There’s a lot of confusion since the first version of the app had a massive success, with over 1200 stars on github and now the second version of the app it’s closed source and costs a dollar. Being a lazy guy I couldn’t update the first version and I wrote the app entirely from scratch because

  1. I had more experience with React, Redux and other libs
  2. Rewriting something it’s harder than I thought.

So, if I have enough time, I’ll open source it and give you guys the source code of this beautiful app(in my humble opinion). Stay tuned!

Final thoughts

It was a fun and hard period during the app development, since in this period my wife gave birth to an angel.

Don’t forget to support me and my development and buy the app.

--

--

Catalin MIRON

dev@Skype; ex HootSuite | uberVU. React, React Native, graphQL and open source enthusiast. 🙃