# Building Reusable React Components: Patterns & Best Practices
Picked up reactjs on a Friday. By Sunday, I had something running in production. Here's my actual learning path.
Why This Matters (and Why I Care)
Honestly, most devs over-engineer components. At Beyin Digital, we ship bilingual products for clients in Abu Dhabi. I learned fast that reusable components aren't about "generic" code—they're about predictable APIs. When I have to switch between Arabic and English layouts, I can't afford prop spaghetti. Compound components saved my team 30% dev time on our last e-commerce dashboard.
The Basics You Actually Need
Start with composition over configuration. Here's what we actually use in production:
// Compound component pattern - Beyin Digital's go-to
interface SelectContextType {
value: string
onChange: (value: string) => void
}
const SelectContext = createContext<SelectContextType | null>(null)
function Select({ children, value, onChange }: {
children: React.ReactNode
value: string
onChange: (value: string) => void
}) {
return (
<SelectContext.Provider value={{ value, onChange }}>
<div className="relative">{children}</div>
</SelectContext.Provider>
)
}
Select.Option = function Option({ value, children }: {
value: string
children: React.ReactNode
}) {
const ctx = useContext(SelectContext)
if (!ctx) throw new Error('Option must be inside Select')
return (
<button onClick={() => ctx.onChange(value)}>
{children}
</button>
)
}
How I Build With It (Step by Step)
First, I identify the shared state. In our booking system, every dropdown needed the same open/close behavior. Instead of copy-pasting `useState` everywhere, I built a `<Dropdown>` compound component:
function Dropdown({ children }: { children: React.ReactNode }) {
const [open, setOpen] = useState(false)
// Shared logic for click outside
useEffect(() => {
if (!open) return
const handleClick = () => setOpen(false)
document.addEventListener('click', handleClick)
return () => document.removeEventListener('click', handleClick)
}, [open])
return (
<DropdownContext.Provider value={{ open, setOpen }}>
<div className="relative">{children}</div>
</DropdownContext.Provider>
)
}
Second, I extract the pattern into a reusable hook. This is where most tutorials stop—but the real value is in the API design.
Mistakes I Made (So You Don't Have To)
1. **Prop drilling everything**: I used to pass 10+ props down. Compound components eliminated that entirely.
2. **Over-abstracting early**: Tried to build a "universal" button component with 20 variants. Waste of time. Start with 3, iterate.
3. **Ignoring TypeScript strict mode**: Without strict types, refactoring breaks silently. Enable `strict: true` from day one.
Advanced Tips From Production
My Honest Take
Compound components aren't new, but they're still underused. Every project at Beyin Digital uses this pattern now. It's not about being clever—it's about writing code that doesn't make you cringe 6 months later. Start with one reusable component today, not a library.
---
*Mohamed Qurashi | Full-Stack Developer at Beyin Digital | [https://qurashi.dev](https://qurashi.dev)*
---
**Further reading:**
**Related articles on this blog:**