How to Trigger a dotLottie Animation from a Button in React

How to Trigger a dotLottie Animation from a Button in React

How to Trigger a dotLottie Animation from a Button in React

Three ways to play a .lottie animation when someone clicks a button in React: play(), named markers, and state machine events.

Three ways to play a .lottie animation when someone clicks a button in React: play(), named markers, and state machine events.

Iridescent glass slabs in sequence on a black background

Your designer sent a .lottie file. Now you need it to play on click.

Dropped into the page, it autoplays and loops. What you actually want is for it to play once when someone clicks Submit.

There are three ways to do that, from simplest to most robust.

Setup

npm
npm
npm

DotLottieReact renders a canvas. To control it, you need the player instance, which the component hands you through dotLottieRefCallback.

Storing it in state rather than a ref means your effects re-run once the player exists.

import { useState } from 'react';
import { DotLottieReact } from '@lottiefiles/dotlottie-react';

export function SubmitButton() {
  const [player, setPlayer] = useState(null);

  return (
    <button onClick={() => { player?.stop(); player?.play(); }}>
      <DotLottieReact
        src="/animations/submit.lottie"
        style={{ width: 32, height: 32 }}
        dotLottieRefCallback={setPlayer}
      />
      Submit
    </button>
  );
}
import { useState } from 'react';
import { DotLottieReact } from '@lottiefiles/dotlottie-react';

export function SubmitButton() {
  const [player, setPlayer] = useState(null);

  return (
    <button onClick={() => { player?.stop(); player?.play(); }}>
      <DotLottieReact
        src="/animations/submit.lottie"
        style={{ width: 32, height: 32 }}
        dotLottieRefCallback={setPlayer}
      />
      Submit
    </button>
  );
}
import { useState } from 'react';
import { DotLottieReact } from '@lottiefiles/dotlottie-react';

export function SubmitButton() {
  const [player, setPlayer] = useState(null);

  return (
    <button onClick={() => { player?.stop(); player?.play(); }}>
      <DotLottieReact
        src="/animations/submit.lottie"
        style={{ width: 32, height: 32 }}
        dotLottieRefCallback={setPlayer}
      />
      Submit
    </button>
  );
}

1) play() on click

Leave out autoplay and loop, then call stop() and play() in the click handler.

The stop() matters. It resets to frame 0, so a second click replays the animation instead of doing nothing because it already finished.

Use this when the file holds one animation that always plays start to finish.

2) Named markers

Most button animations have more than one moment: a press, a success, an error. Ask your designer to add a named marker for each one. Then you play a marker by name:

function playMarker(name) {
  player?.setMarker(name);
  player?.play();
}

// after your request resolves
ok ? playMarker('success') : playMarker('error');
function playMarker(name) {
  player?.setMarker(name);
  player?.play();
}

// after your request resolves
ok ? playMarker('success') : playMarker('error');
function playMarker(name) {
  player?.setMarker(name);
  player?.play();
}

// after your request resolves
ok ? playMarker('success') : playMarker('error');

Why markers instead of frame numbers? If the designer retimes the animation, frame 45 might become frame 60 and your code silently plays the wrong part. A marker name survives retiming.

You can list what’s in the file with player.markers().

3) A state machine event

If the animation has real states, like idle, loading and success, that need to blend cleanly, the logic belongs in the file, not in your component.

dotLottie files can carry a state machine. Your code loads it once, then fires events:

import { useEffect } from 'react';

useEffect(() => {
  if (!player) return;
  const start = () => {
    if (player.stateMachineLoad('submitButton')) {
      player.stateMachineStart();
    }
  };
  if (player.isLoaded) start();
  player.addEventListener('load', start);
  return () => player.removeEventListener('load', start);
}, [player]);

// in your click handler
player?.stateMachineFireEvent('submit');
import { useEffect } from 'react';

useEffect(() => {
  if (!player) return;
  const start = () => {
    if (player.stateMachineLoad('submitButton')) {
      player.stateMachineStart();
    }
  };
  if (player.isLoaded) start();
  player.addEventListener('load', start);
  return () => player.removeEventListener('load', start);
}, [player]);

// in your click handler
player?.stateMachineFireEvent('submit');
import { useEffect } from 'react';

useEffect(() => {
  if (!player) return;
  const start = () => {
    if (player.stateMachineLoad('submitButton')) {
      player.stateMachineStart();
    }
  };
  if (player.isLoaded) start();
  player.addEventListener('load', start);
  return () => player.removeEventListener('load', start);
}, [player]);

// in your click handler
player?.stateMachineFireEvent('submit');

Two things trip people up here.

  • stateMachineLoad only works after the animation has loaded, which is why it runs inside the load listener.

  • The ID must match the state machine ID in the file exactly. Ask the designer for it rather than guessing.

Gotchas

  • Size the wrapper. The component fills its container, so a container with no height gives you an invisible animation.

  • Next.js App Router. The component uses hooks and a canvas, so put it in a file marked 'use client'.

  • Clean up listeners. Attaching listeners inline in the ref callback adds a new one every time it fires. The effect above removes its listener on cleanup.

What to ask your motion designer for

For option 2, a list of marker names. For option 3, the state machine ID and the names of every event and input.

If those come documented with the file, wiring it up takes minutes, not days.

That handoff note ships with every interactive Lottie project we deliver. If you want animations that arrive ready to wire up, get in touch.

Reach out anytime

Ready to bring your ideas to life?

Reach out for a quote.

Contact Us

Reach out anytime

Ready to bring your ideas to life?

Reach out for a quote.

Contact Us

Reach out anytime

Ready to bring your ideas to life?

Reach out for a quote.

Contact Us
Featured on Creators Toolbox