javascriptreactjshigher-order-components

Is it possible to render a component passed in as a Prop to a Higher Order Component?


I am working on increasing my knowledge of Higher Order Components. I am wondering if it is possible to render a "component," which is passed in as a prop to a higher order component "SuperCommentList." To my knowledge there is no way to render a component as "this.props.component" or even as an instance variable "this.WrappedComponent." I know this does not follow traditional HOC conventions, but was trying to determine if this was possible. I am receiving the errors below. Can anyone advise how I can achieve this?

Warning:

Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: . Did you accidentally export a JSX literal instead of a component? at App

Error:

react-dom.development.js:28439 Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

Check the render method of App. at createFiberFromTypeAndProps (react-dom.development.js:28439:1) at createFiberFromElement (react-dom.development.js:28465:1) at reconcileSingleElement (react-dom.development.js:15750:1) at reconcileChildFibers (react-dom.development.js:15808:1) at reconcileChildren (react-dom.development.js:19167:1) at updateContextProvider (react-dom.development.js:21154:1) at beginWork (react-dom.development.js:21649:1) at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1) at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1) at invokeGuardedCallback (react-dom.development.js:4277:1)

HOC Call

import CommentList from "./CommentList";
import data from "../utils/data";
import modelClass from "../utils/Model";
import SuperCommentList  from "../utils/SuperCommentList";

const CommentListWithSubscription = withSubscription(CommentList, model.data);

function withSubscription(WrappedComponent, selectedData) {
  const color = { color: selectedData.color };
  return <SuperCommentList selectedData={selectedData} component={WrappedComponent} color={color}/>;
}

HOC Example below:

import React, {Component} from "react";

class SuperCommentList extends Component {

   WrappedComponent;
    constructor(props) {
      super(props);
      console.log("WithSubscription props:", props);
      this.handleChange = this.handleChange.bind(this);

      this.WrappedComponent = this.props.component;
      this.state = {
        data: this.props.selectedData,
      };
    }

    componentDidMount() {
      // ... that takes care of the subscription...
      this.handleChange();
    }

    handleChange() {
      this.setState({
        data: this.props.selectedData,
      });
    }

    render() {
      console.log("WithSubscription State Data:", this.state.data);
      return <this.WrappedComponent data={this.state.data} {...this.props.color}/>;
    }
  }

  export default SuperCommentList;

Solution

  • the HOC need to return a component, not a rendered DOM node.

    So change the HOC to

    function withSubscription(WrappedComponent, selectedData) {
      const color = { color: selectedData.color };
    
      return function ComponentWithSubscription() {
         return <SuperCommentList selectedData={selectedData} component={WrappedComponent} color={color} />;
      }
    }