score:3

Accepted answer

This is an anti-pattern, as @hamms has pointed out. There are better ways to implement themes in React using plain old CSS.

Said that, here's a hack to a working example of your use case - https://codesandbox.io/s/ymqwyww22z.

Basically, here's what I have done:

  1. Make List a class based component. It's not too much trouble to wrap a functional component into one.

    import React, { Component } from "react";
    
    export default class List extends Component {
      render() {
        return (
          <ul>
            <li>1</li>
            <li>2</li>
          </ul>
        );
      }
    }
    
  2. Implement render in the dynamic class Red<Component> to first fetch the element-tree returned from the base Component's render and then edit it.

    import React from "react";
    
    export default function makeRed(Component) {
      return class RedComponent extends Component {
        constructor(props) {
          super(props);
    
          RedComponent.displayName = `Red${Component.name}`;
        }
    
        render() {
          let componentElement = super.render();
          let { children, ...rest } = componentElement.props;
          children = React.Children.map(children, child => {
            return React.cloneElement(child, {
              ...child.props,
              style: {
                backgroundColor: "red"
              }
            });
          });
          return React.cloneElement(componentElement, rest, ...children);
        }
      };
    }
    

How's this different from the createElement version of makeRed?

As makeRed returns a HOC, when you use it in your App component, you don't assign props to it. Something like this...

function App() {
  return <RedList />; // no props!
}

So inside the dynamic component function, where you use createElement to create a new instance, component.props don't carry any children. Since List creates its own children, you need to grab those and modify them, instead of reading children from props.


Related Query

More Query from same tag