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:
- 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 }));
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
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
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
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
useValuefor 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
useValuefor static values (useuseStateinstead) - Don't update values in render (causes issues)
- Don't forget to use modifiers for animations (raw values change instantly)
- Don't use
useValuefor complex state management (use state management libraries)
Performance Tips
- Batch updates - Update multiple properties in a single object rather than separate values
- Use appropriate modifiers -
withSpringfor natural motion,withTimingfor precise control - Avoid unnecessary re-renders -
useValuealready prevents re-renders, but don't trigger React state updates during animations
Next Steps
Now that you understand useValue, explore:
- Animation Modifiers - Learn how to control animations
- Presence & Exit - Animate components entering/leaving the DOM
- Interpolation - Map values to colors, ranges, and more
- Gestures - Combine
useValuewith gesture hooks