Create a Stateless Component for an Array of JSON Objects in React
In this guide, we will take a look at some considerations when binding a list of objects in a React.js component's interface.
Sep 25, 2020 • 5 Minute Read
Introduction
Binding an array to a set of DOM elements (JSX) in React.js is a common task in app development. Often, you need to list a set of objects and their corresponding attributes, such as those found in product catalogs, member records, or lists of transactions. In this guide, we will take a look at some considerations when binding a list of objects in a React.js component's interface.
Setup
Suppose that you are creating a React.js component that lists a set of products a customer can buy in a grocery store. Each product has an id, name, and price. Data might come from anywhere, such as an API or another component. In any case, you can expect that an array of items will look like the following:
{ id: 1
This type of data will be passed as a props attribute called items within your component.
First, create a component that looks like the following:
import React from 'react';
export default class ItemsList extends React.Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
return (
<table>
<thead>
<th>
Item
</th>
<th>
Price
</th>
</thead>
<tbody>
</tbody>
</table>
);
}
}
Notice that you don't have any state to maintain and that this component returns a single element in the form of a <table>. Everything will be read from props instead of state. Within the <table>, React.js requires that you include a <tbody> before inserting rows in it. Otherwise, it will complain that <tr> is not a valid child element of <table>.
Populating the Table
Instead of rendering the array of items directly to render(), create a separate function to handle the building of DOM elements:
renderRows() {
return this.props.items.map(function(o) {
return <tr key={"item-" + o.id}>
<td>{o.name}</td>
<td>{o.price}</td>
</tr>
});
}
Notice first that the code references this.props and assumes that it will have an attribute items. Since it's calling from this.props, it expects that this data will be passed from an external component. Second, the code uses the map function of a JavaScript array to iterate through this.props.items, which accepts a function that returns a <tr> element. Finally, the <tr> element will contain a key attribute. This is a requirement for React.js wherein each child element of a parent element that is dynamically generated has to be assigned a key unique within the parent element. Since it is assumed that each item will contain an id unique to it, the code uses that information to generate the key value of item-someItemId.
Invoke the function within the component's render() inside the <tbody> tag:
<tbody>
{this.renderRows()}
</tbody>
These items will change if a component calling ItemsList passes a new set of values for items via props.
Overall Code
import React from 'react';
export default class ItemsList extends React.Component {
constructor(props) {
super(props);
this.state = {}
}
renderRows() {
return this.props.items.map(function(o) {
return <tr key={"item-" + o.id}>
<td>{o.name}</td>
<td>{o.price}</td>
</tr>
});
}
render() {
return (
<table>
<thead>
<th>
Item
</th>
<th>
Price
</th>
</thead>
<tbody>
{this.renderRows()}
</tbody>
</table>
);
}
}
Loading Values
Suppose that you want to test it out. From an external JavaScript section in your app, invoke ItemsList with some data in a DOM element react-root-div:
var items = [
{ id: 1, name: "Apple", price: 25.00 },
{ id: 2, name: "Oranges", price: 20.00 },
{ id: 3, name: "Grapes", price: 22.00 }
];
ReactDOM.render(
<ItemsList items={items} />,
document.getElementById("react-root-div")
);
You should see the table render with the name of the item in the first column and its price in the second column. To add more rows to the table, add more objects to items, making sure that each object has an id different from the existing objects in the array.
Conclusion
In this guide, you've created a component that has no state but populates a list of JavaScript objects often derived from a JSON object. The component renders these items dynamically, and each child element rendered should have a unique key within its parent element. Because it is a stateless component, you can easily plug this component in other parts of your React.js app that need a list rendered of items.
For an extra challenge, see if you can integrate this in your own React.js app where data is coming from an external API instead of being hardcoded.