Usage
import { usePrevious } from '@kivora/react';
function Counter() {
const [count, setCount] = useState(0);
const prevCount = usePrevious(count);
return (
<div>
<p>Current: {count}</p>
<p>Previous: {prevCount ?? 'none'}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
Parameters
The value to track. Can be any type (state, prop, derived value, etc.)
Return Value
The value from the previous render. Returns
undefined on the first render.Examples
Detect Value Changes
const [searchTerm, setSearchTerm] = useState('');
const prevSearchTerm = usePrevious(searchTerm);
useEffect(() => {
if (prevSearchTerm !== searchTerm && searchTerm) {
console.log(`Search changed from "${prevSearchTerm}" to "${searchTerm}"`);
performSearch(searchTerm);
}
}, [searchTerm, prevSearchTerm]);
Animation Direction
const [currentSlide, setCurrentSlide] = useState(0);
const prevSlide = usePrevious(currentSlide);
const direction = prevSlide !== undefined
? currentSlide > prevSlide ? 'forward' : 'backward'
: 'none';
return (
<Slider
currentSlide={currentSlide}
direction={direction}
/>
);
Form Field Comparison
const [formData, setFormData] = useState({ name: '', email: '' });
const prevFormData = usePrevious(formData);
const hasChanges = prevFormData && (
prevFormData.name !== formData.name ||
prevFormData.email !== formData.email
);
return (
<form>
<input
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
/>
<input
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
/>
<button disabled={!hasChanges}>Save Changes</button>
</form>
);
Track Prop Changes
function UserProfile({ userId }: { userId: string }) {
const prevUserId = usePrevious(userId);
const [userData, setUserData] = useState(null);
useEffect(() => {
if (prevUserId !== userId) {
console.log(`User changed from ${prevUserId} to ${userId}`);
fetchUserData(userId).then(setUserData);
}
}, [userId, prevUserId]);
return <div>{userData?.name}</div>;
}
Counter Increment Detection
const [count, setCount] = useState(0);
const prevCount = usePrevious(count);
const increment = prevCount !== undefined ? count - prevCount : 0;
return (
<div>
<p>Count: {count}</p>
<p>Last change: {increment > 0 ? `+${increment}` : increment}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
<button onClick={() => setCount(count + 5)}>+5</button>
<button onClick={() => setCount(count - 1)}>-1</button>
</div>
);
Optimistic Updates Rollback
const [data, setData] = useState(initialData);
const prevData = usePrevious(data);
const updateData = async (newData: Data) => {
setData(newData); // Optimistic update
try {
await api.update(newData);
} catch (error) {
// Rollback on error
if (prevData) {
setData(prevData);
}
}
};