Introduction
Most React developers might have seen this error before. Although the error doesn't make it very clear what mistake was made, it states a clear rule:
you can't use JavaScript Objects as a child in React.
The error "Objects are not valid as a React child" is rather common and the solution is to manipulate the object so that it becomes a valid element. Consider the following code:
const MyComponent = () => {
const myVariable = 'a';
return <div>{myVariable}</div>;
};
tsx
In the above example, we store a string in a variable called myVariable and use it directly as a child for the div
tag. The above code works because the stored value "a" is a primitive type. It would also function properly if it was any other primitive type such as a number or undefined, for example.
The problem starts when myVariable assumes an object. React has no way to tell what to render when provided with an object, thus the Invariant Violation error pops up when attempting so. Let's consider the possible solutions for the following scenario:
const MyComponent = () => {
const myVariable = {
productName: 'Watermelon',
price: 12,
};
return <div>{myVariable}</div>;
};
tsx
Multiple outputs could be expected from the above code. One could argue that it should render the value of each property separated by a comma. Another could expect it to actually print the whole object structure, the property names, and its values. Even though these cases could be decided upon and addressed by the React render, things get trickier when a property holds a function, or even another object. Because of the numerous possibilities that exist with non-primitive types (JavaScript objects are the only non-primitive) React's render assumes nothing and throws the "Objects are not valid as a react child" error. And this is excellent because it nows remains in the developer's hand to decide how to present the data in the object in its application. From the above example, one possible (real) solution would be:
const MyComponent = () => {
const myVariable = {
productName: 'Watermelon',
price: 12,
};
return (
<div>
{myVariable.productName} : ${myVariable.price}
</div>
);
};
tsx
And the above code would render a div with the content: Watermelon: $12
Besides primitive types, other valid react children include React components and HTML tags. In essence, something that React can use to render UI.
Displaying a List of Items
Rendering a collection of items is a common pattern in react applications. Lists, tables, cards, buttons, and other types of components are very often applied through the usage of the .map() array method. Let's check an example. A JavaScript object represents the data from a given table row, it contains the properties name and age. More objects sharing the same structure exist and they are stored inside an array. The array, which is a special JavaScript variable, holds, belong to other class methods, a very useful one called map.
The execution of the map method iterates through each item in this array, which are different JavaScript objects containing the name and age data, and allows us to modify what's stored in the array for each of these objects.
This delivers a powerful tool that allows transforming a collection of data into react components. By applying the map method in the array and returning JSX for each element, which is React's own syntax that looks like a combination of HTML and JavaScript.
const MyComponent = () => {
const users = [
{ name: 'User 1', age: 21 },
{ name: 'User 2', age: 38 },
{ name: 'User 3', age: 45 },
];
return (
<div>
{users.map((user) => (
<p>
[{user.age}] {user.name}
</p>
))}
</div>
);
};
tsx
The "Objects are not valid as a React child" error happens when trying to render a collection of data by mistakenly returning the object when applying the map method instead of using the data from the object to create and return JSX.
The code example below shows how the above example could have been written wrong and resulting in the error.
const MyComponent = () => {
const users = [
{ name: 'User 1', age: 21 },
{ name: 'User 2', age: 38 },
{ name: 'User 3', age: 45 },
];
return (
<div>
{users.map((user) => (
<p>
[{user}] {user.name}
</p>
))}
</div>
);
};
tsx
Notice the usage of user instead of user.age. Since it refers to the whole object in question, it causes the code to break. The error could also happen by forgetting to apply the map method at all. This would result in an array of objects being passed to the return of the react components, and since objects are not primitive types, they can't be rendered.
What would actually work this way is to use an array of primitive types, such as an array of string:
export default function App() {
const teste = ['A', 'B', 'C'];
return <div className='App'>{teste}</div>;
}
tsx
Since react knows what to render when provided with primitive types, it can easily render a collection of primitive types. But it is unlikely to be seen applied like this because it doesn't allow for manipulating how it will be displayed. You can see from the example that it simply concatenates each string from the array, resulting in the text "Abc".
Also, another thing to bear in mind is that it results in the following HTML:
<div class="App">Abc</div>
html
A real case would prefer employing a proper tag to handle text, such as <p>
for a paragraph of one of the h tags for headings
Wrap Up
This is a common error and sometimes it's hard to simply take a look at the code and notice it. Here some of the most the common reasons the error "Objects are not valid as a react child" occur:
No .map() method was called to render a collection of items from an array. An object is being returned instead of accessing one of its properties. An object is unintentionally created when attempting to return a primitive The motives for this error to be thrown are the diverse possible scenarios for rendering an object, and, allowing the developer to address how he will present the available data is a worthy feature and not a problem at all. In other words, this is React's way of telling that you should be the one responsible for deciding what to render from the object because React's renderer would very unlikely do a proper job if attempting so.
Inside the error, a clear rule states that JavaScript objects don't fit alongside the components, meaning that you should use the data from the object in order to decide how to create the component to display.
If you ever run into this problem, take a good look at the error message on the console. It will state inside what component and which line of code the error happened to be thrown. Holding this information and the knowledge that such an object wasn't really supposed to be there, it becomes easy to solve this mistake.