UNPKG

react-rooks

Version:

Store management for React and React Native with simple hooks !

1,065 lines (856 loc) โ€ข 27.8 kB
# React Rooks ![React Rooks Logo](docs/rook-logo.svg) > **React Rooks is a lightweight state management library for React that brings the simplicity of `useState` to global and contextual state. Just like a chess rook moves in straight lines, your state updates are direct, predictable, and powerful.** [![npm version](https://badge.fury.io/js/react-rooks.svg)](https://badge.fury.io/js/react-rooks) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ๐ŸŽฎ **[Try the Interactive Demo โ†’](https://nastuzzisamy.github.io/react-rooks/)** | ๐Ÿ“– [Documentation](#api-reference) | ๐Ÿš€ [Quick Start](#quick-start) --- ## ๐ŸŽฏ Why Choose React Rooks? **If you love `useState` but need global state**, React Rooks is for you. It's designed to feel exactly like React's built-in hooks while providing powerful state management capabilities. > ๐Ÿ’ก **New to React Rooks?** Check out our [interactive demo](https://nastuzzisamy.github.io/react-rooks/) to see all features in action with real-time state inspection and code tooltips! ### โœจ Key Benefits - **๐Ÿชถ Ultra Lightweight**: No runtime dependencies, pure React - **๐ŸŽฃ Hook-First Design**: Feels exactly like `useState` but for global state - **๐Ÿ”’ Type-Safe**: Full TypeScript support with automatic type inference - **โšก Zero Boilerplate**: No actions, reducers, or selectors required - **๐Ÿงฉ Flexible**: Global stores, scoped stores, multiple stores - **๐Ÿ“ฆ Tree-Shakable**: Only bundle what you use --- ## ๐Ÿ“Š How React Rooks Compares | Feature | React Rooks | Redux Toolkit | Zustand | Jotai | Valtio | | ---------------------- | ------------ | ------------- | ----------- | ------------ | ------------ | | **Bundle Size** | ~2KB | ~47KB | ~8KB | ~13KB | ~14KB | | **useState-like API** | โœ… Perfect | โŒ Complex | โœ… Good | โœ… Good | โš ๏ธ Different | | **TypeScript Support** | โœ… Excellent | โœ… Good | โœ… Good | โœ… Excellent | โœ… Good | | **Zero Boilerplate** | โœ… | โŒ | โœ… | โœ… | โœ… | | **Multiple Stores** | โœ… | โœ… | โœ… | โœ… | โœ… | | **Scoped Providers** | โœ… | โŒ | โš ๏ธ Manual | โœ… | โš ๏ธ Manual | | **Schema Validation** | ๐Ÿ”„ Coming | โŒ | โŒ | โŒ | โŒ | | **Reducers** | โœ… Optional | โœ… Required | โœ… Optional | โœ… | โŒ | | **DevTools** | โŒ | โœ… | โœ… | โœ… | โœ… | --- ## ๐Ÿš€ Quick Start ### Installation ```bash # Using bun (recommended) bun add react-rooks # Using npm npm install react-rooks # Using yarn yarn add react-rooks ``` ### ๐ŸŽฎ Try the Interactive Demo Experience React Rooks in action with our interactive demo: ```bash # Clone and run the demo locally git clone https://github.com/your-username/react-rooks.git cd react-rooks/demo bun install bun dev ``` **Demo Features:** - ๐Ÿ“‹ **Classic Examples**: Todo lists, counters, user profiles - ๐ŸŽฏ **Advanced Patterns**: Scoped stores, reducer integration, conditional rendering - ๐Ÿ”„ **Reducer Examples**: Complex state management with `useRook` and reducers - ๐Ÿ” **Real-time State Inspection**: See state changes as they happen - ๐Ÿ’ก **Code Tooltips**: Hover over components for implementation details ### Basic Usage (Global Store) ```tsx import { createRook } from "react-rooks"; // 1. Create your store (like useState but global) export const [UserStore, useUser] = createRook({ name: "John Doe", email: "john@example.com", theme: "light" as "light" | "dark", }); // 2. Use anywhere in your app function UserProfile() { const [name, setName] = useUser("name"); const [email, setEmail] = useUser("email"); return ( <div> <input value={name} onChange={(e) => setName(e.target.value)} /> <input value={email} onChange={(e) => setEmail(e.target.value)} /> </div> ); } // 3. Wrap your app function App() { return ( <UserStore> <UserProfile /> </UserStore> ); } ``` --- ## ๐ŸŽฏ useState vs useRook React Rooks is designed to feel **exactly** like `useState`: | **useState (React)** | **useRook (React Rooks)** | | --------------------------------------- | -------------------------------------------- | | `const [count, setCount] = useState(0)` | `const [count, setCount] = useRook("count")` | | Component-scoped | Global/contextual scope | | Direct updates | Direct updates | | Type-safe | Type-safe | | Simple API | Simple API | ### Migration is Easy ```tsx // Before: Component state function Counter() { const [count, setCount] = useState(0); return <button onClick={() => setCount((c) => c + 1)}>{count}</button>; } // After: Global state (same API!) const [CounterStore, useCounter] = createRook({ count: 0 }); function Counter() { const [count, setCount] = useCounter("count"); return <button onClick={() => setCount((c) => c + 1)}>{count}</button>; } ``` --- ## ๐Ÿ”ง Upcoming Features React Rooks is actively developed with exciting features coming soon: - **๐Ÿ›ก๏ธ Schema Validation**: Built-in validation system for your stores - **๐Ÿ” DevTools Integration**: Debug your state changes with ease - **๐Ÿ“Š Performance Monitoring**: Track re-renders and optimize performance - **๐Ÿ”„ Time Travel**: Undo/redo functionality for development - **๐Ÿ’พ Persistence**: Automatic state persistence to localStorage/sessionStorage --- ## ๐ŸŽฎ Interactive Demo Experience the full power of React Rooks with our comprehensive demo application that showcases all features in an interactive environment. ### ๐Ÿš€ Running the Demo ```bash git clone https://github.com/your-username/react-rooks.git cd react-rooks/demo bun install && bun dev ``` ### ๐ŸŽฏ What's Inside The demo includes **5 comprehensive examples** that demonstrate: - **๐Ÿ“‹ Classic State Management**: Todo lists, counters, and user profiles - **๐ŸŽฏ Advanced Patterns**: Scoped stores, multiple store instances, conditional rendering - **๐Ÿ”„ Reducer Integration**: Complex state logic with `useRook` and reducer patterns - **๐Ÿช Store Architecture**: Global vs scoped stores, provider composition - **๐Ÿ’ก Real-time Features**: Live state inspection, interactive code tooltips ### ๐Ÿ” Interactive Features - **Real-time State Viewer**: Watch state changes as they happen across all stores - **Code Tooltips**: Hover over any component to see implementation details and explanations - **Live Examples**: Modify state and see immediate updates across multiple components - **Pattern Comparison**: Side-by-side comparison of different state management approaches > ๐Ÿ’ก **Perfect for Learning**: Each example includes detailed explanations and shows best practices for different use cases. --- ## ๐Ÿ—บ๏ธ Roadmap ### ๐ŸŽฏ Version 2.x - Performance & Lifecycle #### ๐Ÿš€ Performance Optimizations - **โšก Smart Re-renders**: Limit re-renders in `useRook` when the accessed key hasn't changed ```tsx // Only re-render when 'name' changes, not when another key changes const [name] = useUser("name"); ``` #### ๐Ÿ”„ Lifecycle Management - **โœ… Initialization Callbacks**: Execute callbacks when store initialization is complete ```tsx const [UserStore] = createRook( { user: null }, { onInitComplete: (store) => { console.log("Store initialized:", store); // Perfect for analytics, logging, or side effects }, } ); ``` - **๐Ÿ—๏ธ Lazy Mounting**: Allow components to render even before store initialization Currently, Rook providers don't render their children until the store is fully initialized. This feature will allow components to mount immediately with loading states. ```tsx // Current behavior: Children don't render until store is ready function App() { return ( <UserStore> {/* Children wait for store initialization */} <UserProfile /> </UserStore> ); } // Future: Components can render with loading states before store is ready function UserProfile() { const { inited } = useRookState(UserStore); const [user] = useUserRook("user"); if (!inited) return <Spinner />; // Shows immediately return <div>{user.name}</div>; } ``` ### ๐Ÿ›ก๏ธ Version 3.x - Schema Validation (Zod Integration) #### ๐Ÿ“‹ Zod v3 Support - **๐Ÿ” Runtime Validation**: Automatic validation of store updates - **๐ŸŽฏ Selective Validation**: Validate only specific keys or entire store - **โš ๏ธ Error Boundaries**: Graceful error handling for validation failures ```tsx import { createZodRook } from "react-rooks/zod"; import { z } from "zod"; const UserSchema = z.object({ name: z.string().min(1), email: z.string().email(), age: z.number().min(0).max(120), }); const [UserStore, useUser] = createZodRook(UserSchema, { validateOnUpdate: true, onValidationError: (error) => { // Handle validation errors gracefully toast.error(`Invalid data: ${error.message}`); }, }); ``` ### ๐Ÿš€ Version 4.x - Advanced Schema Features #### ๐ŸŽญ Enhanced Validation - **๐Ÿ”„ Schema Evolution**: Handle schema migrations and versioning - **๐ŸŽฏ Conditional Validation**: Dynamic schemas based on store state - **๐Ÿ”— Cross-Store Validation**: Validate data across multiple stores - **๐Ÿ“Š Validation Analytics**: Track validation errors and patterns ```tsx // Advanced schema with conditional validation const UserSchema = z .object({ type: z.enum(["admin", "user"]), permissions: z.array(z.string()).optional(), }) .refine( (data) => { // Conditional validation: admins must have permissions if (data.type === "admin") { return data.permissions && data.permissions.length > 0; } return true; }, { message: "Admin users must have at least one permission", } ); ``` --- ## ๐Ÿ“‹ API Reference ### `createRook(initialStore, reducers?)` Creates a global store with optional reducers. ```tsx import { createRook } from "react-rooks"; // Basic store const [Store, useStore] = createRook({ count: 0, user: { name: "", email: "" }, }); // With reducers const [Store, useStore] = createRook( { count: 0 }, { count: (state, action) => { switch (action.type) { case "increment": return state + 1; case "decrement": return state - 1; default: return state; } }, } ); ``` ### `useRook(key?)` Hook to access store values. ```tsx // Access specific key const [count, setCount] = useRook("count"); // Access entire store const [store, setStore] = useRook(); // Functional updates setCount((prevCount) => prevCount + 1); // Direct updates setCount(42); ``` ### `RookContainer` Combine multiple stores. ```tsx import { RookContainer } from "react-rooks"; const [UserStore] = createRook({ name: "" }); const [ThemeStore] = createRook({ mode: "light" }); function App() { return ( <RookContainer rooks={[UserStore, ThemeStore]}> <MyApp /> </RookContainer> ); } ``` **โš ๏ธ Order Matters**: Stores are nested from top to bottom. Components lower in the tree can access stores from higher levels. ```tsx // โœ… Correct: CartStore can access UserStore and ThemeStore <RookContainer rooks={[UserStore, ThemeStore, CartStore]}> <App /> </RookContainer> // โŒ Wrong: UserStore can't access CartStore or ThemeStore <RookContainer rooks={[CartStore, ThemeStore, UserStore]}> <App /> </RookContainer> ``` --- ## ๐Ÿ›๏ธ Real-World Comparison: Shopping Cart Let's see the same shopping cart feature implemented across different state management solutions. **Same functionality, different complexity.** ### ๐Ÿ† React Rooks (22 lines) ```tsx import { createRook } from "react-rooks"; // 1. Create store (2 lines) const [CartStore, useCart] = createRook({ items: [] as Array<{ id: number; name: string; price: number; quantity: number; }>, total: 0, }); // 2. Hook for actions (6 lines) function useCartActions() { const [items, setItems] = useCart("items"); const [, setTotal] = useCart("total"); const addItem = (item: (typeof items)[0]) => { const newItems = [...items, item]; setItems(newItems); setTotal(newItems.reduce((sum, i) => sum + i.price * i.quantity, 0)); }; const removeItem = (id: number) => { const newItems = items.filter((i) => i.id !== id); setItems(newItems); setTotal(newItems.reduce((sum, i) => sum + i.price * i.quantity, 0)); }; return { addItem, removeItem }; } // 3. Component (12 lines) function ShoppingCart() { const [items] = useCart("items"); const [total] = useCart("total"); const { addItem, removeItem } = useCartActions(); return ( <div> <h2> Cart ({items.length} items) - ${total.toFixed(2)} </h2> {items.map((item) => ( <div key={item.id}> {item.name} - ${item.price} x {item.quantity} <button onClick={() => removeItem(item.id)}>Remove</button> </div> ))} <button onClick={() => addItem({ id: Date.now(), name: "New Item", price: 10, quantity: 1 }) } > Add Item </button> </div> ); } // 4. App wrapper (2 lines) function App() { return ( <CartStore> <ShoppingCart /> </CartStore> ); } ``` ### ๐Ÿ“ฆ Redux Toolkit (65 lines) ```tsx import { configureStore, createSlice, PayloadAction } from "@reduxjs/toolkit"; import { Provider, useSelector, useDispatch } from "react-redux"; // 1. Types (4 lines) interface CartItem { id: number; name: string; price: number; quantity: number; } interface CartState { items: CartItem[]; total: number; } // 2. Slice (22 lines) const cartSlice = createSlice({ name: "cart", initialState: { items: [], total: 0, } as CartState, reducers: { addItem: (state, action: PayloadAction<CartItem>) => { state.items.push(action.payload); state.total = state.items.reduce( (sum, item) => sum + item.price * item.quantity, 0 ); }, removeItem: (state, action: PayloadAction<number>) => { state.items = state.items.filter((item) => item.id !== action.payload); state.total = state.items.reduce( (sum, item) => sum + item.price * item.quantity, 0 ); }, }, }); // 3. Store (3 lines) const store = configureStore({ reducer: { cart: cartSlice.reducer }, }); type RootState = ReturnType<typeof store.getState>; // 4. Actions (2 lines) const { addItem, removeItem } = cartSlice.actions; // 5. Component (20 lines) function ShoppingCart() { const { items, total } = useSelector((state: RootState) => state.cart); const dispatch = useDispatch(); const handleAddItem = () => { dispatch( addItem({ id: Date.now(), name: "New Item", price: 10, quantity: 1 }) ); }; const handleRemoveItem = (id: number) => { dispatch(removeItem(id)); }; return ( <div> <h2> Cart ({items.length} items) - ${total.toFixed(2)} </h2> {items.map((item) => ( <div key={item.id}> {item.name} - ${item.price} x {item.quantity} <button onClick={() => handleRemoveItem(item.id)}>Remove</button> </div> ))} <button onClick={handleAddItem}>Add Item</button> </div> ); } // 6. App wrapper (6 lines) function App() { return ( <Provider store={store}> <ShoppingCart /> </Provider> ); } ``` ### ๐Ÿป Zustand (35 lines) ```tsx import { create } from "zustand"; // 1. Types (4 lines) interface CartItem { id: number; name: string; price: number; quantity: number; } interface CartStore { items: CartItem[]; total: number; addItem: (item: CartItem) => void; removeItem: (id: number) => void; } // 2. Store (18 lines) const useCartStore = create<CartStore>((set, get) => ({ items: [], total: 0, addItem: (item) => set((state) => { const newItems = [...state.items, item]; return { items: newItems, total: newItems.reduce((sum, i) => sum + i.price * i.quantity, 0), }; }), removeItem: (id) => set((state) => { const newItems = state.items.filter((i) => i.id !== id); return { items: newItems, total: newItems.reduce((sum, i) => sum + i.price * i.quantity, 0), }; }), })); // 3. Component (12 lines) function ShoppingCart() { const { items, total, addItem, removeItem } = useCartStore(); return ( <div> <h2> Cart ({items.length} items) - ${total.toFixed(2)} </h2> {items.map((item) => ( <div key={item.id}> {item.name} - ${item.price} x {item.quantity} <button onClick={() => removeItem(item.id)}>Remove</button> </div> ))} <button onClick={() => addItem({ id: Date.now(), name: "New Item", price: 10, quantity: 1 }) } > Add Item </button> </div> ); } // 4. App (1 line) function App() { return <ShoppingCart />; } ``` ### โš›๏ธ Context + useState (45 lines) ```tsx import { createContext, useContext, useState, ReactNode } from "react"; // 1. Types (4 lines) interface CartItem { id: number; name: string; price: number; quantity: number; } interface CartContextType { items: CartItem[]; total: number; addItem: (item: CartItem) => void; removeItem: (id: number) => void; } // 2. Context (2 lines) const CartContext = createContext<CartContextType | undefined>(undefined); // 3. Provider (23 lines) function CartProvider({ children }: { children: ReactNode }) { const [items, setItems] = useState<CartItem[]>([]); const [total, setTotal] = useState(0); const addItem = (item: CartItem) => { const newItems = [...items, item]; setItems(newItems); setTotal(newItems.reduce((sum, i) => sum + i.price * i.quantity, 0)); }; const removeItem = (id: number) => { const newItems = items.filter((i) => i.id !== id); setItems(newItems); setTotal(newItems.reduce((sum, i) => sum + i.price * i.quantity, 0)); }; return ( <CartContext.Provider value={{ items, total, addItem, removeItem }}> {children} </CartContext.Provider> ); } // 4. Hook (5 lines) function useCart() { const context = useContext(CartContext); if (!context) { throw new Error("useCart must be used within CartProvider"); } return context; } // 5. Component (12 lines) function ShoppingCart() { const { items, total, addItem, removeItem } = useCart(); return ( <div> <h2> Cart ({items.length} items) - ${total.toFixed(2)} </h2> {items.map((item) => ( <div key={item.id}> {item.name} - ${item.price} x {item.quantity} <button onClick={() => removeItem(item.id)}>Remove</button> </div> ))} <button onClick={() => addItem({ id: Date.now(), name: "New Item", price: 10, quantity: 1 }) } > Add Item </button> </div> ); } // 6. App wrapper (3 lines) function App() { return ( <CartProvider> <ShoppingCart /> </CartProvider> ); } ``` ### ๐Ÿ“Š Comparison Results | Metric | React Rooks | Redux Toolkit | Zustand | Context + useState | | ------------------------ | ----------- | ------------- | ------- | ------------------- | | **Total Lines of Code** | 22 โญ | 65 | 35 | 45 | | **Concepts to Learn** | 1 โญ | 5 | 2 | 3 | | **Boilerplate Required** | Minimal โญ | Heavy | Medium | Medium | | **TypeScript Inference** | Auto โญ | Manual | Manual | Manual | | **useState-like API** | โœ… โญ | โŒ | โš ๏ธ | โœ… | | **Performance** | Optimal โญ | Good | Good | Manual Optimization | ### ๐ŸŽฏ Why React Rooks Wins 1. **๐Ÿชถ Simplicity**: Just 22 lines vs 65 for Redux Toolkit 2. **๐ŸŽฃ Familiar API**: Uses `useState` syntax you already know 3. **๐Ÿ”’ Type Safety**: Automatic TypeScript inference without manual typing 4. **โšก Zero Concepts**: No actions, reducers, selectors, or providers to learn 5. **๐Ÿงฉ Direct Updates**: Change state directly like `useState` **Same functionality, 66% less code, 80% fewer concepts to learn.** ๐Ÿ† --- ## ๐Ÿ—๏ธ Advanced Features ### Multiple Stores with Scoping ```tsx // Create separate stores for different domains const [UserStore, useUser] = createRook({ defaultStore: { profile: { name: "", email: "" }, preferences: { theme: "light", notifications: true }, }, }); const [CartStore, useCart] = createRook({ defaultStore: { items: [], total: 0, }, }); // Use them together function App() { return ( <RookContainer rooks={[UserStore, CartStore]}> <Header /> <MainContent /> <Footer /> </RookContainer> ); } // Or scope them to specific parts of your app function UserSection() { return ( <UserStore> <UserProfile /> <UserSettings /> </UserStore> ); } ``` ### ๐Ÿ”— Store Order and Dependencies **The order of stores in `RookContainer` is crucial!** Stores are nested from top to bottom, so components can only access stores that are positioned above them in the array. ```tsx // ๐Ÿช Three stores with different responsibilities const [UserStore, useUser] = createRook({ defaultStore: { user: { id: 1, name: "Alice", role: "admin" }, isLoggedIn: true, }, }); const [ThemeStore, useTheme] = createRook({ defaultStore: { mode: "light" as "light" | "dark", primaryColor: "#3b82f6", }, }); const [CartStore, useCart] = createRook({ defaultStore: { items: [] as CartItem[], total: 0, }, }); // Component that consumes from multiple stores function SmartCartManager() { // โœ… Can access UserStore (positioned above) const [user] = useUser("user"); const [isLoggedIn] = useUser("isLoggedIn"); // โœ… Can access ThemeStore (positioned above) const [mode] = useTheme("mode"); // โœ… Can access CartStore (same level) const [items, setItems] = useCart("items"); const addItem = () => { if (!isLoggedIn) { alert(`${user.name}, please log in first!`); return; } const newItem = { id: Date.now(), name: `Item ${items.length + 1}`, price: 29.99, quantity: 1, }; setItems([...items, newItem]); }; return ( <div style={{ backgroundColor: mode === "dark" ? "#1f2937" : "#f9fafb", padding: "20px", borderRadius: "8px", }} > <h3>๐Ÿ›’ Cart for {user.name}</h3> <p>Theme: {mode} mode</p> <button onClick={addItem} disabled={!isLoggedIn}> Add Item to Cart </button> <p>Items in cart: {items.length}</p> </div> ); } // โœ… CORRECT: Proper order allows SmartCartManager to access all stores function CorrectApp() { return ( <RookContainer rooks={[UserStore, ThemeStore, CartStore]}> <SmartCartManager /> </RookContainer> ); } // โŒ WRONG: CartStore is first, so SmartCartManager can't access UserStore/ThemeStore function WrongApp() { return ( <RookContainer rooks={[CartStore, UserStore, ThemeStore]}> <SmartCartManager /> {/* This will throw errors! */} </RookContainer> ); } ``` ### ๐Ÿ’ก RookContainer Best Practices 1. **Order by Dependency**: Place stores that others depend on first 2. **Logical Hierarchy**: User โ†’ Theme โ†’ Feature-specific stores 3. **Scope Appropriately**: Only include stores that components actually need ```tsx // ๐Ÿ“Š Recommended order patterns: // For E-commerce app: <RookContainer rooks={[ AuthStore, // 1. Authentication (most fundamental) ThemeStore, // 2. UI preferences UserStore, // 3. User data CartStore, // 4. Shopping functionality CheckoutStore // 5. Specific features ]}> // For Admin dashboard: <RookContainer rooks={[ AuthStore, // 1. Who is logged in? PermissionStore,// 2. What can they do? ThemeStore, // 3. How does it look? DataStore // 4. Application data ]}> // For Blog: <RookContainer rooks={[ UserStore, // 1. Reader preferences ThemeStore, // 2. Display settings PostStore, // 3. Content data CommentStore // 4. Interactive features ]}> ``` ### Custom Reducers ```tsx const [TodoStore, useTodos] = createRook( { todos: [], filter: "all", }, { todos: (state, action) => { switch (action.type) { case "ADD_TODO": return [...state, { id: Date.now(), text: action.text, done: false }]; case "TOGGLE_TODO": return state.map((todo) => todo.id === action.id ? { ...todo, done: !todo.done } : todo ); case "DELETE_TODO": return state.filter((todo) => todo.id !== action.id); default: return state; } }, } ); function TodoList() { const [todos, dispatch] = useTodos("todos"); const addTodo = (text: string) => { dispatch({ type: "ADD_TODO", text }); }; const toggleTodo = (id: number) => { dispatch({ type: "TOGGLE_TODO", id }); }; } ``` ### Server-Side Rendering (SSR) ```tsx import { createRook } from "react-rooks"; // Initialize with server data const [AppStore, useApp] = createRook({ user: typeof window !== "undefined" ? JSON.parse(localStorage.getItem("user") || "null") : null, theme: typeof window !== "undefined" ? localStorage.getItem("theme") || "light" : "light", }); // Hydrate on client function App({ initialData }: { initialData?: any }) { return ( <AppStore initialValue={initialData}> <MyApp /> </AppStore> ); } ``` --- ## ๐ŸŽญ Philosophy: The Chess Rook ``` ____ | | |____| | | |____| | | /|____|\ /_|____|_\ | | |____| / \ /____\ [ DATA ] ``` Just like a rook in chess, React Rooks represents: - **๐Ÿฐ Centralized Power**: A strong, reliable foundation for your state - **๐Ÿ“ Straight Lines**: Direct, predictable state updates (no magic) - **โ™Ÿ๏ธ Strategic Position**: Can be placed anywhere in your component tree - **๐Ÿ”’ Defensive**: Type-safe and validated data protection - **โšก Fast Movement**: Instant updates across your entire application The rook doesn't move in complex patternsโ€”it's straightforward, powerful, and reliable. That's exactly how your state management should be. --- ## ๐Ÿค Contributing We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details. ### Development Setup ```bash git clone https://github.com/your-username/react-rooks.git cd react-rooks # Using bun (recommended) bun install bun run dev # Using npm npm install npm run dev # Using yarn yarn install yarn dev ``` --- ## ๐Ÿ“„ License MIT ยฉ [Your Name](https://github.com/your-username) --- ## ๐Ÿ™ Acknowledgments - Inspired by React's `useState` hook - Built with TypeScript for type safety - Chess rook metaphor for clear mental model --- **Ready to move your state in straight lines? Start with React Rooks today! ๐Ÿฐ**