Skip to content

Commit

Permalink
refactor: React work on dependencies (#11)
Browse files Browse the repository at this point in the history
* work on deps

* split the useSmoothAnimation hook
  • Loading branch information
yhattav authored Dec 2, 2024
1 parent e48b414 commit cf8c9cf
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 30 deletions.
4 changes: 2 additions & 2 deletions src/CustomCursor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ export const CustomCursor: React.FC<CustomCursorProps> = React.memo(
}, [id]);

React.useEffect(() => {
if (onMove && position.x !== null && position.y !== null) {
onMove(position.x, position.y);
if (position.x !== null && position.y !== null) {
onMove?.(position.x, position.y);
}
}, [position, onMove]);

Expand Down
45 changes: 38 additions & 7 deletions src/hooks/useMousePosition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,51 @@ export function useMousePosition(
x: e.clientX + offsetX,
y: e.clientY + offsetY,
};
setTargetPosition(newPosition);
if (
positionRef.current.x === null ||
positionRef.current.y === null
newPosition.x !== targetPosition.x ||
newPosition.y !== targetPosition.y
) {
setPosition(newPosition);
setTargetPosition(newPosition);
}
}
} else {
const newPosition = {
x: e.clientX + offsetX,
y: e.clientY + offsetY,
};
setTargetPosition(newPosition);
if (positionRef.current.x === null || positionRef.current.y === null) {
setPosition(newPosition);
if (
newPosition.x !== targetPosition.x ||
newPosition.y !== targetPosition.y
) {
setTargetPosition(newPosition);
}
}
},
[containerRef, offsetX, offsetY]
);
// useEffect(() => {
// console.log('targetPosition', targetPosition);
// }, [targetPosition]);

// useEffect(() => {
// console.log('position', position);
// }, [position]);

// useEffect(() => {
// console.log('isVisible', isVisible);
// }, [isVisible]);

// useEffect(() => {
// console.log('offsetX', offsetX);
// }, [offsetX]);

// useEffect(() => {
// console.log('offsetY', offsetY);
// }, [offsetY]);

// useEffect(() => {
// console.log('containerRef', containerRef);
// }, [containerRef]);

useEffect(() => {
const handleMouseLeave = () => {
Expand Down Expand Up @@ -95,5 +119,12 @@ export function useMousePosition(
};
}, [containerRef, updateTargetPosition]);

// Initialize position when we get the first valid targetPosition
useEffect(() => {
if (position.x === null && position.y === null) {
setPosition(targetPosition);
}
}, [targetPosition]);

return { position, setPosition, targetPosition, isVisible };
}
75 changes: 54 additions & 21 deletions src/hooks/useSmoothAnimation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { useEffect, useCallback } from 'react';
import { Position, TargetPosition } from '../types';

const SMOOTHING_THRESHOLD = 0.1;
Expand All @@ -9,34 +9,45 @@ export function useSmoothAnimation(
smoothFactor: number,
setPosition: React.Dispatch<React.SetStateAction<Position>>
) {
useEffect(() => {
if (position.x === null || position.y === null) return;
// Memoize the smoothing calculation
const calculateNewPosition = useCallback(
(currentPosition: Position) => {
if (currentPosition.x === null || currentPosition.y === null) {
return currentPosition;
}

let animationFrameId: number;
const dx = targetPosition.x - currentPosition.x;
const dy = targetPosition.y - currentPosition.y;

if (smoothFactor === 1) {
setPosition(targetPosition);
return;
}
if (
Math.abs(dx) < SMOOTHING_THRESHOLD &&
Math.abs(dy) < SMOOTHING_THRESHOLD
) {
return currentPosition;
}

return {
x: currentPosition.x + dx / smoothFactor,
y: currentPosition.y + dy / smoothFactor,
};
},
[targetPosition.x, targetPosition.y, smoothFactor]
);

// Memoize the animation frame callback
const animate = useCallback(() => {
let animationFrameId: number;

const smoothing = () => {
setPosition((prev) => {
if (prev.x === null || prev.y === null) return prev;
const newPosition = calculateNewPosition(prev);

const dx = targetPosition.x - prev.x;
const dy = targetPosition.y - prev.y;

if (
Math.abs(dx) < SMOOTHING_THRESHOLD &&
Math.abs(dy) < SMOOTHING_THRESHOLD
) {
// Only trigger update if position actually changed
if (newPosition.x === prev.x && newPosition.y === prev.y) {
return prev;
}

return {
x: prev.x + dx / smoothFactor,
y: prev.y + dy / smoothFactor,
};
return newPosition;
});

animationFrameId = requestAnimationFrame(smoothing);
Expand All @@ -49,7 +60,29 @@ export function useSmoothAnimation(
cancelAnimationFrame(animationFrameId);
}
};
}, [position.x, position.y, targetPosition, smoothFactor, setPosition]);
}, [calculateNewPosition, setPosition]);

useEffect(() => {
// If smoothFactor is 1, just set position directly
if (smoothFactor === 1) {
setPosition(targetPosition);
return;
}

// Skip animation if position is null
if (position.x === null || position.y === null) {
return;
}

return animate();
}, [
smoothFactor,
position.x,
position.y,
targetPosition,
animate,
setPosition,
]);

return null;
}

0 comments on commit cf8c9cf

Please sign in to comment.