Lottie JSON file from Sanity not rendering in lottie-react component

3 replies
Last updated: Dec 1, 2025
I have a massive challenge! The client I am working with uses Lottie animations on their old site. This all gets added as part of the CMS (now Sanity). I have added a custom upload of Lottie JSON files in the blockContent and I know the file is there but when I call it into the lottie-react hook nothing happens. The serializer currently looks like this:

lottieFile: (_props_)  => {

const data = _props_.node.document.url

const styles = {

width: 500,

height: 500

}

return (

<Lottie _animationData_={data} _style_={styles} />

)
AI Update

The issue you're experiencing is that lottie-react's animationData prop expects the actual JSON object data, not a URL string. When you pass props.node.document.url, you're giving it the URL path to the file, but Lottie needs the parsed JSON content.

The Solution: Fetch and Parse the JSON

You need to fetch the JSON file from the URL first, then pass the parsed data to the animationData prop:

lottieFile: (props) => {
  const [animationData, setAnimationData] = React.useState(null);
  const url = props.node.document.url;
  
  React.useEffect(() => {
    fetch(url)
      .then(response => response.json())
      .then(data => setAnimationData(data))
      .catch(error => console.error('Error loading Lottie:', error));
  }, [url]);

  const styles = {
    width: 500,
    height: 500
  };

  if (!animationData) return <div>Loading animation...</div>;
  
  return <Lottie animationData={animationData} style={styles} />;
}

This approach:

  • Fetches the Lottie JSON file from the Sanity CDN URL
  • Parses it into a JavaScript object
  • Passes that object to the animationData prop (which is what lottie-react expects)
  • Handles loading states while the file is being fetched

Important: Verify Your URL Structure

Based on the Sanity file type documentation, when querying file assets, you need to dereference them properly to get the URL. Make sure your GROQ query includes:

// In your query
"lottieFile": {
  "url": asset->url
}

If you're accessing it through props.node.document.url in your serializer, verify that your schema and query are properly set up to include the dereferenced asset URL. The asset field in a file type is a reference that needs to be dereferenced with the -> operator.

Alternative: useLottie Hook

If you need more control over the animation (play/pause, speed, etc.), you can use the useLottie hook instead:

lottieFile: (props) => {
  const [animationData, setAnimationData] = React.useState(null);
  const url = props.node.document.url;
  
  React.useEffect(() => {
    fetch(url)
      .then(response => response.json())
      .then(data => setAnimationData(data))
      .catch(error => console.error('Error loading Lottie:', error));
  }, [url]);

  const options = {
    animationData: animationData,
    loop: true,
    autoplay: true,
  };

  const { View } = useLottie(options);

  if (!animationData) return <div>Loading animation...</div>;
  
  return <div style={{ width: 500, height: 500 }}>{View}</div>;
}

The key takeaway: animationData expects a JSON object, not a URL path, so you must fetch and parse the file first before passing it to the Lottie component.

Show original thread
3 replies

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?