React patterns

Key takeaways

  • Container/presentational components: Separate your components into container components and presentational components. Container components handle the application's state and logic, while presentational components focus on how things look. This improves code organization, reusability, and maintainability.

  • Render props: Pass a function as a prop to a component to control what gets rendered. This allows components to share code, logic, or state with other components.

  • Consumer pattern: Use the Context API to separate data producers (providers) and consumers. Consumers can access data provided by a context without explicitly passing it through props. This improves maintainability and reduces prop drilling.

React patterns refer to recurring solutions or best practices that developers adopt when designing and structuring React components. These patterns help improve code organization, maintainability, and reusability. Here are some common React patterns:

Container/presentational components

Container components manage the state and logic of an application. They are responsible for data fetching, handling user input, and any other business logic. Presentational components are concerned with how things look. They receive data and callbacks as props from container components and focus on rendering the UI. Separating components into container and presentational components is a common practice in React to improve code organization, reusability, and maintainability. This separation follows the principle of having one component responsible for managing state and logic (container) while another focuses solely on presenting UI (presentational).

Let's take a look at the following example:

// Container component
class Container extends React.Component {
state = {
data: [],
};
render() {
return <PresentationalComponent data={this.state.data} />;
}
}
// Presentational component
const PresentationalComponent = ({ data }) => {
return <div>{/* render data */}</div>;
};

In the above code:

  • Lines 2–5: We created a class-based React component that contains a state with an empty array named data.

  • Lines 7–10: We used render() method, to render the PresentationalComponent, passing the data from its state as a prop named data.

  • Lines 13–15: We designed a component to render UI elements based on the data it receives as a prop. Typically, this component would include logic to render elements based on the content of the data array.

Consumer pattern

The consumer pattern is a design pattern used in software development, particularly in the context of React or other component-based architectures. It involves the separation of concerns by defining components that produce data (producers) and components that consume that data (consumers).

In React, the Context API allows the implementation of Consumer patterns effectively. The Consumer component is part of the Context API and is used to consume data from a provided context.

Let's take a look at the following example:

const MyContext = React.createContext();
const MyProvider = ({ children }) => {
const value = 'Hello, Context!';
return (
<MyContext.Provider value={value}>
{children}
</MyContext.Provider>
);
};
const MyComponent = () => (
<MyProvider>
<MyContext.Consumer>
{(value) => <div>{value}</div>}
</MyContext.Consumer>
</MyProvider>
);

In the above code:

  • Line 1: We created a React.createContext() named MyContext. This creates a new Context object, allowing components to access the provided value.

  • Lines 3–10: In the MyProvider component, we use MyContext.Provider to provide a value ('Hello, Context!') to any component that consumes MyContext. It wraps the children prop with the Provider, allowing them to access the provided value.

  • Lines 12–18: The MyComponent function consumes the value provided by MyProvider using the MyContext.Consumer.

Layout component 

A layout component is a reusable component in React that defines the structure and arrangement of elements on a web page. It typically includes common elements such as headers, footers, navigation menus, and sidebars, providing a consistent layout across multiple pages within an application. The layout component helps streamline the development process by centralizing the layout logic, making it easier to maintain and update the visual appearance of the application.

Let's take a look at the following example:

import React from 'react';
import Header from './Header';
import Footer from './Footer';
const Layout = ({ children }) => {
return (
<div className="container">
<Header />
<main className="content">
{children}
</main>
<Footer />
</div>
);
};
export default Layout;

In the above code:

  • Lines 2–3: We import the Header and Footer component.

  • Lines 5–15: We define a functional component called Layout. It accepts a prop called children, which represents the content that will be nested within the layout component.

  • Line 17: We export the Layout component as the default export from this file, allowing it to be imported and used in other application parts.

Higher-order component

A higher-order component (HOC) is a pattern used in React to enhance or modify the behavior of existing components. Essentially, a higher-order component is a function that takes a component as an argument and returns a new component with added functionality. This allows for code reusability and abstraction of common logic across multiple components.

