epic-react-patterns

安装量: 35
排名: #19542

安装

npx skills add https://github.com/epicweb-dev/epic-stack --skill epic-react-patterns

Epic Stack: React Patterns and Guidelines When to use this skill

Use this skill when you need to:

Write efficient React components in Epic Stack applications Optimize performance and bundle size Follow React Router patterns and conventions Avoid common React anti-patterns Implement proper code splitting Optimize re-renders and data fetching Use React hooks correctly Philosophy

Following Epic Web principles:

Make it work, make it right, make it fast - In that order. First make it functional, then refactor for clarity, then optimize for performance. Pragmatism over purity - Choose practical solutions that work well in your context rather than theoretically perfect ones. Optimize for sustainable velocity - Write code that's easy to maintain and extend, not just fast to write initially. Do as little as possible - Only add complexity when it provides real value. Patterns and conventions Data Fetching in React Router

Epic Stack uses React Router loaders for data fetching, not useEffect.

✅ Good - Use loaders:

// app/routes/users/$username.tsx export async function loader({ params }: Route.LoaderArgs) { const user = await prisma.user.findUnique({ where: { username: params.username }, }) return { user } }

export default function UserRoute({ loaderData }: Route.ComponentProps) { return

{loaderData.user.name}
}

❌ Avoid - Don't fetch in useEffect:

// ❌ Don't do this export default function UserRoute({ params }: Route.ComponentProps) { const [user, setUser] = useState(null)

useEffect(() => {
    fetch(`/api/users/${params.username}`)
        .then(res => res.json())
        .then(setUser)
}, [params.username])

return user ? <div>{user.name}</div> : <div>Loading...</div>

}

Avoid useEffect for Side Effects

You Might Not Need useEffect

Instead of using useEffect, use event handlers, CSS, ref callbacks, or useSyncExternalStore.

✅ Good - Use event handlers:

function ProductPage({ product, addToCart }: Route.ComponentProps) { function buyProduct() { addToCart(product) showNotification(Added ${product.name} to cart!) }

function handleBuyClick() {
    buyProduct()
}

function handleCheckoutClick() {
    buyProduct()
    navigate('/checkout')
}

return (
    <div>
        <button onClick={handleBuyClick}>Buy Now</button>
        <button onClick={handleCheckoutClick}>Checkout</button>
    </div>
)

}

❌ Avoid - Side effects in useEffect:

// ❌ Don't do this function ProductPage({ product, addToCart }: Route.ComponentProps) { useEffect(() => { if (product.isInCart) { showNotification(Added ${product.name} to cart!) } }, [product])

function handleBuyClick() {
    addToCart(product)
}

// ...

}

✅ Appropriate use of useEffect:

// ✅ Good - Event listeners are appropriate useEffect(() => { const controller = new AbortController()

window.addEventListener(
    'keydown',
    (event: KeyboardEvent) => {
        if (event.key !== 'Escape') return
        // handle escape key
    },
    { signal: controller.signal },
)

return () => {
    controller.abort()
}

}, [])

Code Splitting with React Router

React Router automatically code-splits by route. Use dynamic imports for heavy components.

✅ Good - Dynamic imports:

// app/routes/admin/dashboard.tsx import { lazy } from 'react'

const AdminChart = lazy(() => import('#app/components/admin/chart.tsx'))

export default function AdminDashboard() { return ( Loading chart...\