I have a React component that implements a dark mode toggle using the following Lottie animation:
https://lottiefiles.com/free-animation/button-switch-ui-AX5XJZQdq8
The animation has different frames for the light-to-dark and dark-to-light transitions which I am able to set manually with an on click, however I also need to set initial frame of the Lottie animation based on the user’s theme preference stored in localStorage.
The issue I’m having is that the Lottie always defaults to frame 0 which means that if the user’s theme is dark mode, the Lottie animation will be incorrectly displayed.
import React, { useEffect, useState, useRef } from "react";
import Lottie from "lottie-react";
import darkModeToggle from "./assets/dark-mode-lottie.json";
const DarkModeToggle = () => {
const initialTheme = localStorage.getItem("theme");
const [isDarkMode, setIsDarkMode] = useState(initialTheme === "dark");
const lottieRef = useRef(null);
useEffect(() => {
const root = document.documentElement;
const metaThemeColor = document.querySelector('meta[name="theme-color"]');
const themeColor = isDarkMode ? "#000000" : "#f1f5f9";
if (isDarkMode) {
root.setAttribute("data-theme", "dark");
localStorage.setItem("theme", "dark");
metaThemeColor.content = themeColor;
} else {
root.removeAttribute("data-theme");
localStorage.setItem("theme", "light");
metaThemeColor.content = themeColor;
}
}, [isDarkMode]);
const handleClick = () => {
if (lottieRef.current) {
if (isDarkMode) {
setIsDarkMode((prev) => !prev);
lottieRef.current?.playSegments([120, 150], true);
} else {
setIsDarkMode((prev) => !prev);
lottieRef.current?.playSegments([30, 50], true);
}
}
};
useEffect(() => {
if (lottieRef.current) {
const initialFrame = initialTheme === "dark" ? 30 : 0;
lottieRef.current?.goToAndStop(initialFrame, true);
}
}, []);
return (
<button
onClick={handleClick}
className="w-24 h-24 p-1 rounded focus:outline-none"
aria-label="Toggle dark mode"
>
<Lottie
lottieRef={lottieRef}
loop={false}
autoplay={false}
animationData={darkModeToggle}
/>
</button>
);
};
export default DarkModeToggle;
I have tried a few things including a useEffect to set the initial frame on render based on the theme as per above code, but this still ends up with the Lottie animation defaulting to frame 0 every time.
I have also tried to implement initialSegment on the Lottie element but again this ended with the same result.
I am currently using lottie-react because I use the playSegments method for playing the animating the lottie animation on click, but I have also tried using react-lottie too but to no avail.