0

I have an array of string that specifies the order in which my components are rendered.

const requiredOrder = [ "Line1Component", "Line3Component", "Line2Component" ];

I also have components with names that match the string in my above array.

I want to render the components based on the order mentioned in my requiredOrder array.

When I try to run the below code, I get:

Objects are not valid as a React child (found: object with keys {OrderredComponents}). If you meant to render a collection of children, use an array instead.

Minified: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

I tried to wrap the return statement in a wrapper, but still not able to figure out what's wrong.

I want to avoid case statements as mentioned here here as my requiredOrder list may grow very big.

class OrderMyComponents extends React.Component {
  render() {
    const requiredOrder = [
      "Line1Component",
      "Line2Component",
      "Line3Component"
    ];

    const Line1Component = () => (
      <div>
        <b>Line 1</b>
      </div>
    );
    const Line2Component = () => (
      <div>
        <b>Line 2</b>
      </div>
    );
    const Line3Component = () => (
      <div>
        <b>Line 3</b>
      </div>
    );

    const OrderredComponents = requiredOrder.map(function(item) {
      return { item };
    });

    return <OrderredComponents />;
  }
}

ReactDOM.render(
  <OrderMyComponents />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Shaunak Sontakke
  • 980
  • 1
  • 7
  • 17
  • https://stackoverflow.com/questions/47717326/how-to-render-a-component-by-string-name Here is a question similar to this one. – Thakur Karthik Sep 20 '19 at 18:25
  • That doesn't help as I would need to do that mapping of my key from requiredOrder and the corresponding component. Thats the challenge to do that dynamically. I cannot do that as I get the requiredOrder as an input for my component. – Shaunak Sontakke Sep 20 '19 at 18:55

2 Answers2

0

The usual use case is if you want to render the dynamic data i.e the list of strings. You can just use one component and render those. Example

class OrderMyComponents extends React.Component {
  render() {
    const requiredOrder = [
      "Line1Component",
      "Line2Component",
      "Line3Component"
    ];

    const ItemComponent = (item, index) => (
      <div key={index}>
        <b>{item}</b>
      </div>
    );
    

    return <div>{requiredOrder.map(ItemComponent)}</div>;
  }
}

ReactDOM.render(
  <OrderMyComponents />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.development.js"></script>
<div id="react"></div>

But if you want to lookup a different component for each item in your array, you can refer to this how to render a component by string name as suggested by https://stackoverflow.com/users/7364894/thakur-karthik

class OrderMyComponents extends React.Component {
  render() {
    const requiredOrder = [
      <div key={1}>
        <b>Line1Component</b>
      </div>,
      <div key={2}>
        <b>Line2Component</b>
      </div>,
      <div key={3}>
        <b>Line3Component</b>
      </div>
   ];

    

    return <div>{requiredOrder}</div>;
  }
}

ReactDOM.render(
  <OrderMyComponents />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.development.js"></script>
<div id="react"></div>
agenthunt
  • 8,450
  • 3
  • 30
  • 26
  • That doesn't help as I would need to do that mapping of my key from requiredOrder and the corresponding component. Thats the challenge to do that dynamically. I cannot do that as I get the requiredOrder as an input for my component. – Shaunak Sontakke Sep 20 '19 at 18:58
  • You could actually create an array of components as well instead specifying an order and looking up separately . It would help if could explain a bit more context of the problem you are trying to solve. – agenthunt Sep 20 '19 at 19:02
  • I am trying to create the same - array of components as you mentioned. Context is: I want to build an i18n address component for entering international addresses. This component receives a list of address fields in particular country. Different countries have different order of address fields. Fields are - addressline1,2,3postalcode, locality, country. Based on the list received, I have to order my component. My component receives a sequence as input. I have render the components in that order. – Shaunak Sontakke Sep 20 '19 at 19:38
0

I created an object with a component name as a key as per https://medium.com/@Carmichaelize/dynamic-tag-names-in-react-and-jsx-17e366a684e9

and that solved my problem.

Thanks agent_hunt and thakur-karthik for your help.

const components = {
  Line1Component: () => (
    <div>
      <b>Line 2</b>
    </div>
  ),
  Line2Component: () => (
    <div>
      <b>Line 2</b>
    </div>
  ),
  Line3Component: () => (
    <div>
      <b>Line 3</b>
    </div>
  )
};

class OrderMyComponents extends React.Component {
  render() {
    const requiredOrder = [
      "Line1Component",
      "Line2Component",
      "Line3Component"
    ];

    return requiredOrder.map((item, key) => {
      const Component = components[item];

      return <Component />;
    });
  }
}

ReactDOM.render(
  <OrderMyComponents />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Shaunak Sontakke
  • 980
  • 1
  • 7
  • 17