OOP and RxJS: Managing State in React with Akita

Netanel Basal
Datorama Engineering
6 min readOct 9, 2018

--

🤔 What is Akita?

Akita is a state management pattern, built on top of RxJS, which takes the idea of multiple data stores from Flux and the immutable updates from Redux, along with the concept of streaming data, to create the Observable Data Store model.

Akita encourages simplicity. It saves you the hassle of creating boilerplate code and offers powerful tools with a moderate learning curve, suitable for experienced and inexperienced developers alike.

Akita is based on object-oriented design principles instead of functional programming, so developers with OOP experience should feel right at home. Its opinionated structure provides your team with a fixed pattern that cannot be deviated from.

👷 Akita’s Architecture

Akita’s Architecture

👁 High-level Principles

1. The Store is a single object that contains the store state and serves as the “single source of truth.”

2. The only way to change the state is by calling setState() or one of the update methods based on it.

3. A component should NOT get data from the store directly but instead use a Query.

4. Asynchronous logic and update calls should be encapsulated in services and data services.

Let’s learn about Akita’s core concepts by creating the traditional Todo application.

🤓 Core Concepts

The Store

The basic store can contain any form of data that you want, but in most cases, you will prefer working with an entity store. You can think of an entity store as a table in a database where each row represents an entity.

Akita entity stores give you all the tools you need to manage your store easily, such as CRUD operations on entities, active entity management, error management, etc.

First, we must define the store’s interface. We extend the EntityState from Akita, providing it with the Todo entity type.

If you are curious, EntityState has the following signature:

Note that in addition to the todos entities, the store root holds a state that contains the active ui filter. Here’s a visualization of our store:

Spoiler!! Akita supports Redux dev-tools.

The Model

The model is a representation of an entity. Let’s take for example a todo:

Akita recommends creating both a type and a factory function in charge of building the entity. ( in a case of an entity store )

The Query

The Query is how we get data from the store. Like the store, it has two types: query for basic stores, and query for entity stores.

You can classify the query methods into two types. A method that starts with select, for which you will get an observable for the requested data, and a method that starts with get, in which you will receive the requested data once and directly.

It’s important to emphasize that the subscription won’t be triggered unless the value you requested is changed by reference, freeing you from using something like re-select.

We extended the QueryEntity from Akita. Its constructor function receives as parameters its own store and possibly other query classes.

Here, you will receive from Akita a lot of built-in functionality, including methods such as selectAll(), selectEntity(), selectMany(), selectActive(), selectLoading(), etc.

The built-in select() method selects a slice from the store. In our case, we need to combine the active filter with the current todos to find the visible todos and display them to the user.

The Service

Akita recommends that asynchronous logic and update calls be encapsulated in services, so let’s continue by creating a service that is responsible for the todos crud operations.

The code is self-explanatory. We use Akita’s built-in methods to perform crud operations on our todos store.

⌨ Akita CLI

Akita offers a CLI tool, enabling you to generate stores based on the specifications quickly.

⏱ It’s Time to React

Akita encourages the modeling of smart and dumb (aka stateless and stateful ) components’ architecture. This combination allows us to use React’s PureComponent to improve performance.

If a component depends only on its props, and they are immutable, then this component can change only if one of its props changes.

Presentational Components

Presentational components describe how things look. Typically, they receive data via props and communicate via events.

Let’s create our presentational components:

Container Components

Container components are concerned with how things work. They provide the data and behavior to presentational or other container components.

Let’s create a TodosPage component in charge of displaying a list of todos filtered by the active filter:

The component reactively receives data from the query and delegates store updates to the service.

This is how we establish a one-way data flow with a precise architecture that you can’t deviate from.

Let’s see it in action with the dev-tools:

As you can see, Akita also supports store-based or entity-based redo-undo functionality.

😍 Akita in Datorama

Behind Akita there is a company — Datorama. Datorama invests a lot of time and effort in developing and improving Akita to make it better for us and the community, allowing us to give back to the community for all that it gives us.

Additionally, before we released it to the community, Akita was used internally here for over eight months, during which it passed our tests, bugs were fixed, and feature requests were added.

Our product is a big data product. We have vast amounts of data on the client, and Akita handles it amazingly.

😎 Not Only for Angular

Here in Datorama we work with Angular, so until today, Akita was Angular-oriented, although we’ve built it in such way that it is not coupled to Angular. Our goal was to create Framework-Agnostic state management that can work with Angular, React, Web components and vanilla JavaScript.

Actually we’ve begun to work with React on several internal projects. We feel that we’ve come to the point where we can push non-Angular developers to use it. We believe that, in addition to all Akita’s advantages, the beauty of Akita is that, when you’re migrating from one framework to another or reading our Angular-focused articles, the only thing that you’ll need to replace is the component implementation.

✋ But Wait, There’s More

Plugins ecosystem

Store enhancers

Articles

Our team created handful of articles so you can familiarize yourself with Akita quickly. We’ve created articles about infinite scrolling, state normalization, firebase and more.

Summary

We’ve seen here how the various core concepts of Akita work together to give us an easy way to manage our application state. This is only a small taste of Akita; it has many more additional features, including powerful plugins, dev tools, cli, support for active state, transactions, and web workers.

#Example One

#Example Two

Here is a complete working example including session management:

#Example Three

Here is a complete working example that demonstrates the active entity management functionality.

Follow me on Medium or Twitter to read more about Angular, Akita and JS!

--

--

A FrontEnd Tech Lead, blogger, and open source maintainer. The founder of ngneat, husband and father.