Hooks are a feature introduced in React 16.8 that allow you to use state and other React features without writing a class. They enable you to reuse stateful logic between components, making your code more concise and easier to understand. Common built-in hooks include useState, useEffect, useContext, useRef, and more.
This example demonstrates basic React hooks: useState, useEffect, and useRef.
Count: 0
Ref Value: 0
Check the browser console to see the effects of different hooks.
// HooksExample.tsx
import React, { useState, useEffect, useRef } from "react";
export const HooksExample: React.FC = () => {
// useState - Managing state in a functional component
const [count, setCount] = useState(0);
const [isActive, setIsActive] = useState(false);
// useRef - Persisting values across renders without causing re-renders
const intervalRef = useRef<NodeJS.Timeout | null>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
// useEffect - Side effects like API calls, DOM manipulation, subscriptions
useEffect(() => {
// This runs after every render
document.title = `Count: ${count}`;
// This cleanup function runs before the component unmounts
// or before the effect runs again
return () => {
document.title = 'React App';
};
}, [count]); // Only re-run when count changes
useEffect(() => {
// Focus the button when the component mounts
if (buttonRef.current) {
buttonRef.current.focus();
}
// Clean up any intervals on unmount
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
};
}, []); // Empty dependency array means this runs once on mount
// Toggle the counter
const toggleCounter = () => {
setIsActive(!isActive);
if (!isActive) {
// Start the interval
intervalRef.current = setInterval(() => {
setCount(c => c + 1);
}, 1000);
} else {
// Stop the interval
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
}
};
// Reset the counter
const resetCounter = () => {
setCount(0);
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
setIsActive(false);
};
return (
<div className="flex flex-col items-center space-y-4">
<div className="text-4xl font-bold">{count}</div>
<div className="space-x-2">
<button
ref={buttonRef}
onClick={toggleCounter}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
{isActive ? 'Pause' : 'Start'}
</button>
<button
onClick={resetCounter}
className="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600"
>
Reset
</button>
</div>
<div className="text-sm text-gray-500">
{isActive ? 'Counter is running' : 'Counter is paused'}
</div>
</div>
);
};