Beyond Hooks: Exploring Custom React Patterns for Scalable Applications
In today’s React ecosystem, hooks have become synonymous with writing modern and reusable components. But as applications scale, the need for more structured and tailored patterns becomes evident. In this article, I’ll explore some lesser-discussed but highly effective patterns for building scalable and maintainable React applications.
When building complex components like modals, tabs, or dropdowns, the compound component pattern shines. It allows you to provide a set of components that work together while maintaining flexibility for the consumer.
Example: Building a Custom Tabs Component
import { useState, Children, cloneElement } from "react";
const Tabs = ({ children }) => {
const [activeTab, setActiveTab] = useState(0);
return (
<div>
{Children.map(children, (child, index) => {
return cloneElement(child, {
activeTab,
setActiveTab,
index,
});
})}
</div>
);
};
Tabs.Tab = ({ index, activeTab, setActiveTab, children }) => (
<button
style={{ fontWeight: activeTab === index ? "bold" : "normal" }}
onClick={() => setActiveTab(index)}
>
{children}
</button>
);
Tabs.Panel = ({ index, activeTab, children }) => {
return activeTab === index ? <div>{children}</div> : null;
};
// Usage
<Tabs>
<Tabs.Tab>Tab 1</Tabs.Tab>
<Tabs.Tab>Tab 2</Tabs.Tab>
<Tabs.Panel>Content for Tab 1</Tabs.Panel>
<Tabs.Panel>Content for Tab 2</Tabs.Panel>
</Tabs>
This pattern ensures that your components remain cohesive yet customizable.
Render props are a flexible way to share logic between components. Although hooks have replaced many use cases, render props still excel when you want complete control over the rendered output.
Example: Mouse Tracker
import { useState } from "react";
const MouseTracker = ({ children }) => {
const [position, setPosition] = useState({ x: 0, y: 0 });
const handleMouseMove = (e) => {
setPosition({ x: e.clientX, y: e.clientY });
};
return (
<div style={{ height: "100vh" }} onMouseMove={handleMouseMove}>
{children(position)}
</div>
);
};
// Usage
<MouseTracker>
{({ x, y }) => <h1>The mouse is at ({x}, {y})</h1>}
</MouseTracker>
This pattern gives full control to the consuming component while encapsulating the reusable logic.
Managing forms in React can get tricky, especially in large apps. Leveraging controlled and uncontrolled components appropriately can simplify state management.
Recommended by LinkedIn
Tip:
Example:
import { useRef } from "react";
const UncontrolledForm = () => {
const inputRef = useRef();
const handleSubmit = (e) => {
e.preventDefault();
alert(`Input Value: ${inputRef.current.value}`);
};
return (
<form onSubmit={handleSubmit}>
<input ref={inputRef} />
<button type="submit">Submit</button>
</form>
);
};
This distinction ensures better performance and clarity when handling user inputs.
While hooks have largely replaced HOCs, they’re still valuable for cross-cutting concerns like logging or performance tracking.
Example: Logging Props
import { useEffect } from "react";
const withLogger = (WrappedComponent) => {
return (props) => {
useEffect(() => {
console.log("Props: ", props);
}, [props]);
return <WrappedComponent {...props} />;
};
};
const MyComponent = ({ name }) => <div>Hello, {name}</div>;
const LoggedComponent = withLogger(MyComponent);
// Usage
<LoggedComponent name="React" />;
This demonstrates how HOCs can abstract repetitive logic effectively.
Final Thoughts
While hooks are indispensable in modern React, leveraging advanced patterns like compound components, render props, and HOCs ensures scalability and flexibility as your app grows. These patterns may not be new, but their thoughtful implementation can make a world of difference in your project’s architecture.
#ReactJS #WebDevelopment #JavaScript #Programming #SoftwareEngineering #FrontendDevelopment #ReactPatterns #ScalableApps #CleanCode #TechInsights
60k+ FOLLOWERS || SR. SOFTWARE DEVELOPER || REACTJS || VUEJS || REACT NATIVE || NODEJS || NEXTJS || GRAPHQL || JEST || AWS || WhatsApp: 8700969004
1wInsightful
Frontend Developer @ Comhard Technologies Pvt Ltd
1wVery informative