What is Data Sources?
Data sources act as facades for specific parts of data in external storages like local storage, session storage, cookies, and more. They implement a unified interface called DataSource, which simplifies integration with various storage mechanisms. This interface also enables states to seamlessly connect to external storages, ensuring that state remains synchronized with them.
Beyond providing access to a specific portion of the storage, data sources enable the ability to subscribe to data changes. This feature ensures reactive updates within your application, keeping your state aligned with external changes.
List of Data Sources
-
Local Storage Part
Provides interaction with a specific key-value pair stored in the browser’s local storage -
Session Storage Part
Provides interaction with a specific key-value pair stored in the browser’s session storage -
Memory Storage Part
Provides interaction with a specific key-value pair stored in the memory storage -
Cookie Part
Provides interaction with a specific key-value pair stored in the browser’s cookie
How to Use Data Sources
Create a data source
Let’s start by creating a data source that manages data in localStorage under the key theme
:
import { localStoragePart } from '@bitfiber/rx';
// Create a data source
const themeSource = localStoragePart('theme');
Modify data
Use the data source to set or update the value:
themeSource.set('dark');
To remove the value, simply call:
themeSource.remove();
Retrieve data
Retrieve the current value:
const value = themeSource.get();
Subscribe to data changes
Data sources are reactive, meaning you can subscribe to data changes and respond accordingly:
themeSource.$.subscribe((theme) => {
if (theme === 'dark') {
// Perform logic for the dark theme
console.log('Dark theme activated!');
}
});
Any Data Types for Storages
Data sources such as localStoragePart
, sessionStoragePart
, and cookiePart
simplify
the handling of data by allowing you to store and retrieve values of any type, including objects,
arrays, and primitives. These sources automatically convert data into JSON strings when storing it
and parse JSON strings back into their original types when retrieving.
import {localStoragePart} from '@bitfiber/rx';
type Preferences = {theme: 'dark' | 'light'; notifications: boolean};
// Create a data source
const preferencesSource = localStoragePart<Preferences>('preferences');
// Set a preferences object in local storage
preferencesSource.set({theme: 'dark', notifications: true});
// Retrieve the preferences object from local storage
const preferences = preferencesSource.get();
// Expected result: preferences is equal to {theme: 'dark', notifications: true}
console.log(preferences);
Using Data Sources with State
The DataSource interface facilitates seamless connection of state to specific parts of external storages, ensuring that state data remains synchronized and up to date. This approach streamlines the management of data consistency and alignment across your application.
Key Benefits
-
Seamless Synchronization:
Automatically sync state updates to external storage and vice versa, ensuring consistent data across your application. -
Reactive Updates:
Subscribe to changes in external storages and propagate those changes directly to your state, enabling real-time reactivity. -
Scoped Access:
Focus on specific parts of storage, allowing precise and efficient management of data segments.
State Connection Example
import {state, localStoragePart} from '@bitfiber/rx';
// Create a state
const userPreferences = state({theme: 'dark', notifications: true}, s => s
// Connect the state to the user preferences source
.connect(localStoragePart('userPreferences')));
// Now, any updates to the state are saved in localStorage, and changes in
// localStorage will automatically update the state
Creating a Custom Data Source
To create a custom data source, you need to implement the DataSource interface. This allows your custom data source to integrate seamlessly with states
Custom Data Source Example
import {Subject} from 'rxjs';
import {DataSource} from '@bitfiber/rx';
class CustomDataSource<T = any> implements DataSource<T> {
private value: T;
private readonly subject = new Subject<T>();
// Observable stream for external subscribers
readonly $ = this.subject.asObservable();
// Retrieve the current value
get(): T {
return this.value;
}
// Update the value and notify subscribers
set(value: T): void {
this.value = value;
this.subject.next(this.value);
}
// Remove the value and notify subscribers
remove(): void {
delete this.value;
this.subject.next(undefined);
}
}