Let's take a look at the following example:

import React from 'react';
// Define a higher-order component that adds a "prefix" prop to the wrapped component
const withPrefix = (WrappedComponent) => {
return class extends React.Component {
render() {
// Pass all props to the wrapped component along with an additional "prefix" prop
return <WrappedComponent {...this.props} prefix="Hello" />;
}
};
};
// Define a simple functional component
const MyComponent = ({ prefix }) => (
<div>
<p>{prefix}, World!</p>
</div>
);
// Wrap the MyComponent with the withPrefix higher-order component
const PrefixedComponent = withPrefix(MyComponent);
// Usage of the PrefixedComponent
const App = () => (
<div>
<PrefixedComponent />
</div>
);
export default App;

In the above code:

  • Lines 4–11: We define higher-order component withPrefix that takes a WrappedComponent as input and returns a new component. The returned component adds a prefix prop with a value of Hello to the wrapped component.

  • Lines 14–18: We define a simple functional component MyComponent that receives the prefix prop and displays a greeting.

  • Lines 21–28: We define PrefixedComponent by wrapping MyComponent with the withPrefix higher-order component.

Render props

Render props is a design pattern in React. This pattern involves passing a function as a prop to a component, which allows the component to control what gets rendered. This approach allows components to share code, logic, or state with other components.

Let's take a look at the following example:

import React from 'react';
// Component using Render Props technique
class RenderPropComponent extends React.Component {
render() {
// Invoking the function received as a prop to render content
return (
<div>
<h2>Render Prop Component</h2>
{this.props.renderContent()}
</div>
);
}
}
// Usage of the RenderPropComponent
const App = () => {
return (
<div>
<RenderPropComponent
renderContent={() => (
<p>This content is rendered using a Render Prop technique!</p>
)}
/>
</div>
);
};
export default App;

In the above code:

  • Lines 4–14: We create a component named RenderPropComponent that receives a prop called renderContent, which is a function. Inside the RenderPropComponent's render method, it invokes this.props.renderContent() rendering the content returned by the function.

  • Lines 17–27: We use RenderPropComponent to pass an anonymous function as the renderContent prop. This function defines the content to be rendered within the RenderPropComponent.

Code example

Let's see the code example of render props design pattern:

{
  "name": "reactproject",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}
Render props

Code explanation

  • Greeting component: This is a functional component that receives props as an argument. It uses the name prop to display a greeting message.

  • App component: This is the parent component that renders the Greeting component twice, passing different name props ("Alice" and "Bob").

Conclusion

React patterns are helpful guides for creating React components. They help us write code that's easier to understand, use, and reuse in different parts of our React apps. Each pattern helps us keep track of information, share data between components, make our code neat, and put components together in smart ways. Overall, they make it easier for us to build and maintain our React apps.

Frequently asked questions

Haven’t found what you were looking for? Contact Us


Is React a MVC or MVVM?

React is often categorized as a MVVM (Model-View-ViewModel) framework. This is because it closely aligns with the MVVM pattern’s principles of separating concerns between data (Model), presentation (View), and logic (ViewModel).

While React doesn’t explicitly enforce a strict MVVM architecture, its component-based approach and the use of state and props can be seen as implementing MVVM concepts.


Is React an MVC pattern?

While React doesn’t directly follow the Model-View-Controller (MVC) pattern, it shares some similarities. The component hierarchy in React can be viewed as a loose representation of the MVC pattern, where:

Model: The data is managed within components (state, props). View: These are the rendered UI elements. Controller: It is the component logic that handles updates to the model and re-renders the view. However, React’s component-based rendering and data flow approach differs from the traditional MVC pattern.


What are the common architectural patterns in React?

React offers several common architectural patterns to help structure and organize your code:

  • Container/presentational components
  • Render props
  • Higher-order components (HOCs)
  • Context API
  • Hooks

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved