Skip to main content
Version: 5.3.2

useValue

The useValue hook is the core of React UI Animate. It creates animated values that update smoothly without causing React re-renders, making your animations performant and your code simple.

Understanding useValue

Think of useValue as useState optimized for animations. It returns a tuple [value, setValue] that you can use just like useState, but with superpowers:

  • No re-renders - Updates happen outside React's render cycle
  • Smooth animations - Works seamlessly with animation modifiers
  • Flexible types - Supports numbers, strings, arrays, and objects
  • Direct style binding - Use values directly in JSX styles

Basic Usage

The simplest way to use useValue is with a number:

import { useValue, animate } from 'react-ui-animate';

function MyComponent() {
const [width, setWidth] = useValue(100);

return (
<animate.div style={{ width, height: 100, background: '#60a5fa' }} />
);
}

Immediate vs. Animated Updates

Understanding when values change instantly vs. smoothly is crucial:

Important
  • Raw values → Change immediately (no animation)
  • Modifier-wrapped values → Animate smoothly
const [width, setWidth] = useValue(100);

// ❌ Immediate change (no animation)
setWidth(200);

// ✅ Smooth animation
setWidth(withSpring(200));
setWidth(withTiming(200, { duration: 300 }));
Preview

Try it yourself: Click "Animate" to see a smooth spring animation, then "Reset" to see a timing-based transition back.

Supported Value Types

useValue works with multiple data types. Here's how to use each:

1. Primitive Values (Number & String)

Perfect for animating single properties like width, opacity, or color.

const [width, setWidth] = useValue(100);        // number
const [color, setColor] = useValue('teal'); // string

Real-world example: Animate a button's width on hover:

function ExpandableButton() {
const [width, setWidth] = useValue(100);

return (
<animate.button
onMouseEnter={() => setWidth(withSpring(200))}
onMouseLeave={() => setWidth(withSpring(100))}
style={{ width, padding: '10px 20px' }}
>
Hover me
</animate.button>
);
}
View full example
Preview

2. Arrays

Animate multiple values simultaneously. Perfect for lists, grids, or any collection of elements.

const [positions, setPositions] = useValue([0, 0, 0]);

Real-world example: Stagger animation for a list of items:

function AnimatedList() {
const [heights, setHeights] = useValue([0, 0, 0, 0]);

const expand = () => {
setHeights(withSpring([100, 100, 100, 100]));
};

return (
<>
<button onClick={expand}>Expand All</button>
{heights.map((height, i) => (
<animate.div
key={i}
style={{ height, background: '#60a5fa', margin: 5 }}
/>
))}
</>
);
}
View full example
Preview

3. Objects

Animate multiple properties together. Ideal for position, size, or any grouped properties.

const [position, setPosition] = useValue({ x: 0, y: 0 });
const [size, setSize] = useValue({ width: 100, height: 100 });

Real-world example: Animate a card's position and size together:

function AnimatedCard() {
const [style, setStyle] = useValue({
x: 0,
y: 0,
width: 200,
height: 200,
});

const moveAndResize = () => {
setStyle(
withSpring({
x: 100,
y: 100,
width: 300,
height: 300,
})
);
};

return (
<>
<button onClick={moveAndResize}>Move & Resize</button>
<animate.div
style={{
translateX: style.x,
translateY: style.y,
width: style.width,
height: style.height,
background: '#60a5fa',
}}
/>
</>
);
}
View full example
Preview

Common Patterns

Pattern 1: Toggle Animation

function ToggleButton() {
const [isOpen, setIsOpen] = useState(false);
const [width, setWidth] = useValue(100);

useEffect(() => {
setWidth(withSpring(isOpen ? 200 : 100));
}, [isOpen]);

return (
<animate.button
onClick={() => setIsOpen(!isOpen)}
style={{ width }}
>
{isOpen ? 'Close' : 'Open'}
</animate.button>
);
}

Pattern 2: Conditional Animation

function ConditionalAnimation() {
const [isActive, setIsActive] = useState(false);
const [scale, setScale] = useValue(1);

useEffect(() => {
setScale(withSpring(isActive ? 1.2 : 1));
}, [isActive]);

return (
<animate.div
onClick={() => setIsActive(!isActive)}
style={{
scale,
width: 100,
height: 100,
background: isActive ? 'red' : 'teal',
}}
/>
);
}

Best Practices

✅ Do

  • Use useValue for values that change frequently (animations, gestures)
  • Combine related properties in objects for coordinated animations
  • Use animation modifiers (withSpring, withTiming) for smooth transitions
  • Access values directly in JSX (no need to call .value)

❌ Don't

  • Don't use useValue for static values (use useState instead)
  • Don't update values in render (causes issues)
  • Don't forget to use modifiers for animations (raw values change instantly)
  • Don't use useValue for complex state management (use state management libraries)

Performance Tips

  1. Batch updates - Update multiple properties in a single object rather than separate values
  2. Use appropriate modifiers - withSpring for natural motion, withTiming for precise control
  3. Avoid unnecessary re-renders - useValue already prevents re-renders, but don't trigger React state updates during animations

Next Steps

Now that you understand useValue, explore: