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
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.