DEV Community

Cover image for Stop Using Conditional Rendering: Leveraging the Factory Pattern for Dynamic Component Creation
moayad khader
moayad khader

Posted on

Stop Using Conditional Rendering: Leveraging the Factory Pattern for Dynamic Component Creation

Introduction:

In the realm of front-end development, conditional rendering has long been a common practice for dynamically rendering components based on certain conditions. While it can serve its purpose in simple scenarios, as applications grow in complexity, maintaining clean and scalable code becomes a challenge. In this article, we explore an alternative approach to conditional rendering by leveraging the factory pattern for dynamic component creation. We'll delve into the benefits of this pattern and demonstrate how it can improve code organization and extensibility.

The Problem with Conditional Rendering:

Conditional rendering involves writing logic within React components to determine which component should be rendered based on certain conditions. While this approach may work well for a few scenarios, it can quickly become convoluted and difficult to maintain as the number of conditions and components increases. Additionally, the logic for conditional rendering can clutter the component code, making it harder to read and understand.

Introducing the Factory Pattern:

The factory pattern is a creational design pattern that allows for the creation of objects without specifying their concrete types. Instead of including conditional rendering within the components, we can delegate the responsibility of component creation to a factory class. This promotes separation of concerns and provides a clean and extensible solution.

Implementing the Factory Pattern for View Components:

To illustrate the benefits of the factory pattern, let's consider a scenario where we need to dynamically create different view components based on a view type. Instead of using conditional rendering within our React components, we can employ the factory pattern to handle the component creation.

We define a View class as the base class, containing a view property of type IViewComponent. This property represents the view component that will be created by the factory. Subclasses of View, such as Home, Settings, Profile, and Organization, extend the base class and set the view property to the respective view components (HomeView, SettingsView, ProfileView, and OrganizationView).

Next, we create a ViewFactory class that includes a createView static method. This method takes a view type as a parameter and returns an instance of the appropriate view subclass based on the provided type. By encapsulating the component creation logic within the factory class, we eliminate the need for conditional rendering within the React components.

Example Implementation:

Let's see an example implementation of the factory pattern for view components:

import HomeView from "views/home";
import SettingsView from "views/settings";
import ProfileView from "views/settings/subViews/profile";
import OrganizationView from "views/settings/subViews/organization";
import { IViewComponent } from "lib/types/view.types";

class View {
    view: IViewComponent;

    constructor() {}

    getView(): IViewComponent {
        return this.view;
    }
}

class Home extends View {
    constructor() {
        super();
        this.view = HomeView;
    }
}

class Settings extends View {
    constructor() {
        super();
        this.view = SettingsView;
    }
}

class Profile extends View {
    constructor() {
        super();
        this.view = ProfileView;
    }
}

class Organization extends View {
    constructor() {
        super();
        this.view = OrganizationView;
    }
}

class ViewFactory {
    static createView(view: string): View {
        switch (view) {
            case "home":
                return new Home();
            case "settings":
                return new Settings();
            case "profile":
                return new Profile();
            case "organization":
                return new Organization();
        }
    }
}

export default ViewFactory;
Enter fullscreen mode Exit fullscreen mode

In the example above, we define different view components (Home, Settings, Profile, and Organization) by extending the View base class. Each subclass sets the view property to the corresponding view component.

The ViewFactory class includes a static method createView that takes a view type as a parameter. Based on the provided type, it creates an instance of the appropriate view subclass using the factory pattern.

Usage in React Components:

To use the factory pattern for dynamic component creation in React, we can leverage the useMemo hook. Let's assume we have a view variable that determines the type of the view we want to render. We can use the ViewFactory to create the appropriate view component using the following code:

const ViewComponent = useMemo(() => ViewFactory.createView(view).getView(), [view]);

return <div>{ViewComponent}</div>;
Enter fullscreen mode Exit fullscreen mode

In the code above, we use the useMemo hook to memoize the result of ViewFactory.createView(view).getView(). This ensures that the view component is only created when the view variable changes. We then render the ViewComponent within a parent component, such as a <div> element.

Benefits of the Factory Pattern:

  1. Separation of concerns: The factory pattern separates the responsibility of component creation from the React components themselves, promoting cleaner and more maintainable code.
  2. Scalability: Adding new view types becomes as simple as creating a new subclass of View and updating the createView method in the factory class. This modular approach avoids cluttering the React components with conditional logic for each new type.
  3. Code reusability: The factory pattern allows for the reuse of common creation logic across different components, enhancing code efficiency and reducing duplication.

Conclusion:

Conditional rendering has long been a go-to technique for dynamically rendering components based on specific conditions. However, as applications grow in complexity, maintaining clean and scalable code becomes increasingly challenging. By adopting the factory pattern for dynamic component creation, we can separate concerns, improve code organization, and enhance extensibility. The factory pattern provides a structured and scalable solution that eliminates the need for conditional rendering within React components. Let's embrace this pattern and write cleaner, more maintainable code in our front-end projects.

Top comments (0)