Higher order component.
Tags: react, javascript, typescript, webdev
Published: 2023-11-25 19:11:01

- React Higher-Order Components (HOCs) are functions that accept a component as an argument and return an enhanced version of that component.


- HOCs provide a way to reuse component logic, add additional functionality, or modify the behaviour of components without altering their original implementation.


- HOCs follow the concept of "composition" in React, allowing components to be composed with multiple HOCs to achieve the desired functionality.


- HOCs promote code reusability, modularity, and separation of concerns by encapsulating common functionality in a separate component.

---

**Benefits of using HOCs**

1. Code Reusability: HOCs enable the reuse of component logic across different parts of the application. Logic that is common to multiple components can be encapsulated within an HOC and applied to those components when needed.

2. Separation of Concerns: HOCs help separate different concerns of a component. The HOC can handle specific functionality (such as authentication or resize observation) while the wrapped component focuses solely on its own rendering and UI logic.

3. Enhancing Existing Components: HOCs allow you to enhance existing components with additional functionality without modifying their original code. This helps maintain the integrity of the original component while adding new capabilities.

4. Composability: HOCs can be composed together to achieve complex functionality by applying multiple HOCs to a component. This enables a flexible and modular approach to building components.

**Component Example**

> - The Resizable component is a regular React component that needs to detect and respond to changes in its size.
> - The Resize Observer HOC is created as a separate component that encapsulates the functionality of observing size changes.
> - The Resize Observer HOC is applied to the Resizable component using the composition pattern, enhancing it with resize observation capabilities.
```
//ResizableComponent 

const ResizableComponent = ({ onResize }) => 
  const [size, setSize] = useState({ width: 0, height: 0 });


  useEffect(() => {
    const handleResize = () => {
      const { clientWidth: width, clientHeight: height } = containerRef.current;
      setSize({ width, height });
    };

    handleResize(); // Initial size calculation
    const resizeListener = () => {
      handleResize();
    };

    window.addEventListener("resize", resizeListener);

    return () => {
      window.removeEventListener("resize", resizeListener);
    };
  }, []); // Empty dependency array to run effect only once

  const containerRef = React.useRef();
  return (
    <div ref={containerRef}>
      <h2>Resizable Component</h2>
      <div
        style={{
          width: "100%",
          height: "200px",
          border: "1px solid black",
          padding: "20px",
        }}
      >
        <p>Resize this element:</p>
        <p>Width: {size.width}px</p>
        <p>Height: {size.height}px</p>
      </div>
    </div>
  );
};{
```

> - The Resize Observer HOC sets up a Resize Observer to monitor the size changes of a specific DOM element within the Resizable component.
> - Whenever a size change is detected, the Resize Observer HOC triggers a callback (passed as a prop) in the Resizable component, providing the updated dimensions.
> - The Resizable component can then utilize the received dimensions to update its UI, trigger other actions, or respond to the size changes in any desired way.

```
import { useEffect, useRef } from "react";

// Resize Observer HOC
const withResizeObserver = (WrappedComponent) => {
    const ResizeObserverHOC = ({ onResize, ...props }) => {
        const containerRef = useRef(null);
        const resizeObserverRef = useRef(null);

        useEffect(() => {
            if (typeof onResize !== "function") {
                console.warn(
                    "The 'onResize' prop is not a function. Resize events will be ignored."
                );
                return;
            }

            const observeResize = () => {
                resizeObserverRef.current = new ResizeObserver((entries) => {
                    handleResize(entries);
                });
                resizeObserverRef.current.observe(containerRef.current);
            };

            const handleResize = (entries) => {
                for (let entry of entries) {
                    const { width, height } = entry.contentRect;
                    onResize({ width, height });
                }
            };

            const cleanup = () => {
                if (resizeObserverRef.current) {
                    resizeObserverRef.current.disconnect();
                }
            };

            observeResize();

            return cleanup;
        }, [onResize]);

        return (
            <div ref={containerRef}>
                <WrappedComponent {...props} />
            </div>
        );
    };

    return ResizeObserverHOC;
};

```

By using the Resize Observer HOC, the Resizable component gains the ability to adapt and respond to changes in its size, making it more flexible and interactive.

Thanks for reading!!

If you have any further questions or need more information, feel free to connect!