Reactivity
ElectricSQL is a reactive database system. It allows you to subscribe and bind queries to data changes. This applies to both local changes (when, as the user, you change the data) and replicated changes (when someone else changes the data).
Data flow
ElectricSQL integrates with both SQLite and Postgres. For Postgres, integration is via logical replication. For SQLite, writes are made to the local SQLite database. Replication is implemented using triggers. These triggers record all insert, update and delete operations in an oplog table.
After each transaction that may have changed the data in the local database, the electrified database driver emits a “potential data change” event. This triggers the background replication process to check the oplog. If new entries are found, these are replicated and an “actual data changed” notification is emitted, with the tablename and primary key identifiers of the changes data. Components and dynamic queries can subscribe to these events to re-query / re-render.
The same applies to updates that are applied from the replication stream. Except in this case the background replication process simply emits the change events directly.
Note that the background replication process also polls the oplog, so if for some reason data is changed without triggering a “potential data change” event, then the changes will eventually get picked up.
Notifier API
The electrified database client has an electric
namespace added to it as a public property, e.g.:
const db = electrify(original, config)
// has `db.electric` property
This electric
property provides the ElectricNamespace
interface:
adapter
: a normalised database client adapter that provides theDatabaseAdapter
interfacenotifier
: a notifier instance that provides theNotifier
interfacepotentiallyChanged()
: a method that callsnotifier.potentiallyChanged()
The Notifier
interface provides methods to emit and subscribe to the events used in the reactive dataflow. You can use this to develop custom integrations and hooks and to manually trigger replication by calling electric.potentiallyChanged()
.
Framework Hooks
ElectricSQL implements reactive framework hooks for popular frameworks. These include useElectric
and useElectricQuery
React hooks. See the frameworks guide for more information. You can also use the source code as a reference if implementing your own framework integrations.
For example, the following is a snippet from within the useElectricQuery
hook:
// Once we have the tablenames, we then establish the data change
// notification subscription, comparing the tablenames used by the
// query with the changed tablenames in the data change notification
// to determine whether to re-query or not.
//
// If we do need to re-query, then we call `bustCache` to set a new
// `cacheKey`, which is a dependency of the next useEffect below
useEffect(() => {
if (electric === undefined || tablenames === undefined) {
return
}
const notifier = electric.notifier
const handleChange = (notification: ChangeNotification): void => {
// Reduces the `ChangeNotification` to an array of namespaced tablenames,
// in a way that supports both the main namespace for the primary database
// and aliases for any attached databases.
const changedTablenames = notifier.alias(notification)
if (hasIntersection(tablenames, changedTablenames)) {
bustCache()
}
}
const key = notifier.subscribeToDataChanges(handleChange)
if (changeSubscriptionKey !== undefined) {
notifier.unsubscribeFromDataChanges(changeSubscriptionKey)
}
setChangeSubscriptionKey(key)
return () => notifier.unsubscribeFromDataChanges(key)
}, [electric, tablenamesKey])
Connectivity Hook
ElectricSQL provides a connectivity hook that can be used to trigger events in the application when the connectivity with the replication service changes.
// connectivityState is one of "available" | "connected" | "disconnected" | "error".
// ElectricSQL will change the value of connectivityState, when ElectricSQL establishes
// connection with the service or disconnects because of an error or network issues.
// toggleConnectivityState toggles between "available" and "disconnected".
// When connectivityState is "available", ElectricSQL tries to initiate replication.
// When set to "disconnected", ElectricSQL closes the replication connection.
const {connectivityState, toggleConnectivityState} = useConnectivityState()