Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React HOC class returns nothing

I am facing a problem I can't figure out. For a project we use React to generate a layout from JSON input using the following code (simplified):

function generateComponents(children, params) {
  let comps = [];
  if (!children || children && children.length === 0) {
    return [];
  }

  forEach(children, (comp) => {
      let compName = comp.component;
      let createdComp;
      switch (compName) {
        case 'test1':
          createdComp = TestOne(Object.assign({}, comp, params));
          break;
        case 'test2':
          createdComp = TestTwo(Object.assign({}, comp, params));
          break;
      }
      comps.push(createdComp)
    }
  }
  return comps.length === 1 ? comps[0] : comps;
}

This works well and the layout is generated correctly. We wanted to take this a step further and wrap the createdComp in a Higher Order Component. We implemented that in the following way:

function generateComponents(children, params) {
  // see above for implementation

  let component;

  if (condition)
    component = testingHOC(createdComp);
  else
    component = createdComp

  comps.push(component);
}

// TestingHOC.js
export function testingHoc(WrappedComponent) {
  console.log('wrapped')
  return class TestingHoc extends Component {
    render() {
      console.log('props TestingHOC', this.props);
      return ( <WrappedComponent { ...this.props} />);
    }
  }
};

This broke our component generation. The code returns nothing. The only thing that gets logged is the console.log('wrapped'), the render function of the class is never called. What are we missing here?

EDIT: Render method of the render class:

render() {
    const children = this.state.children;
    const {params} = this.props;
    const arrChildren = isArray(children) ? children : [children];
    let comps = generateComponents(arrChildren, params || {});
    if (isArray(comps)) {
        return (
            <ViewComponent>
                {comps}
            </ViewComponent>
        );
    } else {
        return comps;
    }
}

EDIT 2:

Console.log of {comps} with the testingHoc Console.log of <code>{comps}</code> with the testingHoc Console.log of {comps} without the testingHoc Desired state of children

Edit 3

Added the code for ViewComponent:

import React from 'react';

const ViewComponent = (props) => (
    <div {...props}/>
);

export default ViewComponent;
like image 532
Mathijs Rutgers Avatar asked Nov 03 '17 10:11

Mathijs Rutgers


2 Answers

The issue you are facing is because of the inherent difference between a React element and a React component.

When you are not using the HOC, you are creating a React element which can be seen by the first console.log image. This is the output after reconciliation has occurred.

When you use the HOC, your HOC returns a component which shows up as the test(props) function in your second console.log image.

To have the same functionality with your HOC enhanced components, you need to change the code in generateComponents functions to

  if (condition){
     let Comp = testingHOC(createdComp);
     component = <Comp/>;
  }
like image 102
palsrealm Avatar answered Nov 09 '22 03:11

palsrealm


Try

    ...
    return (
        <ViewComponent>
            {comps.map((Comp) => <Comp />)}
        </ViewComponent>
    );
    ...

or

    ...
    return (
        <ViewComponent>
            {comps.map((comp) => comp())}
        </ViewComponent>
    );
    ...
like image 31
IzumiSy Avatar answered Nov 09 '22 02:11

IzumiSy