Introduction to App's Digest

Introduction to App's Digest with React

Introduction to App's Digest

App's Digest is an open source state management library for JavaScript applications based on the publisher-subscriber pattern and inversion-of-control (IoC) container design principle.

App's Digest allows you to have centralized locations (stores) with units of state (atoms) that your application can subscribe to. Unlike other state management libraries, App's Digest only triggers strictly-needed, isolated updates for computations (e.g. React components) subscribed to atoms.

With App's Digest you can manage your application state outside of any UI framework, making your code decoupled, portable, and testable.

The library name was inspired by the general-interest subscription-based magazine, Reader's Digest.

Why App's Digest over other state management libraries?

  • Simple and un-opinionated
  • Makes hooks the primary means of consuming state
  • Less boilerplate and no provider wrapping
  • Centralized, atomic and subscription-based state management

In this tutorial, we will:

  • Explain App's Digest core concepts
  • Explain App's Digest usage
  • Use App's Digest store with React

App's Digest Core Concepts

App's Digest leverages on two software architecture patterns:

  • IoC Container pattern (a.k.a. DI Container) to manage store instantiation, dependency injection and lifecycle.
  • The publisher-subscriber pattern to implement values within the stores that any JavaScript context (including React components) can subscribe and publish to.

App's Digest Flow

App's Digest Flow

What's a Store?

A store is essentially a bucket of values that other JavaScript objects can subscribe and publish to. The stores live as long as they have at least one reference in the container. Once the last reference of a store is removed, the store is disposed.

What's a Value?

A value is the atomic part of the store, which can be subscribed/published to. Each value is independent from other values (unlike redux, where the entire application state lives in a single object), so every update to the store values is performed in isolation, and only the interested parties (subscribers) will be notified of the update.

What's a Computed Value?

A computed value at its core is just a "complex" store value that uses other store values as input to produce derivations from them. We can compare this behavior to the selectors in redux-reselect.

Demonstration

To demonstrate how App's Digest works, we will create an example implementing a counter store.

Creating a Store

To begin, we will create a basic representation of the store using a class:

class CounterStore { }

Creating Values

Our store needs values it can update and keep track of. So, let's import AppsDigestValue and create our first store value:

import { AppsDigestValue } from 'apps-digest'; class CounterStore { count = new AppsDigestValue(0); }

Updating Values (setters) (optional)

Setter methods in a Store are optional, but it is a good practice to follow the single-responsibility pattern, which ensures a single source of update.

import { AppsDigestValue } from 'apps-digest'; class CounterStore { count = new AppsDigestValue(0); increment() { const currentCount = this.count.value; this.count.value = currentCount + 1; } }

Exporting our Store to be used

Now that we have our store and its value, we need to export our store.

import { AppsDigestValue } from 'apps-digest'; class CounterStore { count = new AppsDigestValue(0); increment() { const currentCount = this.count.value; this.count.value = currentCount + 1; } } export default CounterStore;

Subscribing and interacting with our App's Digest store

Now that we have our store, we can use it anywhere within a JavaScript application by getting its instance via the container.

import { AppsDigestContainer } from 'apps-digest'; import CounterStore from './CounterStore'; // get the App's Digest container singleton const storeContainer = AppsDigestContainer.getInstance(); // use the container singleton to get (instantiate) store instances const counterStore = storeContainer.get(CounterStore); // subscribe to our counter the value const subscriberId = counterStore.count.subscribe((count) => { console.log(`Current Count: ${count}`); }); // update our counter using our setter counterStore.increment(); counterStore.increment(); counterStore.increment(); // unsubscribe from the value counterStore.count.unsubscribe(subscriberId); // dispose the store storeContainer.remove(CounterStore);

We'll se the following result:

See this live

Please visit our App's Digest Codesandbox to see a live example of the vanilla JS usage.

Managing frontend with App's Digest and React

All right, let's use our store in a UI using React! (we'll support frameworks in the future).

Create a new React app

Let's use the create-react-app library to create a new React application. From the terminal, we will run:

npx create-react-app counter-app

The above command will bootstrap the application and install the dependencies.

Manage components

Let’s make a CounterView component to show the details of our counter store:

import { useStore, useValue } from 'apps-digest'; import CounterStore from './CounterStore'; const CounterView = () => { const counterStore = useStore(CounterStore); const count = useValue(counterStore.count); return <div>Current Count: {count}</div>; }; export { CounterView };

Inside of our App.jsx, we will import the CounterView component, like so:

import { CounterView } from "./CounterView"; export default function App() { return ( <div> <h1>My Counter App</h1> <CounterView /> </div> ); }

We'll se the following result:

Implement counter button

Next, let's modify our CounterView component to increment our counter value. For this, we will add a button and and assign it to the onClick event:

const CounterView = () => { const counterStore = useStore(CounterStore); const count = useValue(counterStore.count); return ( <div> Current Count: {count} <br /> <br /> <button onClick={() => counterStore.increment()}>Increment Count</button> </div> ); }; export { CounterView };

Now, our results will look something like this:

See this live

Please visit our App's Digest Codesandbox to see a live example of the React usage.

Conclusion

In this article, we have explored how to use App's Digest to manage the state of an application, and specifically how to use App's Digest to manage the state of a React application.

Please note that for our example, we decided to separate the logic of our store from the UI for instructional purposes.

Links