Home > Enterprise >  Component should be returning a JSX.Element, but says it is not returning a value at all
Component should be returning a JSX.Element, but says it is not returning a value at all

Time:01-14

The component in question is this:

const NavigationItems = (props: {name: string, href: string}[]): JSX.Element => {
  props.map((item, index) => {
    return <a href={item.href} key={index}>{item.name}</a>
  })
};

export default NavigationItems;

Which is generating this error:

ERROR in src/components/navigation/NavigationItems.tsx:1:66
TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
  > 1 | const NavigationItems = (props: {name: string, href: string}[]): JSX.Element => {
      |                                                                  ^^^^^^^^^^^
    2 |   props.map((item, index) => {
    3 |     return <a href={item.href} key={index}>{item.name}</a>
    4 |   })

I've tried to do:

return props.map((item, index) => {
  <a href={item.href} key={index}>{item.name}</a>
})

Which then results in:

ERROR in src/components/navigation/NavigationItems.tsx:2:3
TS2739: Type 'void[]' is missing the following properties from type 'ReactElement<any, any>': type, props, key

Also tried:

return props.map((item, index) => {
  return <a href={item.href} key={index}>{item.name}</a>
})

Which results in:

ERROR in src/components/navigation/NavigationItems.tsx:2:3
TS2739: Type 'Element[]' is missing the following properties from type 'ReactElement<any, any>

So I'm not quite sure what is going on here.

Any suggestions?


The dataset:

{
  "navbar": {
    "navBrand": "My Name",
    "navItems": [
      {
        "name": "Bio",
        "href": "#bio"
      },
      {
        "name": "Projects",
        "href": "#projects"
      },
      {
        "name": "Articles",
        "href": "#articles"
      },
      {
        "name": "Resume",
        "href": "#resume"
      },
      {
        "name": "Contact",
        "href": "#contact"
      }
    ]
  }
}

The parent component:

// Bootstrap imports
import { Container, Navbar } from 'react-bootstrap';

// Component imports
import NavigationItems from './NavigationItems';

// Import data
import data from '../../data/data.json';

const Navigation = () => {
  return (
    <Navbar>
      <Container>
        <Navbar.Brand>{data.navbar.navBrand}</Navbar.Brand>
        <NavigationItems {...data.navbar.navItems} />
      </Container>
    </Navbar>
  );
};

export default Navigation;

CodePudding user response:

Your first example isn't returning anything. When you enclose the body of an arrow function in curly braces e.g. const myFunc = () => { ...body } you have to explicitly put a return inside. What you want is to omit the curly braces.

However, that will still not work, because you'll be returning an array rather than an element. You can use a React fragment, such as:

const NavigationItems = (props: {name: string, href: string}[]): JSX.Element => (
  <>
  props.map((item, index) => {
    return <a href={item.href} key={index}>{item.name}</a>
  })
  </>
);

I typed this on my phone so I hope that syntax is correct. But the <> indicates a fragment. You can read more here: https://reactjs.org/docs/fragments.html

Note that <>...</> is shorthand for <React.Fragment>...</React.Fragment>

CodePudding user response:

I think you should return the map result.

const NavigationItems = (props: {name: string, href: string}[]): JSX.Element => {
    // add return here
    return props.map((item, index) => {
        return <a href={item.href} key={index}>{item.name}</a>
    })
};

export default NavigationItems;

or to simplify (maybe), you can write it like this

const NavigationItems = (props: {name: string, href: string}[]): JSX.Element => 
    props.map((item, index) => <a href={item.href} key={index}>{item.name}</a>)
  •  Tags:  
  • Related