TinyBase logoTinyBase


The addDidFinishTransactionListener method registers a listener function with the Store that will be called just after other non-mutating listeners are called at the end of the transaction.

addDidFinishTransactionListener(listener: TransactionListener<Store>): string

The function that will be called after the end of a transaction.


A unique Id for the listener that can later be used to remove it.

This is useful if you need to know that a set of listeners have just been called at the end of a transaction, perhaps to batch their consequences together.

The provided TransactionListener will receive a reference to the Store and two booleans to indicate whether Cell or Value data has been touched during the transaction. The two flags is intended as a hint about whether non-mutating listeners might have been called at the end of the transaction.

Here, 'touched' means that Cell or Value data has either been changed, or changed and then changed back to its original value during the transaction. The exception is a transaction that has been rolled back, for which the value of cellsTouched and valuesTouched in the listener will be false because all changes have been reverted.

Note that a TransactionListener added to the Store with this method cannot mutate the Store itself, and attempts to do so will fail silently.


This example registers a listener that is called at the end of the transaction, just after its listeners have been called. The transactions shown here variously change, touch, and rollback cells, demonstrating how the cellsTouched and valuesTouched parameters in the listener work.

import {createStore} from 'tinybase';

const store = createStore()
    pets: {fido: {species: 'dog', color: 'brown'}},
  .setValues({open: true, employees: 3});
const listenerId = store.addDidFinishTransactionListener((store) => {
  const [cellsTouched, valuesTouched] = store.getTransactionLog() ?? {};
  console.log(`Cells/Values touched: ${cellsTouched}/${valuesTouched}`);
const listenerId2 = store.addTablesListener(() =>
  console.log('Tables changed'),
const listenerId3 = store.addValuesListener(() =>
  console.log('Values changed'),

store.transaction(() =>
  store.setCell('pets', 'fido', 'color', 'brown').setValue('employees', 3),
// -> 'Cells/Values touched: false/false'

store.transaction(() => store.setCell('pets', 'fido', 'color', 'walnut'));
// -> 'Tables changed'
// -> 'Cells/Values touched: true/false'

store.transaction(() => store.setValue('employees', 4));
// -> 'Values changed'
// -> 'Cells/Values touched: false/true'

store.transaction(() => {
    .setRow('pets', 'felix', {species: 'cat'})
    .delRow('pets', 'felix')
    .setValue('city', 'London')
// -> 'Cells/Values touched: true/true'
// But no Tables or Values listeners fired since there are no net changes.

  () =>
      .setRow('pets', 'felix', {species: 'cat'})
      .setValue('city', 'London'),
  () => true,
// -> 'Cells/Values touched: false/false'
// Transaction was rolled back.

// -> 'Cells/Values touched: false/false'
// It is meaningless to call this listener directly.