Skip to main content

Reactive API

The Reactive API provides automatically synchronized state properties for Flicking, eliminating the need for manual event listeners and state management boilerplate.


Overview

When building carousel UIs, you often need to reflect Flicking's internal state in surrounding elements like pagination dots, progress bars, or navigation buttons. The traditional approach requires listening to multiple events and manually keeping your UI in sync.

The Reactive API solves this by exposing reactive state properties that update automatically whenever Flicking's state changes.

Traditional Approach vs Reactive API

Traditional (event-based):

const flicking = new Flicking("#el");

let progress = 0;
let isReachStart = true;
let isReachEnd = false;

flicking.on("move", () => {
const cam = flicking.camera;
progress = ((cam.position - cam.range.min) / (cam.range.max - cam.range.min)) * 100;
updateProgressBar(progress);
});

flicking.on("changed", () => {
isReachStart = flicking.index === 0;
isReachEnd = flicking.index === flicking.panelCount - 1;
updateButtons(isReachStart, isReachEnd);
});

Reactive API:

const flicking = new Flicking("#el");
const reactive = connectFlickingReactiveAPI(flicking);

reactive.subscribe("progress", (value) => updateProgressBar(value));
reactive.subscribe("isReachStart", (value) => updateButtons(value, reactive.isReachEnd));
reactive.subscribe("isReachEnd", (value) => updateButtons(reactive.isReachStart, value));

Key Benefits

  1. Less boilerplate: No manual event listeners, useState, or useEffect to keep UI in sync.
  2. Framework-native: Returns React state / Vue3 reactive refs that integrate naturally with your components and any UI libraries you use.
  3. Auto-sync: State updates are never missed. Drag, programmatic moves, and panel additions all trigger updates automatically.
  4. SSR-ready: Pre-set initial values to match server-rendered markup and avoid hydration flicker.

Getting Started

import Flicking, { connectFlickingReactiveAPI } from "@egjs/flicking";

const flicking = new Flicking("#el");
const reactive = connectFlickingReactiveAPI(flicking);

// Read current values
console.log(reactive.currentPanelIndex);
console.log(reactive.progress);

// Subscribe to changes
reactive.subscribe("currentPanelIndex", (value) => {
console.log("Panel changed to:", value);
});

// Use methods
reactive.moveTo(2);

connectFlickingReactiveAPI returns a reactive object. Use .subscribe() to listen for state changes.


Reactive State

PropertyTypeDescription
currentPanelIndexnumberIndex of the currently active panel
totalPanelCountnumberTotal number of panels
progressnumberOverall scroll progress as a percentage (0-100)
indexProgressnumberCamera position as a fractional panel index (e.g., 2.5 means halfway between panel 2 and 3)
isReachStartbooleanWhether the first panel is currently active
isReachEndbooleanWhether the last panel is currently active
progress vs indexProgress
  • progress is best for continuous indicators like progress bars. It ranges from 0 to 100 and works well with moveType: "freeScroll".
  • indexProgress is best for per-panel visual effects like parallax or coverflow. It provides fractional values between panel indices and updates in real-time during drag.

Reactive Methods

MethodTypeDescription
moveTo(index: number) => Promise<void>Move to a specific panel by index. Ignores calls while animating.

SSR Optimization

When using SSR (Server-Side Rendering), you can provide initial values to prevent layout shifts during hydration:

const reactive = connectFlickingReactiveAPI(flicking, {
defaultIndex: 2,
totalPanelCount: 10
});
OptionTypeDefaultDescription
defaultIndexnumber0Initial panel index. Also affects isReachStart, isReachEnd, and indexProgress initial values.
totalPanelCountnumber0Initial panel count. Prevents layout shifts when pagination UI depends on this value.

Next Steps

  • Demos: See Reactive API in action with interactive examples
  • API Reference: Full type definitions and property details