Building the Open Targets Platform Interface using React

Open Targets Platform Jun 3, 2021

In the final section of the four-part series discussing the Open Targets Platform’s codebase, we delve into the User Interface. The Open Targets Platform UI presents, in a meaningful and accessible way, the rich data produced by the ETL that is served through the GraphQL API.

The full technical pipeline: (1) Platform Input Support ensures reproducible inputs to (2) the Extract-Transform-Load pipeline. The data generated by the ETL pipeline feeds into (3) the GraphQL API, which is used by the (4) front-end to access and query the data. 

For the newly redesigned Open Targets platform, we developed the UI from scratch using React. Since Angular.js is no longer maintained, the front-end team had a choice between going with the newer version of Angular 2+ or React. We chose to implement the UI with React because it has become the dominant UI tool for building highly interactive user interfaces and also because transitioning from Angular 1.x to Angular 2+ was as big of a change as going from Angular 1.x to React.

Given that the Open Targets Platform is a data intensive application, the data is served through a GraphQL API. This allows the UI to only request the data that it needs and avoid over fetching. We use Apollo Client, which is a library that provides us with an in-memory cache. It stores the data from GraphQL queries and helps avoid making new calls to the GraphQL API, improving the latency of the UI.

We use the Material-UI component library which provides us with a set of common UI React components. This helps us build the UI and iterate fast. We modify the components with custom CSS to fit our needs.

To keep page load times low, we split the code of several visualisation components with heavy JavaScript bundles. This allows us to lazy load JavaScript code only when it is needed. We also use React.memo where appropriate to prevent unnecessary re-rendering of React components as well as useMemo for memoizing the results of expensive computations.

Throughout the UI, we present the data with tables. In tables with limited data, we are able to load all the rows at once without a major performance hit. However, for tables with a large number of rows, we make use of server side paging to only request a portion of the rows to display in the UI. This helps reduce the memory footprint of the UI.

Future plans

We have many plans that we want to explore to keep improving the UI and our development process. We are currently experimenting with automatically generating TypeScript types from GraphQL queries. This will help us prevent introducing bugs when interacting with the GraphQL API since some deeply nested fields are optional and could be null.

As the UI grows, we want to experiment with route-based code splitting or server side rendering to improve even more the page load times. Finally, now that the UI is in a more stable state, we will be adding unit and integration tests.

Feel free to take a look at the frontend code and contribute here.

Previous posts in the series

Open Targets’ Platform Input Support: ensuring a reproducible ETL
In this first part of a series looking at the codebase which underpins the Open Targets Platform, we discuss Platform Input Support, our way of ensuring reproducible outputs for our ETL pipeline
Extracting, Transforming, and Loading Data for the Open Targets Platform
In this second part of a series looking at the codebase which underpins the Open Targets Platform, we discuss the Extract-Transform-Load (ETL) pipeline.
How Open Targets uses GraphQL to present Platform data
[3.5 minute read] In this third part of the series examining the Open Targets Platform’s codebase, we discuss the switch from REST to a GraphQL API and how it uses the data produced by the ETL pipeline through Elasticsearch and Clickhouse.


Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.