Baspa
Baspa

Reputation: 1168

React: Nothing was returned while the ternary always returns something

I have a component where I want to show a ul based upon an array of objects. These objects are Topics. I've created a Topics function which returns this ul. In my component, I call the function like this:

<Topics topics={topics} />

The Topics look like this:

0: {name: "Aanwezigen / afwezigen"}
1: {name: "Toevoegingen agenda"}
2: {name: "Update openstaande actiepunten"}
3:
    children: Array(3)
    0: {name: "Website"}
    1: {name: "Social media"}
    2: {name: "Nieuwsbrief"}
     length: 3
     __proto__: Array(0)
    name: "Marketing"
     __proto__: Object
4: {name: "Acquisitie", children: Array(3)}
5: {name: "Inkoop", children: Array(2)}
6: {name: "Jaarrekening 2018"}
7: {name: "Komende periode"}
8: {name: "Oplezen actiepunten"}
9: {name: "Rondvraag"}

This is my Topics function where I map through the topics and return an ul.

function Topics({ topics }) {
    return <ul>{topics.map(function (topic) { return <Topic topic={topic} /> })}</ul>;
}

This function calls the function Topic:

function Topic({ topic }) {

    return (topic.hasOwnProperty('children')) ?
        topic.children.forEach(child => {
            <ul><li key={child.name}>{child.name}</li></ul>;
        }) : <li key={topic.name}>{topic.name}</li>
}

In this function, I check if the object contains any children; and if it does, I loop through this array and create a new ul with the li elements in them. But, React gives me the below error:

Uncaught Invariant Violation: Topic(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.

But, if I look at the ternary operator, it should always return something right? So, I don't understand where this error is coming from. To give you an idea on how it should look like:

Example on how it should look like

Any help or ideas are appreciated. I just don't get why it says that it doesn't return anything while I think it does.

Upvotes: 0

Views: 76

Answers (2)

Md. Abu Sayed
Md. Abu Sayed

Reputation: 2486

I hope you fetch recursive problem, you can apply Recursive function code here: https://codesandbox.io/s/elastic-fire-nxbt0

Recursive for your list like as:

const getHtmlStructure = items => {
    let html = (
      <ul>
        {items.map(item => {
          return (
            <li>
              {item.name}
              {(item.children || []).length > 0
                ? getHtmlStructure(item.children)
                : ""}
            </li>
          );
        })}
      </ul>
    );
    return html;
  };

Full code

App/Parent component

function App() {
  let exampleData = [
    { id: 1, name: "name 1" },
    {
      id: 2,
      name: "name 2",
      children: [
        { id: 3, name: "name 2.1" },
        { id: 4, name: "name 2.2" },
        { id: 5, name: "name 2.3" }
      ]
    },
    {
      id: 6,
      name: "name 3",
      children: [
        { id: 7, name: "name 3.1" },
        { id: 8, name: "name 3.2" },
        { id: 9, name: "name 3.3" }
      ]
    },
    { id: 10, name: "name 4" },
    { id: 11, name: "name 5" }
  ];

  return (
    <div className="App">
      <h1>Item List</h1>
      <Items data={exampleData} />
    </div>
  );
}

Item component or list component

import React from "react";

export default function Items(props) {
  const getHtmlStructure = items => {
    let html = (
      <ul>
        {items.map(item => {
          return (
            <li>
              {item.name}
              {(item.children || []).length > 0
                ? getHtmlStructure(item.children)
                : ""}
            </li>
          );
        })}
      </ul>
    );
    return html;
  };

  const { data } = props;
  return (data || []).length > 0 ? getHtmlStructure(data) : "No items";
}

Thank you

Upvotes: 1

Jo&#227;o Cunha
Jo&#227;o Cunha

Reputation: 10307

Do not use forEach if you intend to loop through an array to render something.

The forEach method returns undefined.

The forEach() method executes a provided function once for each array element.

Use map instead.

The map() method creates a new array with the results of calling a provided function on every element in the calling array.

It should be:

<>
...
{yourArray.map(item => <YourComponent key={item.id} />)}
...
</>

Upvotes: 0

Related Questions