I feel weird writing about React. I’m not a contributor or upstanding community member. I’m not even an early adopter – we only started working React into Crashlytics about six months ago.
I’m a fan, though. A huge fan. And even though I thought I was the last person to this party, I keep running into frontend developer pals who haven’t given React a try.
Let’s change that!
The models who couldn’t save themselves
How could this be? I had a Group model object, a whole collection of them in fact. You can see them right there in the sidebar. They each had their IDs, and their collection was very clear about how to turn those IDs into URLs. And yet, somehow “save” was broken. Why wasn’t it making its URL?
Let’s be clear, this is my bug. And – full disclosure – I wrote it when converting some other parts of the UI to React. I was finding the Backbone Collection’s “set” method to be too chatty announcing change events, so, for the code that updated our global Group collection in response to a periodic server poll, I changed over to “reset” instead. It even seemed more correct, in my mind: make the groups list exactly like the latest state from the server.
Unfortunately, “reset” works by first emptying the collection of its existing models, then re-populating it. That emptying carries the consequence that those previous occupants — such as the Group object that the editing UI had a reference to — would be orphaned, no longer a member of anything. No parent collection meant no “url” method, and that meant no way to save.
I felt a bit stupid for having caused such a regression, but that was eclipsed by my frustration that such a bug was even possible. Model objects that are capable of saving themselves had already been a pet peeve of mine due to how they hindered testability, but now I found model objects that could arbitrarily lose their ability to save themselves in the middle of my program!
This was a mutation bug on steroids: an object’s functionality changing not even due to local state modifications, but by whether or not another object was holding a reference to it. How could I reason about behavior if this possibility was lurking in my code? What automated test would have even exercised this?
I was determined. I was vengeful. It was now time to, as they say, React all the things.
The DOM Doctors
Doubling down on a new UI rendering library might seem a strange way to solve a model logic problem, but React has the remarkable power to send ripples of correctness through your codebase. Consciously or not, libraries like Backbone end up encoding assumptions about how views work in their data classes. If we fundamentally changed how rendering happens, why wouldn’t that affect how we managed data?
If you’ve heard anything about React, it’s probably that it has a “virtual DOM” that makes its HTML fast using an efficient tree diff algorithm. If you’re like me, the first time you heard that you may have dismissed it. My HTML isn’t slow.
And maybe it’s not that slow, but only because we frontend developers learned not to push it. We joined together our template strings for one big innerHTML splat at the outset and then just modified individual elements going forward. We couldn’t conceive of being so callous as to re-render an entire dialog just because a group’s name changed. We were good programmers, we were precise. We were surgeons, jQuery was our scalpel, and when the “name changed” event came in we made only the tiniest incision in the page to bring it up-to-date.
There’s another reason for why we stepped lightly in the tree: DOM elements are stateful beyond how we created them. They have focus, or scroll positions, or in-progress edits. Some cavalier re-rendering wouldn’t just be slow, it would stomp user data at the same time. And that, at least, was unacceptable.
These constraints had a profound effect on our code. We couldn’t just write the state of what our UI should look like (“the button is disabled because a network request is in progress”). Instead, we were condemned to write the state transitions between those UIs. On network request start? Add class “disabled.” On complete? Remove class “disabled.” If we were lucky, we found all the ways that state tended to linger on our pages. On showing a form? Remove any error messages from the last time we showed this form.
Testing this style of code is both painful and approximate. On top of exercising your initial rendering, you need to test your transitions. They need plausible prior states just to run, but to have good coverage you need to test them against each important variation of prior state that your application is capable of getting itself into. A “finite” state machine perhaps, but only in theory.
Spared from Change
Enter React. The real benefit of that O(n) tree-diffing algorithm isn’t performance per se. It’s that it frees us from having to hand-write every state transition in our UI. Besides reducing drudgery, that actually eliminates the entire class of leaky-state bugs mentioned above. If you declare that your UI is a dialog with an active button and no error message, React will transition to exactly that, performing DOM manipulations that ensure that your button is active and no error message is seen. Any vestiges of previous state are cleansed with no extra effort on your part.
Fundamentally, your old state transition code was a function over your application data, but also over the previous state of the UI. That’s why you needed to consider varied “prior states” when testing. In contrast, your React rendering code is a function over just the application data. You can imagine how much more pleasant that makes your tests.
The real answer to how “just” a view library can affect your data handling is that React is a view library because that’s all that it needs to be. When I talked about the Backbone data classes having assumptions about the way you displayed your UI, I was thinking of mutation handling and attribute-level change events. If you’re writing minimal state transitions, that kind of information is important for doing precise DOM surgery. If you’re writing a React component, though, where declaring UI state is cheap and getting to it is fast, the only notification you really need is “something has changed, probably.”
Since all you need are coarse-grained change notifications, your data objects can be correspondingly simpler. One could argue that React even works best on just plain hashes and arrays. All you need is for a data source to hand your component hierarchy the latest values, and everything flows efficiently from there. No mutation-tracking, self-saving, collection-inhabiting model objects necessary.
Efficient coarse updating also enables what may be my favorite part of React: props and state.
In a correctly-written React component, the only inputs to the UI rendering method are its “props” and its “state.” These are exposed as a pair of hashes on the component object, and changes to either of them cause the component to re-render. (Something has changed, probably.)
The difference between the two is how they change. “props” can be thought of as the input from the outside world. It’s set from the parameters your component is called with, and its values should be treated as immutable. “State,” on the other hand, is the data that’s owned by your component. You update it via the “setState” method, and no one else should be changing it on you.
To give a concrete example, consider a component for editing a group. The props would include the group’s name, while the state might be whether it’s showing a “delete” link or the “confirm” / “cancel” buttons that appear instead when that link is clicked.
This may seem like just a helpful little pattern, but by calling out this distinction between props and state, React has bestowed an enormous understandability boon on your code. Gone is the catch-all “options” hash that contains everything, internal and external. Your data is going to naturally fall into one hash or the other, so there’s one fewer choice to make when structuring your component, and, more importantly, one more signal of your intent when your team comes back to your code months later to extend it.
In practice, the state of one component actually ends up trickling into its child components as props, and establishing your intention is even more valuable. When the same data is “state” here and “props” there it’s perfectly clear what level of your component hierarchy is responsible for coordinating its changes.
Finally, when you consider testability, you can, in almost every case, proceed in ignorance of changes to your component’s props. So, while you and I both know that group names can change, all the component that renders the list of groups in the sidebar needs to do is render the names it’s given. If they change, it’ll be given new names, and it’ll render them just the same. No need to waste time in your tests verifying that case.
Path to salvation
React is fascinating because it takes this rather clever little algorithm for fast tree diffing and follows it to its logical extreme, introducing an incredibly effective paradigm to web developers: If we can diff in O(n) time we can quickly convert one DOM tree to another. That means it’s efficient even if the difference is small. It also means we can keep that partially-filled <input> around. That means we can do coarse-grained updates for any change. That means that re-rendering can be triggered automatically by the framework. That means we can have a simple, standard pattern for state management. And so on.
As a library, React doesn’t really let you build anything that you couldn’t do before with any other UI framework. Maybe some things will be more performant out-of-the-box, but functionality-wise your product will be very much the same. What React gives you instead is much less, better code, sooner. Declarative UIs are faster to write, simpler to test, and far far far easier to reason about.
It feels like nothing short of giving you frontend engineering superpowers.
Hopefully this has whet your appetite for React. Maybe it will be as revelatory for you as it has been for me. Soon, I’ll follow this post up with some more specifics about how we’re using React on Crashlytics, why you don’t need JSX, and our take on a unidirectional data flow pattern
We’re helping our customers build the best apps in the world. Want to be a part of the Crashlytics team and build awesome stuff? Ping us @ firstname.lastname@example.org. We look forward to chatting with you!
(Big thanks to Kevin Robinson, Sam Neubardt and Sam Phillips for contributing to this post.)
When Apple introduced Swift, their new programming language, at this year’s WWDC, like you our engineers didn’t waste any time and dove in to see what it was all about. After spending the past few months testing out support in our developer preview, we’re excited to announce Crashlytics official support for Swift!
Build How You Want, Where You Want
At Crashlytics, we’re huge supporters of making it as easy as possible to develop mobile apps. When Apple promoted Swift as a language that was easier to read and maintain, we knew we wanted to get on board. In anticipation of Apple’s upcoming announcement, we’re rolling out our official support so that developers can quickly get up and running. Our support for Swift provides developers with the flexibility they need to build inside their existing workflows and streamline the overall development process.
Our engineers worked tirelessly updating our backend to support the demangling of Swift crashes and took meticulous care to preserve our seamless onboarding and pristine UI. To provide you with a customized onboarding experience, our Mac app allows you to choose between building with Objective-C or Swift. Whether you’re new to Crashlytics or migrating to this new language, you’ll experience the same powerful features, combined with native support for Swift based builds.
We love supporting developers as they continue to experiment with new and improved ways for building mobile apps. We’re excited for the launch of Crashlytics support for Swift, get started here.
Today, we’re excited to unveil our latest project: Answers by Crashlytics. Finally, mobile analytics you don’t need to analyze.
When we first launched Crashlytics more than two years ago, we were focused solely on solving the problem of mobile crash reporting. Since then, we’ve seen a need for powerful tools across other areas of app development — and we knew that we could apply the same design principles to meet the many challenges faced by today’s mobile app developers. With Answers by Crashlytics, along with our award-winning crash reporting tool and Beta by Crashlytics, developers now have access to a powerful, lightweight suite of products to help them not only build, but also grow great apps.
It’s been an honor to work with many of the top iOS and Android mobile teams as we have crafted Answers, and we’ve received incredible feedback:
We have Answers by Crashlytics displayed on two of our big TVs (one for iOS and one for Android) so the entire team can view the live updates of our app’s key metrics — everyone loves it!
Lars Vedo, Mobile Product Manager,
Terms like ‘bloated’, ‘bulky’, and ‘unreliable’ should never describe any developer tool. We know how hard it can be to gather real-time data, gain actionable insights about user behavior, and iterate quickly to optimize your app. Don’t worry — this is what we do.
Answers streamlines the process of revealing the key drivers of your app’s growth. With just one click, and no extra code changes, you’ll have the power to understand your app’s key usage and retention metrics. We intelligently and quickly send data at low impact times to optimize and reduce traffic on your app. Built into our existing Crashlytics SDK, Answers gives you instant visibility and a constant pulse on your app’s key metrics. And it’s free.
A Dashboard That Makes Sense
Your time is precious. We don’t want to bog you down with data overload. Answers streamlines your day with a UI that calls attention only to your most critical app usage metrics. With full visibility into your growth and engagement indicators, you can immediately understand the current state of your app and intelligently decide where to invest your time.
See a spike in activity? We’ll tell you why. No more guessing if an increase in daily actives is a result of new users or your existing users becoming more active. We’ll connect the dots for you.
And if you’re anticipating increases in usage related to a major event, you can see at a glance how many users are engaging with your app at this very moment. Bring the popcorn and display this data for your team to watch the action live.
No Analysis Required
Once enabled, Answers by Crashlytics intelligently analyzes and learns your app’s behavior and begins delivering live data within minutes. We know you’re busy, and we’ve built Answers with that in mind. You no longer need to don a lab coat and pull out a calculator to understand what’s going on. We look at the long-term trend and understand that there are certain metrics that are cyclical, so we’ll proactively alert you when a pattern is truly abnormal.
You’re constantly pushing out new features and bug fixes, so you’ll want to understand how your top builds compare and how users are engaging with your latest build. View build adoption over time to see the stability of each build with a breakdown of session length and crash-free users per build.
All About Growth
We know that retention is an important metric for understanding growth — that a large increase in new users doesn’t always translate to a long-term increase in your monthly actives. At a glance, monitor what percentage of your new users are coming back within a day, week, or month of installing your app for a clear picture of true user retention.
Sometimes, simply knowing usage numbers isn’t enough to understand overall performance. Answers dives deeper, showing you the total number of user sessions and the average number of sessions per user. For more granularity, we include the median session length, along with the amount of time per day the average user spends in your app. What better way to know that your users are having an awesome experience than to see them spending more time in your app?
Finally, app stability is crucial to ensuring your users have a great experience. Know how many of your users are having crash-free days and crash-free sessions and instantly see the top issues related to your app’s stability. Since Answers is built into the same SDK that powers your crash reporting, you can immediately dive into the issues that have the greatest impact and start fixing bugs.
Experience the Power
This is just the beginning. Our engineers are already working to take Answers to the next level and we have a lot planned. As always, send us your thoughts at email@example.com or find us on Twitter @Crashlytics. We’d love to hear what you think we should tackle next.
If you already have a Crashlytics account, you’ll soon see the new Answers tab on your dashboard. Otherwise, sign up here to get started with Crashlytics.
Don’t just take our word for it:
Answers by Crashlytics is the first thing I check every day. Its breakdown of crash-free users and crash-free sessions are the fundamental metrics we use to measure the stability of our app. I can’t imagine shipping an app without it.
Ryan Johnson, VP of Mobile Engineering,
Answers by Crashlytics is exactly what we’ve been looking for! We just launched a new version and it was amazing to immediately compare it’s stability to our previous versions.
Philip Connaughton, Software Engineer,
Highlights from Twitterverse:
Just one year ago, we announced our open-sourced integrations, inviting the developer community to build on our existing infrastructure. Since then, we’ve had many developers build and submit integrations that are used today by thousands of other developers! We’ve loved seeing the community support and are excited to announce three new integrations to help you strengthen team collaboration and manage your projects.
Since you’re constantly multitasking, we know you’re relying on Red Bull and to-do list tools like Trello to help you manage and prioritize your workload. Our integration with Trello, built by Andrey Chernih, allows you to turn your crashes into Trello cards. Add your crash cards to any of your Trello boards so you can see what crashes need your attention and collaborate with your team to understand who is working on each crash.
Built by Mufri, our Bitbucket integration turns your crashes into Bitbucket issues that are added to your preferred repository. We know your time is valuable and with this integration you can seamlessly jump from your Bitbucket repository directly into your crashes. With this seamless integration, you now have more time for the fun stuff, like coding the next hottest app!
We understand the importance in team collaboration and being in constant communication to understand who’s working on what. Andy McSherry built the Crashlytics integration with messaging service Hall. With this integration, messages are posted into your preferred group so you can quickly and easily communicate with your team about your crashes. No more waiting by the water cooler to track down teammates for status updates, we’ve got you covered.
Interested in adding your own integration? We’d love to work with you and see what you can come up with. See our existing integrations and get started.
At Crashlytics, we’re passionate about building tools that developers love. Three months ago we announced a new Crashlytics Labs project: a beta distribution tool to simplify the process of sharing apps with testers. Since then, we’ve seen an overwhelming demand from iOS and Android developers wanting to get their hands on our latest tool, and the feedback has been outstanding.
I love that we can manage everything from testers to builds in one place — for both iOS and Android. This is a huge improvement in our workflow.
Hundreds of top mobile developers have already distributed their apps to thousands of testers, and we still have people excited to experience what all the hype is about. In response to this demand, we’re excited to announce the official launch of Beta by Crashlytics. This means it’s now fully supported by our engineers, designers, user experience folks and amazing support team, among many others. This also includes a rapid release cycle, so you can expect continuous updates for features and bug fixes automatically and on a regular basis.
The Most Streamlined Beta Distribution Experience.
We’ve heard your frustrations about the state of beta distribution today. Poor UI, confusing registration systems, frequent downtime, and only single-OS support. It’s time to build something usable with both developers and testers in mind.
We applied our Crashlytics power and polish to this problem. The result: a streamlined experience for distributing apps that gives you a single, cross-platform toolset for iOS and Android. Beta distribution should be an intuitive process for you and your testers so you can focus on what matters — building your app, not stressing about getting testers up and running.
With Beta by Crashlytics, you can easily invite new testers through a seamless sign-up workflow, manage testers on the web or right within your IDE, and analyze key metrics to determine when your app is ready for prime time. Combined with our crash reporting solution, there is now a one-stop-shop for debugging and distributing apps. Oh, and it’s free.
Your App, Front and Center.
With the R&D efforts inside Labs, we’ve applied many of our major breakthroughs to Beta by Crashlytics. With only one chance at a first impression, it’s crucial to deliver a high-quality, fluid tester experience. Beta by Crashlytics helps you invite or onboard testers and send builds with just a few clicks. We authenticate the device without requiring user registration. This results in a dramatically noticeable reduction in the time it takes to get your testers up and running.
Your app and brand should be front and center, not buried behind unnecessary UI chrome or colors. Beta by Crashlytics intelligently analyzes your app’s icon and automatically tailors the tester experience to match your apps’ color scheme. The experience for your testers will be seamless and consistent with your brand.
Your Workflow, Uninterrupted.
Beta by Crashlytics is deeply integrated with our existing IDE plugins for Xcode, Android Studio, Eclipse and IntelliJ. You can now invite testers, distribute new builds and enter release notes all via our Mac app or Android IDE plugins. Using a build server? We’ve got you covered. Just upload your build, add testers and you’ll be up and running with just a few tweaks to your build script.
To ensure testers have a great experience, we’ve taken a proactive approach when working with Apple’s provisioning portal by identifying testers that you’re missing UDIDs. On Android, as soon as your testers install the Beta by Crashlytics app, it’s automatically customized and bootstrapped so your app is ready to be launched and tested.
All Your Testers, All in One Place.
The only thing more important than getting your testers up and running is managing and understanding their status. With our web dashboard, you can view the progress of your testers in a sleek racetrack UI. At a glance, you’ll see who is most active or who is still ignoring your invitations. Also, see a high-level view of most recent tester activity to identify new tester status.
Collaborate with your team without being in the same room. Our audit trail shows the most recent developer activity as your team distributes, updates release notes and invites more testers. Want to troubleshoot reported issues with your app? See a high-level overview of your top issues. With just one click you’ll be in your Crashlytics Issues dashboard, with all of our deep analysis tools to help you debug the most complex crashes. Get performance insight, starting with beta testing, all the way through App or Play store distribution.
Don’t just take our word for it:
Setup was a simple drag-and-drop, and the process for sending builds to testers is a no-brainer. This is exactly the beta distribution solution we’ve been waiting for on Android!
We do several hundred internal app releases a year and many times twice a day. Crashlytics has made this monotonous task, ultra lightweight, efficient and painless.
Crashlytics’ beta tool is, hands down, the simplest to use. Getting started took almost zero effort and their integration with XCode is excellent. I love how it does all the work of preparing and distributing builds for me all the way down to automatically detecting new archives.
Highlights from Twitterverse:
Whether you develop for iOS or Android, are working at a large company or hustling as a freelancer, chances are you’re hacking on many apps at the same time. Working on all these apps leads to the pain of managing all their notifications, which we know can sometimes be overwhelming.
We love supporting you in your development efforts and we heard you loud and clear when you told us that you wanted more control and simplification when managing your settings. Thanks to all your feedback, we set out to make managing your settings a top-notch experience, so you can get back to the fun stuff: writing code and building the next big app for millions of users!
Seamless, Intuitive Navigation
We started off by revamping our UI, moving away from modals, and utilizing a full canvas, providing ample space to display all your settings details. Previously settings dashboards were organized at the app level, which required you to switch between each app in order to access the app’s settings. To make this process easier, we added high level lists with views allowing you to instantly access the settings of all apps under your account.
For those of you who manage many apps, belong to many organizations, or have large teams, we’ve added searchable fields for each category. Our new search offers a seamless, real-time filtering based on your query term, so you can quickly and easily find what you’re looking for with very little effort.
Powerful, Streamlined Notifications
With our new notifications we want to put the control in your hands for whether or not you receive alerts for your apps. Previously our notifications were very granular and required more management, especially when adding a new app. We’ve tailored this experience so that you only have to set your preferences once! By choosing “watch”, you automatically assign the preferences you’ve selected to all your apps, or you can stop watching to not receive any notifications for a particular app.
With multiple apps in your account, it can be overwhelming to adjust their settings individually. Our new dashboard offers a completely streamlined process for you to select how you want to get notified. As you view your list of apps, you can easily toggle between watching or not watching. We’ve also added the ability to set a default category for new apps that are added to “watched” or not.
Intelligent, Flexible Email Routing
One of the most widely requested functionalities that we included in this revamp is the ability to assign a confirmed email address to each org when receiving notifications. For developers with multiple orgs, we understood the need to customize where you receive your notifications. You can now assign a confirmed email address for each of your orgs to receive your notifications!
Lightweight, Premium Performance
With this new functionality also comes significant performance improvements. While we’ve added significantly more data requests and provided more information for each request, we’ve increased page speed by over 4200%. Moving away from modals to URL driven displays allows you to quickly access the information you need and jump right back into whatever it is you were working on! With these speed improvements transitions to and from settings are faster allowing you to get in and out of settings quickly dive back into your dashboard without disrupting your workflow.
Optimized Collaboration Experience
It’s now easier to invite multiple members of your team to join your org, all at once! We want to help you get your team up and running as quickly as possible, so we’ve simplified the process of adding team members.
We are very excited and proud to show you our new Settings dashboard. We hope that this will give you the best experience in managing your app settings and help you achieve top performance for all your apps. Log in to your new settings dashboard or sign up for Crashlytics and give us your feedback!