React design patterns are established practices and solutions that developers utilize to address common problems and challenges encountered when building applications with React. These patterns encapsulate reusable solutions to recurring design problems, promoting maintainability, scalability, and efficiency. They provide a structured approach to organizing components, managing state, handling data flow, and optimizing performance.
Consider the following as the top 6 React design patterns:
Container and presentation pattern
The HOC(Higher Order Component)Pattern
Compound Components Pattern
Provider Pattern(Data management with Providers)
State reducer pattern
Component Composition pattern
- Container and presentation pattern In this pattern, Container Components are responsible for managing data and state logic. They fetch data from external sources, manipulate it if necessary, and pass it down to Presentational Components as props. They are often connected to external services, Redux stores, or context providers.
On the other hand, Presentational Components are focused solely on the presentation of UI elements. They receive data from Container Components via props and render it in a visually appealing way. Presentational Components are typically stateless functional components or pure components, making them easier to test and reuse.
Let's consider a complex example to illustrate these patterns:
Suppose we're building a social media dashboard where users can view their friends' posts and interact with them. Here's how we could structure our components:
Container Component (FriendFeedContainer):
This component would be responsible for fetching data about friends' posts from an API, handling any necessary data transformations, and managing the state of the feed. It would pass the relevant data down to the Presentational Components.
Presentational Component (FriendFeed):
This component would receive the friend posts data from its parent Container Component (FriendFeedContainer) as props and render them in a visually appealing way.
By structuring our components this way, we keep the concerns of fetching data and managing the state separate from the UI rendering logic. This separation allows for easier testing, reuse, and maintenance of our React application as it scales.
2.The HOC(Higher Order Component)Pattern
Higher-order components (HOCs) are a pattern in React that allows you to reuse component logic across multiple components. They are functions that take a component and return a new component with additional functionality.
To demonstrate the use of HOCs in a social media dashboard sample with React hooks, let's consider a scenario where you have multiple components that need to fetch user data from an API. Instead of duplicating the fetching logic in each component, you can create an HOC to handle the data fetching and pass the fetched data as props to the wrapped components.
Here's a basic example:
In this example:
withUserData is a higher-order component that handles the fetching of user data from an API. It wraps the passed component (WrappedComponent) and provides the fetched user data as a prop (userData) to it.
UserProfile is a functional component that receives the userData prop and displays the user profile information.
UserProfileWithUserData is the component returned by wrapping UserProfile with withUserData.
SocialMediaDashboard is the main component where you can render UserProfileWithUserData or any other component that needs user data.
Using this pattern, you can easily reuse the data fetching logic across multiple components in your social media dashboard application without duplicating code.
- Compound Components Pattern The Compound Components pattern in React is a design pattern that allows you to create components that work together to form a cohesive UI, while still maintaining a clear separation of concerns and providing flexibility to customize the components' behavior and appearance.
In this pattern, a parent component acts as a container for one or more child components, known as "compound components." These child components work together to achieve a particular functionality or behavior. The key characteristic of compound components is that they share state and functionality with each other through their parent component.
Here's a simple example of implementing the Compound Components pattern in React using hooks:
In this example:
Toggle is the parent component that holds the compound components (ToggleButton and ToggleStatus).
ToggleButton is a child component responsible for rendering the toggle button.
ToggleStatus is another child component responsible for displaying the status of the toggle.
The Toggle component manages the state (isOn) and provides a toggle function to control the state. It clones its children and passes the isOn state and toggle function as props to them.
By using the Compound Components pattern, you can create reusable and composable components that encapsulate complex UI logic while still allowing for customization and flexibility.
- Provider Pattern(Data management with Providers) The Provider Pattern in React is a design pattern used for managing and sharing application state or data across multiple components. It involves creating a provider component that encapsulates the state or data and provides it to its descendant components through React's context API.
Let's walk through an example to illustrate the Provider Pattern in React for managing user authentication data:
In this example:
We create a context called UserContext using React's createContext function. This context will be used to share user data and authentication-related functions across components.
We define a UserProvider component that serves as the provider for the UserContext. This component manages the user state using the useState hook and provides methods like login and logout to update the user state.
Inside the UserProvider, we wrap the children with UserContext.Provider and pass the user state and the login and logout functions as the provider's value.
Now, any component that needs access to user data or authentication-related functions can consume the UserContext using the useContext hook.
Let's create a component that consumes the user data from the context:
In this component:
We import UserContext and use the useContext hook to access the user data and the logout function provided by the UserProvider.
Depending on whether the user is logged in or not, we render different UI elements.
Finally, we wrap our application with the UserProvider to make the user data and authentication-related functions available to all components:
In this way, the Provider Pattern allows us to manage and share application state or data across multiple components without the need for prop drilling, making our code cleaner and more maintainable.
- State reducer pattern The State Reducer Pattern in React is a design pattern used to manage state in a more controlled and predictable manner. It involves using a reducer function to handle state transitions and actions, similar to how reducers work in Redux. This pattern can be particularly useful for managing complex state logic or state that needs to be shared across multiple components.
Let's walk through an example of implementing the State Reducer Pattern in React for managing a a social media dashboard application.In this example, we'll manage the state of the user's posts and notifications using a reducer function.
In this example:
We define action types (ADD_POST, DELETE_POST, ADD_NOTIFICATION, DELETE_NOTIFICATION) that represent different actions that can be performed on the social media dashboard state.
We define a reducer function (dashboardReducer) that takes the current state and an action and returns the new state based on the action.
We use the useReducer hook to create a stateful value (state) and a dispatch function to update the state by passing actions to the reducer.
The Dashboard component contains logic for adding and deleting posts and notifications. It dispatches actions to the reducer to update the state accordingly.
In the UI, posts, and notifications are rendered as list items with buttons to delete them.
Users can add new posts or notifications by clicking on the respective buttons.
This example demonstrates how to implement the State Reducer Pattern in React to manage the state of a social media dashboard, including posts and notifications. The reducer function centralizes state management logic, making it easier to understand and maintain.
6- Component Composition pattern
Component Composition pattern involves composing smaller, reusable components together to create more complex components or UIs. Let's illustrate this pattern with a social media dashboard example.
Suppose we have a social media dashboard that consists of several components such as UserInfo, Feed, Notifications, and Sidebar. We can compose these smaller components together to create the social media dashboard component.
In this example:
We have separate components for UserInfo, Feed, Notifications, and Sidebar, each responsible for rendering a specific part of the social media dashboard.
We compose these smaller components together in the SocialMediaDashboard component to create the entire social media dashboard UI.
The App component serves as the entry point where we pass sample data (user information, posts, notifications) to the SocialMediaDashboard component.
This demonstrates how we can use the Component Composition pattern to build a social media dashboard by composing smaller, reusable components together. Each component focuses on a specific aspect of the UI, promoting reusability and maintainability.
Top comments (0)