- Inside App.js we have two arrays. One with a list of people data and one with a list of products data:
const people = [{
name: 'John Doe',
age: 54,
hairColor: 'brown',
hobbies: ['swimming', 'bicycling', 'video games'],
}, {
name: 'Brenda Smith',
age: 33,
hairColor: 'black',
hobbies: ['golf', 'mathematics'],
}, {
name: 'Jane Garcia',
age: 27,
hairColor: 'blonde',
hobbies: ['biology', 'medicine', 'gymnastics'],
}];
const products = [{
name: 'Flat-Screen TV',
price: '$300',
description: 'Huge LCD screen, a great deal',
rating: 4.5,
}, {
name: 'Basketball',
price: '$10',
description: 'Just like the pros use',
rating: 3.8,
}, {
name: 'Running Shoes',
price: '$120',
description: 'State-of-the-art technology for optimum running',
rating: 4.2,
}];
- We want display this data inside several different kinds of lists using list and list item components which can help us do this most effectively. Lets create some list item components and create two different variations of list items for each type of resource. Create the following files and folders inside the src directory.
src
│ App.js
│ index.js
│ App.css
│ ...
│
└───persons
│ │ LargePersonListItem.js
│ │ SmallPersonListItem.js
│ │
│
└───products
│ │ LargeProductListItem.js
│ │ SmallProductListItem.js
- Let's implement each of these starting off with our 'SmallPersonListItem' component. It's going to take a person as a prop. It's going to get only the name and age from that person props and return them in a
<p>
tag:
export const SmallPersonListItem = ({ person }) => {
const { name, age } = person;
return (
<p>Name: {name}, Age: {age} years</p>
)
}
NOTE:
No styling indicates this components doesn't "know" where its going, so we could display the small person list item in a numbered list, in a very narrow list, in a very wide list, and we could use the styling in its parent component to determine how it gets displayed.
- The LargePersonListItem component is similar to the SmallPersonListItem component but is passing in more props. It will return the JSX wrapped in a fragment as we want to keep the styling open for options in the parent component.
export const LargePersonListItem = ({ person }) => {
const { name, age, hairColor, hobbies } = person;
return (
<>
<h3>{name}</h3>
<p>Age: {age} years</p>
<p>Hair Color: {hairColor}</p>
REMEMBER:
the prop hobbies
is an array, so we will map the hobbies, adding a list item with a key = the hobby itself, and we'll insert the hobby string into that list item. Here is the rest of the LargePersonListItem component:
<h3>Hobbies:</h3>
<ul>
{/* INSERT hobby string into the list item */}
{hobbies.map(hobby => <li key={hobby}>{hobby}</li>)}
</ul>
</>
);
}
-
Now lets create a
single list component
that can display all of these different list items. Create a new file inside the src folder calledRegularList.js
. -
Start by exporting and defining the component which takes in a prop called
items
, a prop calledresourceName
, and a prop calleditemComponent
:
export const RegularList = ({
items,
resourceName,
itemComponent: ItemComponent,
}) => {
- And then for the body of the component in the return statement, inside react fragments, we will map over all of the items and display one item component for each of them, passing it to the prop called resource name:
return (
<>
{items.map((item, i) => (
<ItemComponent key={i} {...{ [resourceName]: item }} />
))}
</>
)
}
RegularList Component Notes:
- Map over the items:
{items.map(
- We get the item and its index here:
(item, i)
- Display the item component:
<ItemComponent
- Add a key, which is just going to be the index.
key={i}
Use the spread operator to spread an object with a key that's going to be that resourceName
prop, and we're going to pass through item
for that:
{...{ [resourceName]: item }}
As it stands, the ItemComponent looks like this:
<ItemComponent key={i} {...{ [resourceName]: item }} />
What this is going to change to if we pass in person
as resourceName
is:
<ItemComponent key={i} person = {item} />
So the Complete RegularList component
looks like this:
export const RegularList = ({
items,
resourceName,
itemComponent: ItemComponent,
}) => {
return (
<>
{items.map((item, i) => (
<ItemComponent key={i} {...{ [resourceName]: item }} />
))}
</>
)
}
Lets open up our App.js
component and display two lists. So we are going to import three components: RegularList
, SmallPersonListItem
, and LargePersonListItem
:
import { RegularList } from "./RegularList";
import {SmallPersonListItem} from "./people/SmallPersonListItem";
import {LargePersonListItem} from "./people/LargePersonListItem";
In the return statement we will display the RegularList component and pass in three props:
prop | description |
---|---|
items = {people} |
the data from above |
resourceName ="person" |
the name of the prop that our SmallPersonListItem and LargePersonListItem are expecting |
itemComponent ={SmallPersonListItem} |
the component that we want each of these people to be displayed inside of |
So our return statement starts with:
<>
<RegularList
items={people}
resourceName="person"
itemComponent={SmallPersonListItem} />
And includes the LargePersonListItem to finish it off:
<RegularList
items={people}
resourceName="person"
itemComponent={LargePersonListItem} />
</>
Run the app:
yarn start
OR
npm run start
So we see the SmallPersonListItem component on the top three lines, and then the LargePersonListItem:
Name: John Doe, Age: 54 years
Name: Brenda Smith, Age: 33 years
Name: Jane Garcia, Age: 27 years
John Doe
Age: 54 years
Hair Color: brown
Hobbies:
swimming
bicycling
video games
Brenda Smith
Age: 33 years
Hair Color: black
Hobbies:
golf
mathematics
Jane Garcia
Age: 27 years
Hair Color: blonde
Hobbies:
biology
medicine
gymnastics
FINAL NOTE:
And I just want to point out before we move on that the regular way of doing this is not to have this reusable list component. It's, instead, to create a large person list item list and a small person list item list that then display those components. So, as you can see, the way that we've done it here makes the regular list a lot more reusable. We're able to simply pass in the component that we want to be displayed as children of this list.