DEV Community

Cover image for Wrapping React Spring's useSpring Hook (A Use Case for Wrapping External Libraries)
Michael Mangialardi
Michael Mangialardi

Posted on

10 4

Wrapping React Spring's useSpring Hook (A Use Case for Wrapping External Libraries)

In my previous post, I discussed some potential improvements by wrapping React Query's useQuery hook.

In this post, I'd like to aim for similar improvements with React Spring's useSpring hook.

The useSpring hook you to animate an element's style by controlling its style from when first appears to when the animation completes:

// some-component.js

import { animated, useSpring } from 'react-spring';

const spring = useSpring({
  from: { opacity: 0 },
  to: { opacity: 1 },
});

// ...

<animated.div style={spring}>Hello World</animated.div>
Enter fullscreen mode Exit fullscreen mode

Without an abstraction, there is no way to make the animations reusable.

One way to make the animation reusable is to create a file that exports an object associating a { from, to, ...etc } config (the argument that useSpring takes) with an animation name:

// animations.js
export default {
  fadeIn: {
    from: { opacity: 0 },
    to: { opacity: 1 },
  },
};

// some-component.js

import { animated, useSpring } from 'react-spring';
import animations from './animations';

const spring = useSpring(animations.fadeIn);

// ...

<animated.div style={spring}>Hello World</animated.div>
Enter fullscreen mode Exit fullscreen mode

This is the easiest solution, but we have to inconveniently import from two places.

We can improve upon this by export react-spring modules plus our animations object from a single file:

// animations.js
export const animations = {
  fadeIn: {
    from: { opacity: 0 },
    to: { opacity: 1 },
  },
};

export * from 'react-spring';

// some-component.js

import { animated, animations, useSpring } from './animations';

const spring = useSpring(animations.fadeIn);

// ...

<animated.div style={spring}>Hello World</animated.div>
Enter fullscreen mode Exit fullscreen mode

We can improve upon this even more by not having to import animated, animations, and useSpring, and then scope animations.fadeIn to useSpring.

Instead, we can expose use[AnimationName] hooks that return all that we need:

// animations.js
import { animated, useSpring } from 'react-spring';

const animations = {
  fadeIn: {
    from: { opacity: 0 },
    to: { opacity: 1 },
  },
};

export function useFadeIn() {
  const spring = useSpring(animations.fadeIn);
  return {
    animated,
    spring,
  };
}

// some-component.js

import { useFadeIn } from './animations';

const { animated, spring } = useFadeIn();

// ...

<animated.div style={spring}>Hello World</animated.div>
Enter fullscreen mode Exit fullscreen mode

Alternatively to creating a hook for every animation, you could expose a more generic but similar useSpring wrapper:

// animations.js
import { animated, useSpring as useBaseSpring } from 'react-spring';

const animations = {
  fadeIn: {
    from: { opacity: 0 },
    to: { opacity: 1 },
  },
};

export const PRESETS = Object.freeze(Object.keys(animations));
export function useSpring({ preset } = {}) {
  const spring = useBaseSpring(animations[preset]);
  return {
    animated,
    spring,
  };
}

// some-component.js

import { PRESETS, useSpring } from './animations';

const { animated, spring } = useSpring({ preset: PRESETS.fadeIn });

// ...

<animated.div style={spring}>Hello World</animated.div>
Enter fullscreen mode Exit fullscreen mode

Personally, I like creating a hook for every animation, just as you would create a CSS class to encapsulate a certain set of styles.

🎉 We've brainstormed ways to improve upon React Spring's useSpring hook.

How would you wrap this hook?

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay