Introducing visx from Airbnb
A collection of expressive, low-level visualization primitives for React
After 3 years of development, 2.5 years of production use at Airbnb, and a rewrite in TypeScript we are excited to announce the official 1.0 release of visx (formerly vx). You can find the project on GitHub and browse documentation and examples on airbnb.io.
At Airbnb, we made it a goal to unify our visualization stack across the company, and in the process we created a new project that brings together the power of D3 with the joy of React. Here are the advantages of visx:
- Keep bundle sizes down. visx is split into multiple packages. Start small and use only what you need.
- Un-opinionated on purpose. Bring your own state management, animation library, or CSS-in-JS solution. Odds are good your React app already has an opinion on how animation, theming, or styling is done. visx is careful not to add another one and integrates with all of them.
- Not a charting library. As you start using visualization primitives, you’ll end up building your own charting library that’s optimized for your use case. You’re in control.
And most importantly — it’s just React. If you know React, you can make visualizations. It’s all the same standard APIs and familiar patterns. visx should feel at home in any React codebase. We’re excited to see what you build with it!
The Problem: Visualization for Frontend Developers
Data visualization is increasingly relevant to more people from varied backgrounds, and that diversity necessitates visualization authoring frameworks that cater to the skills and needs of those individuals.
One such group of authors are frontend developers, who are increasingly tasked with creating visualizations for the web. A wide range of great libraries and frameworks for authoring web-based visualizations are available — from D3, Highcharts, Plotly, ECharts, Victory, G2, Recharts, react-vis, vega, vega-lite, to Semiotic and so on. However, upon evaluating over a dozen existing libraries for use at Airbnb, we found that most fall short in at least one of three areas that our frontend developers value:
- Learnable. (how much learning is required to build and maintain a visualization) — Most frontend engineers are not visualization experts, and the ramp up time or cost of context switching for D3’s imperative API or vega’s custom grammar are non-trivial in a large organization. Ideally, engineers should be able to learn a visualization library as quickly as other frontend packages.
- Expressive. (is it possible to create almost anything you can imagine?) — To use a single visualization framework across a large organization, it needs to support both simple charts — say for Airbnb.com — and highly custom visualizations for internal data products. Should your design capabilities be constrained due to chart library limitations? We don’t think so.
- Performant. Frontend developers who are building production applications — like Airbnb.com — must be able to optimize speed and bundle sizes. One-size fits all chart frameworks with built-in animations, custom styling, and special event handling may not be desirable and bloat bundle sizes.
Others have noted that there is often a direct tradeoff between expressivity and learnability in visualization tooling, so how could we possibly create a library that achieves high marks across those dimensions and also be performant? One word: React.
The Solution: Low-level React-centric Visualization Primitives
In recent years, React has become a mainstream web framework in part because it has a highly readable, declarative API that promotes clean code and maintainability. React is familiar to many frontend developers and there are extensive resources for performance tuning and optimizing React applications. Leveraging React and its ecosystem would provide learnability and performance, and a low-level, modular API would deliver expressivity.
When describing this vision, two common questions arise:
“Why not just use D3 — which is highly expressive — inside a React app? “
You can! But because D3 and React both want to own DOM manipulation, we’ve found that it’s best to only use D3 for the math and React for the DOM because two mental models for updating the DOM opens the door for bugs to sneak in. However, using D3 solely for math means a significant amount of its (DOM-based) functionality is not available for use: selection.join, zoom, drag, brush, and transitions. Additionally, as mentioned above, D3 has its own learning curve and we would like developers to feel like they are writing native React code with standard APIs and familiar patterns.
“Why not just use one of the many existing React visualization libraries?”
In our research (Figure 1), we found that existing React visualization libraries are often high-level abstractions and optimized for ease of use (i.e., fewer lines of code) at the expense of expressivity. None offer the expressivity of D3 primitives and many don’t allow for the optimization we want in production because computation, animations, state management, styles, and rendering are all encapsulated.
Looking at the problem space in Figure 1, there is clearly an opportunity for a highly expressive React library to thrive. By creating low-level visualization primitives with a first-class React API, we hoped we could deliver learnability, expressiveness, and performance that any frontend developer could pick up. And visx was born 👶.
visx: Tell Me about It
visx (previously vx) stands for visualization components, and is a suite of over 30 separate packages of React visualization primitives that fall into several categories (Figure 2). It is un-opinionated on state management, animation, and styling so it can integrate with any React codebase, and its emphasis on modularity (similar to D3) lets you keep your bundle sizes down by only using the packages you need to create your reusable chart library or a custom one-off chart.
How does visx use D3?
Some packages use D3 for math and layout calculations, and functionally mirror the underlying D3 package with a declarative React API — like @visx/axis, @visx/geo, @visx/hierarchy, and @visx/shape. Other packages replace the DOM-manipulating functionality of D3 and bring first-class interaction primitives to React — such as @visx/brush, @visx/drag, and @visx/zoom.
What visualization “things” does it do that D3 doesn’t?
Many packages are entirely distinct from D3 and abstract solutions to common engineering problems we faced when building pixel-perfect visualizations in React. Many of these abstract and simplify challenging measurement tasks in React and simplify SVG APIs. Some specific examples:
@visx/gradient , @visx/pattern (sandbox)
What can you do with visx?
We’ve been using visx for the past 2.5 years on dozens of internal data tools and Airbnb.com visualizations (Figure 3).
We have also leveraged visx to create higher-level, reusable chart libraries to reduce boilerplate code for common, simpler uses (Figure 4).
visx sounds interesting, but I love D3
We love D3 too! 🙂
How has visx evolved over time?
Over 3 years we’ve evolved visx along three primary tracks of work:
- Functionality As we incorporated visx libraries into Airbnb web apps, we naturally encountered limitations (e.g., no support for interactions, missing chart types or layouts) or found ourselves re-implementing the same thing repeatedly (e.g., legends, tooltips). Over time we added this missing functionality to packages or contributed our solutions back in the form of entirely new packages.
- Documentation 30+ packages are not useful unless people can use them, and the number one community request in vx was better documentation. We’ve recently improved the coverage of our documentation across all packages, interlinked package API documentation to multiple blocks.org-like examples per-package, linked all examples out to codesandbox for easy tinkering and sharing, and redesigned our project site for the visx rebranding (Figure 5).
Through this work and the help of great contributions from folks like Krist Wongsuphasawat, Sean Lynch, Conglei Shi, Andy Fang, Jordan Harband, Miles Johnson, Sergii Rudenko, Evan Conrad, Fabian Gündel, Noel Schnierer, Dennis Jjagwe, Xiang Gao, Jason Brown, Elijah Meeks, and Susie Lu, we’ve grown the GitHub following to over 7.5k stars and hope it’s just the start! Check out issues with the “👋 help wanted” or “🐣 beginner friendly” tags to get started, we’d love for you to join us!