function CanvasArea({ image, filters }) {
const canvasRef = useRef(null);
useEffect(() => {
if (!image || !canvasRef.current) return;
const ctx = canvasRef.current.getContext('2d');
// Redraw with filters applied
drawWithFilters(ctx, image, filters);
}, [image, filters]); // Rerun when image or filters change
return <canvas ref={canvasRef} />;
}
useEffect(() => {
const saved = localStorage.getItem('settings');
if (saved) setSettings(JSON.parse(saved));
}, []); // Empty array = run once on mount
useEffect(() => {
const handleKey = (e) => {
if (e.ctrlKey && e.key === 'z') undo();
};
window.addEventListener('keydown', handleKey);
return () => window.removeEventListener(
'keydown', handleKey
); // Cleanup!
}, []);
A wrong dependency triggers an infinite re-render: effect runs → updates state → triggers effect → updates state → crashes.
Identify and fix the incorrect dependency to break the loop.
git switch -c bugfix/PIXELCRAFT-031-canvas-sync
git add src/components/
git commit -m "Sync canvas with React state via useEffect + useRef (PIXELCRAFT-031)"
git push origin bugfix/PIXELCRAFT-031-canvas-sync
# PR → Review → Merge → Close ticket ✅
Side effects vs pure computation.
Pure functions produce the same output for the same input. Side effects (DOM updates, network calls, localStorage) are necessary but harder to manage. useEffect is React's designated boundary.