Quick Start Guide
Get up and running with light-hooks in 5 minutes. Transform your React components with powerful, lightweight hooks.
Ready to supercharge your React app? This guide will get you from zero to hero with light-hooks in just a few minutes!
Note:
This guide assumes you have a React project already set up. If you don't, create one with npx create-react-app my-app or npm create vite@latest my-app -- --template react.
Build a Complete Todo App
We'll build a fully functional todo app showcasing the most popular light-hooks. By the end, you'll have a real app and understand how to use:
useLocalStorage- for persistent datauseToggle- for boolean statesuseCounter- for managing numbersuseDebounce- for search optimization
Step 1: Install and Setup
Install light-hooks in your project:
npm install light-hooks
Create a new component file TodoApp.jsx (or .tsx for TypeScript):
import React, { useState } from 'react';
import { 
  useLocalStorage, 
  useToggle, 
  useCounter, 
  useDebounce 
} from 'light-hooks';
export default function TodoApp() {
  return <div>Let's build something awesome!</div>;
}
Step 2: Persistent Todo Storage
Replace the basic useState with persistent storage:
function TodoApp() {
  // This replaces useState and automatically syncs with localStorage!
  const [todos, setTodos] = useLocalStorage('my-todos', []);
  const [newTodo, setNewTodo] = useState('');
  const addTodo = () => {
    if (newTodo.trim()) {
      setTodos([...todos, {
        id: Date.now(),
        text: newTodo,
        completed: false
      }]);
      setNewTodo('');
    }
  };
  return (
    <div style={{ padding: '20px', maxWidth: '500px', margin: '0 auto' }}>
      <h1>My Awesome Todo App</h1>
      
      <div style={{ marginBottom: '20px' }}>
        <input
          value={newTodo}
          onChange={(e) => setNewTodo(e.target.value)}
          placeholder="What needs to be done?"
          style={{ padding: '10px', marginRight: '10px', width: '300px' }}
        />
        <button onClick={addTodo} style={{ padding: '10px' }}>
          Add Todo
        </button>
      </div>
      <div>
        {todos.map(todo => (
          <div key={todo.id} style={{ padding: '10px', border: '1px solid #ddd', margin: '5px 0' }}>
            {todo.text}
          </div>
        ))}
      </div>
    </div>
  );
}
Note:
Amazing! Your todos now persist automatically. Refresh the page - they're still there!
Step 3: Add Toggle Functionality
Let's add the ability to mark todos as complete using useToggle:
function TodoItem({ todo, onToggle, onDelete }) {
  return (
    <div style={{ 
      padding: '10px', 
      border: '1px solid #ddd', 
      margin: '5px 0',
      display: 'flex',
      justifyContent: 'space-between',
      backgroundColor: todo.completed ? '#f0f8f0' : 'white'
    }}>
      <span 
        style={{ 
          textDecoration: todo.completed ? 'line-through' : 'none',
          color: todo.completed ? '#888' : 'black'
        }}
      >
        {todo.text}
      </span>
      <div>
        <button 
          onClick={() => onToggle(todo.id)}
          style={{ marginRight: '10px', padding: '5px 10px' }}
        >
          {todo.completed ? 'Undo' : 'Done'}
        </button>
        <button 
          onClick={() => onDelete(todo.id)}
          style={{ padding: '5px 10px', backgroundColor: '#ff4444', color: 'white' }}
        >
          Delete
        </button>
      </div>
    </div>
  );
}
function TodoApp() {
  const [todos, setTodos] = useLocalStorage('my-todos', []);
  const [newTodo, setNewTodo] = useState('');
  
  // Perfect for show/hide states!
  const [showCompleted, toggleShowCompleted] = useToggle(true);
  const addTodo = () => {
    if (newTodo.trim()) {
      setTodos([...todos, {
        id: Date.now(),
        text: newTodo,
        completed: false
      }]);
      setNewTodo('');
    }
  };
  const toggleTodo = (id) => {
    setTodos(todos.map(todo => 
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };
  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };
  const filteredTodos = showCompleted 
    ? todos 
    : todos.filter(todo => !todo.completed);
  return (
    <div style={{ padding: '20px', maxWidth: '500px', margin: '0 auto' }}>
      <h1>My Awesome Todo App</h1>
      
      <div style={{ marginBottom: '20px' }}>
        <input
          value={newTodo}
          onChange={(e) => setNewTodo(e.target.value)}
          placeholder="What needs to be done?"
          style={{ padding: '10px', marginRight: '10px', width: '300px' }}
        />
        <button onClick={addTodo} style={{ padding: '10px' }}>
          Add Todo
        </button>
      </div>
      <div style={{ marginBottom: '20px' }}>
        <button 
          onClick={toggleShowCompleted}
          style={{ padding: '10px' }}
        >
          {showCompleted ? 'Hide' : 'Show'} Completed
        </button>
      </div>
      <div>
        {filteredTodos.map(todo => (
          <TodoItem 
            key={todo.id} 
            todo={todo} 
            onToggle={toggleTodo}
            onDelete={deleteTodo}
          />
        ))}
      </div>
    </div>
  );
}
Step 4: Add Statistics with useCounter
Let's add some stats using useCounter:
function TodoStats({ todos }) {
  // useCounter provides increment, decrement, reset, and set methods!
  const [viewCount, { increment: incrementViews }] = useCounter(0);
  React.useEffect(() => {
    incrementViews(); // Count each time stats are viewed
  }, []);
  const completed = todos.filter(todo => todo.completed).length;
  const total = todos.length;
  const pending = total - completed;
  return (
    <div style={{ 
      padding: '15px', 
      backgroundColor: '#f5f5f5', 
      borderRadius: '8px',
      margin: '20px 0'
    }}>
      <h3>Statistics</h3>
      <p>Total: {total}</p>
      <p>Completed: {completed}</p>
      <p>Pending: {pending}</p>
      <p>Times viewed: {viewCount}</p>
    </div>
  );
}
// Add <TodoStats todos={todos} /> to your TodoApp component
Step 5: Add Smart Search with useDebounce
Finally, let's add a search feature that doesn't spam the filter function:
function TodoApp() {
  const [todos, setTodos] = useLocalStorage('my-todos', []);
  const [newTodo, setNewTodo] = useState('');
  const [showCompleted, toggleShowCompleted] = useToggle(true);
  
  // Search functionality
  const [searchTerm, setSearchTerm] = useState('');
  // Only searches after user stops typing for 300ms!
  const debouncedSearch = useDebounce(searchTerm, 300);
  // ... other functions ...
  const filteredTodos = todos
    .filter(todo => showCompleted || !todo.completed)
    .filter(todo => 
      debouncedSearch 
        ? todo.text.toLowerCase().includes(debouncedSearch.toLowerCase())
        : true
    );
  return (
    <div style={{ padding: '20px', maxWidth: '500px', margin: '0 auto' }}>
      <h1>My Awesome Todo App</h1>
      
      {/* Add Todo Section */}
      <div style={{ marginBottom: '20px' }}>
        <input
          value={newTodo}
          onChange={(e) => setNewTodo(e.target.value)}
          placeholder="What needs to be done?"
          style={{ padding: '10px', marginRight: '10px', width: '300px' }}
        />
        <button onClick={addTodo} style={{ padding: '10px' }}>
          Add Todo
        </button>
      </div>
      {/* Search Section */}
      <div style={{ marginBottom: '20px' }}>
        <input
          value={searchTerm}
          onChange={(e) => setSearchTerm(e.target.value)}
          placeholder="Search todos..."
          style={{ padding: '10px', width: '100%' }}
        />
      </div>
      {/* Controls */}
      <div style={{ marginBottom: '20px' }}>
        <button 
          onClick={toggleShowCompleted}
          style={{ padding: '10px' }}
        >
          {showCompleted ? 'Hide' : 'Show'} Completed
        </button>
      </div>
      {/* Stats */}
      <TodoStats todos={todos} />
      {/* Todo List */}
      <div>
        {filteredTodos.length === 0 ? (
          <p style={{ textAlign: 'center', color: '#888' }}>
            {debouncedSearch ? 'No todos match your search' : 'No todos yet. Add one above!'}
          </p>
        ) : (
          filteredTodos.map(todo => (
            <TodoItem 
              key={todo.id} 
              todo={todo} 
              onToggle={toggleTodo}
              onDelete={deleteTodo}
            />
          ))
        )}
      </div>
    </div>
  );
}
Congratulations!
You've just built a complete todo app using light-hooks! Here's what you accomplished:
- Persistent Storage: Todos survive page refreshes with 
useLocalStorage - Smart Toggles: Show/hide completed items with 
useToggle - Statistics: View counting with 
useCounter - Optimized Search: Debounced filtering with 
useDebounce 
Note:
Pro Tip: Your app automatically handles edge cases like empty states, persistence, and performance optimization - all thanks to light-hooks!
What's Next?
Now that you've mastered the basics, explore more hooks:
useInterval- for auto-refresh functionalityuseTimeout- for delayed actionsusePrevious- to compare with previous valuesuseUpdateEffect- useEffect that skips first render
Ready to dive deeper? Check out our individual hook documentation for advanced patterns and real-world examples!
Key Takeaways
- Less Boilerplate: light-hooks eliminate common React patterns
 - Built-in Persistence: 
useLocalStoragehandles serialization automatically - Performance Optimized: 
useDebounceprevents excessive function calls - TypeScript Ready: Full type safety out of the box
 - Tree Shakable: Import only what you need