Type 'Item' is not assignable to type 'ReactNode'

Viewed 29

I am trying to understand what this error means. I have defined a Type for an array of items and each item is a string.

When I wrap the listItem with an empty fragment the error is gone. Am I missing something? Because each item is a string only inside an array of items.

export type Item = {
  listItem: string;
};

 

import { motion } from 'framer-motion';

import { Item } from '@typings/propTypes';

import { container, item } from '@lib/framer';

const UnorderedList = ({
  listItems,
  htmlClass
}: {
  htmlClass: string;
  listItems: Item[];
}) => (
  <motion.ul
    variants={container}
    initial="hidden"
    animate="show"
    className={`flex flex-col flex-wrap my-6 leading-relaxed ${
      htmlClass ? htmlClass : 'text-white'
    }`}
  >
    {listItems.map((listItem, index) => (
      <motion.li key={index} variants={item} className="flex gap-3">
        {listItem}
      </motion.li>
    ))}
  </motion.ul>
);

export default UnorderedList;
1 Answers

listItem is of type Item, which is an object with a property called listItem which is a string. Objects are not valid React child elements, so {listItem} is invalid. The error is TypeScript's way of telling you that at authoring/compilation time before React tells you that at runtime. Perhaps you meant {listItem.listItem}, which would be valid because strings are valid React children.

Here's a simpler reproduction of the problem:

import React from "react";

export type Item = {
    listItem: string;
};

// Doesn't work
const Example1 = ({item}: {item: Item}) => {
    return <div>{item}></div>;
};

// Works
const Example2 = ({item}: {item: Item}) => {
    return <div>{item.listItem}</div>;
};

Playground link

When I wrap the listItem with an empty fragment the error is gone.

Sadly, that's true, but all it does is hide the problem from TypeScript. The problem actually remains, and React will complain:

// Stack Snippets don't support shorthand fragment syntax,
// so we have to use the verbose form here
const Example1 = ({item}: {item: Item}) => {
    return <div><React.Fragment>{item}</React.Fragment></div>;
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example1 item={{listItem: "Hi"}} />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

That results in the usual "Objects are not valid as a React child" runtime error.

Error: Objects are not valid as a React child (found: object with keys {listItem}).

Related