Discover the hidden power of React’s flexibility and elevate your UI component game! In this in-depth exploration, we’ll dive into four expert-level patterns that will transform your coding skills:
- Compound Components: Build modular, reusable UI elements
- Render Props: Harness the power of flexible, dynamic rendering
- Higher-Order Components (HOCs): Wrap your components with reusable logic
- Controlled vs. Uncontrolled Components: Master the art of state management
Get ready to revolutionize your React development workflow and create stunning, efficient UI components that leave a lasting impression!
1. Compound Components
Compound Components enable the creation of components that work together seamlessly. They allow the parent component to provide context and control, while child components communicate with it.
This example demonstrates a Tabs component that allows switching between different panels. Each tab and panel is a child component that communicates with the parent Tabs component via context.
import React, { useState, createContext, useContext } from 'react';
const TabsContext = createContext();
function Tabs({ children, defaultActiveTab }) {
const [activeTab, setActiveTab] = useState(defaultActiveTab);
return (
{children}
);
}
function TabList({ children }) {
return {children};
}
function Tab({ children, name }) {
const { activeTab, setActiveTab } = useContext(TabsContext);
const isActive = activeTab === name;
return (
);
}
function TabPanels({ children }) {
return {children};
}
function TabPanel({ children, name }) {
const { activeTab } = useContext(TabsContext);
return activeTab === name ? {children} : null;
}
export { Tabs, TabList, Tab, TabPanels, TabPanel };
Usage:
Tab 1
Tab 2
Content for Tab 1
Content for Tab 2
2. Render Props
Render Props is a pattern where a function is passed as a prop to a component. It provides flexibility in rendering logic.
This example creates a MouseTracker component that tracks the mouse position and uses a render prop to display the data in a customizable way.
function MouseTracker({ render }) {
const [position, setPosition] = useState({ x: 0, y: 0 });
function handleMouseMove(event) {
setPosition({ x: event.clientX, y: event.clientY });
}
return (
{render(position)}
);
}
export default MouseTracker;
Usage:
(
Mouse position: ({x}, {y})
)} />
3. Higher-Order Components (HOCs)
HOCs are functions that take a component and return a new component, enhancing functionality.
Example: Authentication HOC
This example creates an HOC withAuth that wraps a component and ensures only authenticated users can access it. If the user is not authenticated, it displays a login message.
function withAuth(WrappedComponent) {
return function AuthenticatedComponent(props) {
const isAuthenticated = !!localStorage.getItem('authToken');
if (!isAuthenticated) {
return Please log in to access this page.;
}
return ;
};
}
export default withAuth;
Usage:
function Dashboard() {
return Welcome to the Dashboard!
;
}
export default withAuth(Dashboard);
4. Controlled vs. Uncontrolled Components
Controlled components are fully controlled by React state, while uncontrolled components rely on the DOM.
Controlled component This example shows a controlled input field where the value is managed by React state.
function ControlledInput() {
const [value, setValue] = useState('');
return (
setValue(e.target.value)}
/>
);
}
This example demonstrates an uncontrolled input field where the value is accessed directly from the DOM using a ref.
function UncontrolledInput() {
const inputRef = useRef();
function handleClick() {
alert(inputRef.current.value);
}
return (
);
}
Conclusion
These advanced React patterns enhance component reusability and maintainability. By understanding and applying them, you can create more robust and scalable applications.
Experiment with these patterns and find the ones that best suit your projects!