Skip to main content
Create a Readable store that allows reading by subscription. Unlike writable stores, readable stores cannot be updated from the outside - their value can only be set by the start function.

Usage

import { readable } from 'svelte/store';

const time = readable(new Date(), (set) => {
  const interval = setInterval(() => {
    set(new Date());
  }, 1000);

  return () => clearInterval(interval);
});

Signature

function readable<T>(
  value?: T,
  start?: StartStopNotifier<T>
): Readable<T>
value
T
Initial value of the store.
start
StartStopNotifier<T>
A function that is called when the first subscriber subscribes. It receives set and update functions and optionally returns a cleanup function that is called when the last subscriber unsubscribes.
type StartStopNotifier<T> = (
  set: (value: T) => void,
  update: (fn: Updater<T>) => void
) => void | (() => void)
Readable<T>
object
A readable store object with the following method:
subscribe
(run: Subscriber<T>, invalidate?: () => void) => Unsubscriber
Subscribe to value changes. The run callback is called immediately with the current value and then called again whenever the value changes.Returns an unsubscriber function.

Store Contract

A readable store implements the following contract:

subscribe

Subscribe to value changes:
const unsubscribe = store.subscribe((value) => {
  console.log('Value changed:', value);
});

// Later, cleanup
unsubscribe();
Unlike writable stores, readable stores do not have set or update methods accessible from the outside. The value can only be changed from within the start function.

Examples

Current time store

import { readable } from 'svelte/store';

export const time = readable(new Date(), (set) => {
  // Called when first subscriber subscribes
  const interval = setInterval(() => {
    set(new Date());
  }, 1000);

  // Cleanup function called when last subscriber unsubscribes
  return () => {
    clearInterval(interval);
  };
});
<script>
  import { time } from './stores.js';
</script>

<h1>The time is {$time}</h1>

Mouse position store

import { readable } from 'svelte/store';

export const mouse = readable(
  { x: 0, y: 0 },
  (set) => {
    function handleMouseMove(event) {
      set({
        x: event.clientX,
        y: event.clientY
      });
    }

    window.addEventListener('mousemove', handleMouseMove);

    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
    };
  }
);
<script>
  import { mouse } from './stores.js';
</script>

<p>Mouse position: {$mouse.x}, {$mouse.y}</p>

Geolocation store

import { readable } from 'svelte/store';

export const geolocation = readable(
  null,
  (set) => {
    if (!navigator.geolocation) {
      return;
    }

    const watchId = navigator.geolocation.watchPosition(
      (position) => {
        set({
          latitude: position.coords.latitude,
          longitude: position.coords.longitude
        });
      },
      (error) => {
        console.error('Geolocation error:', error);
      }
    );

    return () => {
      navigator.geolocation.clearWatch(watchId);
    };
  }
);

Auto-subscription with $

In Svelte components, you can use the $ prefix to automatically subscribe and unsubscribe:
<script>
  import { time } from './stores.js';
</script>

<!-- Automatically subscribes and cleans up -->
<h1>{$time}</h1>

TypeScript

import { readable, type Readable } from 'svelte/store';

interface MousePosition {
  x: number;
  y: number;
}

const mouse: Readable<MousePosition> = readable(
  { x: 0, y: 0 },
  (set) => {
    function handleMouseMove(event: MouseEvent) {
      set({
        x: event.clientX,
        y: event.clientY
      });
    }

    window.addEventListener('mousemove', handleMouseMove);
    return () => window.removeEventListener('mousemove', handleMouseMove);
  }
);