Troubleshooting Guide
Common issues and solutions for use-typewriter-animation
. This guide helps you quickly resolve problems and optimize your typewriter animations.
๐จ Common Issuesโ
Animation Not Workingโ
Problem: Text appears instantly without animationโ
Symptoms:
- Text shows up immediately
- No typing animation
- Cursor may or may not appear
Solutions:
- Missing Keyframes (Most Common)
// โ Wrong - Missing keyframes
return (
<div>
{elements}
{cursor}
</div>
);
// โ
Correct - Include keyframes
return (
<>
<style>{keyframes}</style>
<div>
{elements}
{cursor}
</div>
</>
);
- Forgot to Call
.start()
// โ Wrong - Animation never starts
useEffect(() => {
typewriter.type('Hello, World!');
}, []);
// โ
Correct - Call start()
useEffect(() => {
typewriter.type('Hello, World!').start();
}, []);
- Reduced Motion Enabled
// Check if user has reduced motion preference
const { typewriter } = useTypewriter({
respectReducedMotion: true,
reducedMotionFallback: 'slow', // Try 'slow' instead of 'instant'
});
Performance Issuesโ
Problem: Animation is laggy or stutteringโ
Symptoms:
- Choppy animation
- Low frame rate
- Browser becomes unresponsive
Solutions:
- Enable Virtualization for Large Text
const { typewriter } = useTypewriter({
enableVirtualization: true,
maxVisibleSegments: 100,
});
- Optimize Re-renders
// โ Wrong - Creates new object every render
const { typewriter } = useTypewriter({
typeSpeed: 50, // New object each time
});
// โ
Correct - Stable configuration
const config = useMemo(
() => ({
typeSpeed: 50,
cursorStyle: 'bar',
}),
[]
);
const { typewriter } = useTypewriter(config);
- Use GPU Acceleration
const optimizedStyles = {
transform: 'translateZ(0)', // Force GPU layer
willChange: 'transform, opacity',
};
return (
<div style={optimizedStyles}>
{elements}
{cursor}
</div>
);
Memory Leaksโ
Problem: Memory usage keeps increasingโ
Symptoms:
- Browser becomes slow over time
- Memory usage grows continuously
- Page crashes after extended use
Solutions:
- Proper Cleanup
useEffect(() => {
typewriter.type('Hello').start();
// โ
Always cleanup
return () => {
typewriter.stop();
};
}, []);
- Remove Event Listeners
useEffect(() => {
const handleEnd = () => console.log('Done');
typewriter.on('end', handleEnd).type('Hello').start();
return () => {
typewriter.off('end', handleEnd); // Remove listener
typewriter.stop();
};
}, []);
TypeScript Errorsโ
Problem: Type errors in TypeScript projectsโ
Common Errors:
- Missing Type Imports
// โ Wrong - Missing types
import { useTypewriter } from 'use-typewriter-animation';
// โ
Correct - Import types
import { useTypewriter, UseTypewriterOptions, TypewriterState } from 'use-typewriter-animation';
- Incorrect Option Types
// โ Wrong - Invalid cursor style
const options = {
cursorStyle: 'invalid', // Type error
};
// โ
Correct - Valid cursor style
const options: UseTypewriterOptions = {
cursorStyle: 'bar', // 'bar' | 'block' | 'underline'
};
React Strict Mode Issuesโ
Problem: Animation runs twice in developmentโ
Symptoms:
- Animation plays twice
- Only happens in development
- Works fine in production
Solution:
// โ
Handle Strict Mode properly
useEffect(() => {
let cancelled = false;
const runAnimation = async () => {
if (cancelled) return;
typewriter.type('Hello, World!').start();
};
runAnimation();
return () => {
cancelled = true;
typewriter.stop();
};
}, []);
๐ง Debugging Toolsโ
Debug Modeโ
Enable debug logging:
const { typewriter, state, metrics } = useTypewriter({
// Enable debug mode (if available)
debug: process.env.NODE_ENV === 'development',
});
// Log state changes
useEffect(() => {
console.log('Typewriter state:', state);
}, [state]);
// Log performance metrics
useEffect(() => {
console.log('Performance metrics:', metrics);
}, [metrics]);
Performance Monitoringโ
Monitor performance in real-time:
function DebugTypewriter() {
const { typewriter, elements, cursor, metrics } = useTypewriter();
const [debugInfo, setDebugInfo] = useState({});
useEffect(() => {
const interval = setInterval(() => {
setDebugInfo({
memory: performance.memory?.usedJSHeapSize || 0,
timing: performance.now(),
segments: metrics.totalSegments,
fps: metrics.animationFrameRate,
});
}, 1000);
return () => clearInterval(interval);
}, [metrics]);
return (
<div>
<div>
{elements}
{cursor}
</div>
{/* Debug Panel */}
<div
style={{
position: 'fixed',
top: 0,
right: 0,
background: 'rgba(0,0,0,0.8)',
color: 'white',
padding: '1rem',
fontSize: '0.8rem',
fontFamily: 'monospace',
}}
>
<h4>Debug Info</h4>
<div>Memory: {(debugInfo.memory / 1024 / 1024).toFixed(2)}MB</div>
<div>Segments: {debugInfo.segments}</div>
<div>FPS: {debugInfo.fps}</div>
<div>Virtualized: {metrics.isVirtualized ? 'Yes' : 'No'}</div>
</div>
</div>
);
}
React DevToolsโ
Use React DevTools Profiler:
import { Profiler } from 'react';
function ProfiledTypewriter() {
const onRender = (id, phase, actualDuration, baseDuration, startTime, commitTime) => {
console.log('Render performance:', {
id,
phase,
actualDuration,
baseDuration,
startTime,
commitTime,
});
};
return (
<Profiler id='typewriter' onRender={onRender}>
<YourTypewriterComponent />
</Profiler>
);
}
๐ Browser Compatibilityโ
Supported Browsersโ
Browser | Version | Notes |
---|---|---|
Chrome | 88+ | Full support |
Firefox | 85+ | Full support |
Safari | 14+ | Full support |
Edge | 88+ | Full support |
iOS Safari | 14+ | Full support |
Android Chrome | 88+ | Full support |
Polyfillsโ
For older browsers, you may need polyfills:
// Install polyfills
npm install core-js
// In your app entry point
import 'core-js/stable';
import 'regenerator-runtime/runtime';
Feature Detectionโ
Check for required features:
function FeatureCheck() {
const [supported, setSupported] = useState(true);
useEffect(() => {
const checks = [
'IntersectionObserver' in window,
'requestAnimationFrame' in window,
'matchMedia' in window,
];
setSupported(checks.every(Boolean));
}, []);
if (!supported) {
return <div>Your browser doesn't support all required features.</div>;
}
return <YourTypewriterComponent />;
}
๐ฑ Mobile Issuesโ
Touch Eventsโ
Handle touch interactions:
function MobileTypewriter() {
const { typewriter, elements, cursor } = useTypewriter({
enableKeyboardControls: false, // Disable on mobile
});
const handleTouch = () => {
if (typewriter.isPaused()) {
typewriter.resume();
} else {
typewriter.pause();
}
};
return (
<div onTouchStart={handleTouch} style={{ touchAction: 'manipulation' }}>
{elements}
{cursor}
</div>
);
}
Viewport Issuesโ
Handle viewport changes:
function ResponsiveTypewriter() {
const [viewport, setViewport] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
const handleResize = () => {
setViewport({
width: window.innerWidth,
height: window.innerHeight,
});
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const { typewriter, elements, cursor } = useTypewriter({
typeSpeed: viewport.width < 768 ? 60 : 40, // Slower on mobile
});
return (
<div>
{elements}
{cursor}
</div>
);
}
๐ Common Error Messagesโ
"Cannot read property 'type' of undefined"โ
Cause: Trying to use typewriter before it's initialized
Solution:
// โ Wrong - Using typewriter immediately
const { typewriter } = useTypewriter();
typewriter.type('Hello'); // Error!
// โ
Correct - Use in useEffect
const { typewriter } = useTypewriter();
useEffect(() => {
typewriter.type('Hello').start();
}, []);
"Maximum update depth exceeded"โ
Cause: Infinite re-render loop
Solution:
// โ Wrong - Missing dependency array
useEffect(() => {
typewriter.type('Hello').start();
}); // No dependency array causes infinite loop
// โ
Correct - Empty dependency array
useEffect(() => {
typewriter.type('Hello').start();
}, []); // Runs once
"Cannot read property 'matches' of null"โ
Cause: matchMedia
not available (older browsers)
Solution:
// Add polyfill or feature detection
const supportsMatchMedia = typeof window !== 'undefined' && 'matchMedia' in window;
const { typewriter } = useTypewriter({
respectReducedMotion: supportsMatchMedia,
});
๐งช Testing Issuesโ
Jest/Testing Libraryโ
Common testing problems:
// Mock matchMedia for tests
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
// Mock performance API
Object.defineProperty(window, 'performance', {
writable: true,
value: {
now: jest.fn(() => Date.now()),
mark: jest.fn(),
measure: jest.fn(),
getEntriesByName: jest.fn(() => []),
},
});
Async Testingโ
Test async animations:
import { waitFor } from '@testing-library/react';
test('typewriter animation completes', async () => {
render(<TypewriterComponent />);
await waitFor(
() => {
expect(screen.getByText('Hello, World!')).toBeInTheDocument();
},
{ timeout: 5000 }
);
});
๐ Diagnostic Checklistโ
When troubleshooting, check these items:
โ Basic Setupโ
- Keyframes included in JSX
-
.start()
method called - useEffect has proper dependencies
- Cleanup function implemented
โ Performanceโ
- Virtualization enabled for large text
- Stable configuration objects
- GPU acceleration enabled
- Memory leaks prevented
โ Accessibilityโ
- Reduced motion respected
- ARIA attributes configured
- Screen reader support tested
- Keyboard controls working
โ Browser Supportโ
- Target browsers supported
- Polyfills added if needed
- Feature detection implemented
- Mobile optimizations applied
โ TypeScriptโ
- Types imported correctly
- Configuration typed properly
- Event handlers typed
- No type errors in build
๐ Getting Helpโ
If you're still experiencing issues:
- Check the Examples โ Example Gallery
- Review the API โ API Reference
- Search Issues โ GitHub Issues
- Create Minimal Reproduction โ CodeSandbox Template
- Ask for Help โ GitHub Discussions
Creating a Bug Reportโ
Include this information:
- Library version:
npm list use-typewriter-animation
- React version:
npm list react
- Browser/Node version: Check in DevTools
- Minimal reproduction: CodeSandbox link
- Expected behavior: What should happen
- Actual behavior: What actually happens
- Console errors: Any error messages
Remember: Most issues are configuration problems that can be solved quickly with the right approach! ๐ฏ