All right guys. In this lesson, we're going to be learning a new technique to get rid of a big eyesore
in our App.jsx.
Notice how we are creating these card components, and indeed we do have these customizable reusable card
components for each of which we're passing over different custom props that comes from our contacts
array, over here.
But notice how repetitive it is.
We're writing contacts[0].name, contacts[1].name, it seems like it would really benefit
from a loop. In this lesson,
I'm going to show you a technique called mapping components, which is going to make it easy for us to
map all of these individual custom pieces of data to each of these custom components.
And that way we won't have to keep creating card after card, after card, and it can be created dynamically,
for example, using a form on our website or some input elements.
So the map function is a JavaScript function that's really useful for handling arrays such as our contacts
array.
So our contacts array currently contains three items. And each of these are a JavaScript object with
the same properties but different values. Inside our App.jsx, if instead we can go ahead and comment out
these three cards, and instead what we're going to do is we're going to tap into that contacts array
which we have access to because we imported it from the contacts file, and then we're going to call the
map function. So we can write contacts.map(). Now,
note how at the moment it's just typing it out like it's plain text, and that is of course because we're
inside a div element as a child,
so we have to go ahead and wrap it inside some curly braces
so this gets interpreted as JavaScript code.
This map function as the input,
the thing that should go inside these parentheses, it expects an actual function.
So in this case we're calling a function and then passing it a function,
and this is kind of the fundamentals of what you might call functional programming, where instead of
passing values around your code, you're passing functions into functions, even into functions. You can have
many, many levels of functions being passed around.
So what functionality do we want to happen to each of our contacts?
Well, let's go ahead and create a new function up here, and I'm going to call it createCard.
So this function is going to create a new Card component.
So I'm going to return a custom card component and of course, I'm going to pass it some properties.
So let's say that we just pass it one property, which is the name property which we know that the card
is able to handle and put into this h2.
Now this name property I'm going to set it equal to some value, right? Now
let's imagine that this function
createCard, when it gets called it gets passed over a single contact.
So not an array of contacts but a single JavaScript object such as this one or this one.
And of course, each of these objects have properties such as id, name, imgURL that we can tap into
inside the function.
So I could set the name property of the Card component to equal contact.name. So now I'm going to
pass this entire function createCard into my map function.
So let's go ahead and get it to create a card, and what the map function does is it loops through this
array of contacts,
and for every single item that exists in the array, it calls the createCard function and it passes over
each of the objects inside the array.
So that means for the first time it loops around
it passes this entire first element in as the contact, and then we can get hold of it inside our return
statement, and get hold of the name property which gets put into our card component,
right here.
I can of course
go ahead and elaborate on this by adding the img property and set that equal to the contact.img.URL
I think is the name inside our contacts.js.
And that now shows up over here.
And then maybe I can add another property, the telephone property, which I'll set to equal contact.phone
.
And finally, I've got the email property which is just stored inside contact.email.
So now, I've got my Card component which is getting all of these pieces of information using these properties
from our contacts.js, these JavaScript Objects, with each of these names right here.
And that is being sent over as the props for our custom Card component. as we can see in our React Dev
Tools.
But notice how in the console we're actually getting a warning here< and this warning doesn't go away
when we refresh the browser.
So it's actually a real warning instead of some sort of problem with CodeSandbox. And what it tells
us is that, "Each child in a list should have a unique 'key' property."
This is a really important point.
Remember how in the beginning I said that React is able to create a virtual DOM that represents the
current appearance of your website,
and for it to be able to efficiently render components, for every single component that's being rendered
using a loop such as the map function, we will have to give those components a property that has to be
called key. And this property has to be something that is unique amongst each of these Card components
that's being created using this loop.
Luckily inside our contacts.js, I've got an id property which is unique amongst each of these
contacts, and we're going to use it as the key,
so contact.id. And now once we do that our warning goes away because we're now conforming with
React's rules.
Now this key prop has to be spelt exactly like this and it's expected by React. And the value can be
a string or it can be a number, but it must be unique across all of the repeated components,
so in this case our cards. Now I have a challenge for you that's going to require a little bit of debugging
on your part.
See if you can get this key prop which we know corresponds to the ids,
so 1, 2 and 3 that's being passed over to the card component.
See if you can get that rendered as a paragraph tag above the h2,
so right here. Pause the video and complete this challenge.
And as a hint, you're going to have to dig into the React Dev Tools to figure out what's actually going on.
And then once you're done come back and we'll go through the solution together.
All right.
So this was a bit of a trick question because what you will have realized is that if you just go ahead
and create a paragraph tag, and then inside there you try to get hold of props.key which we know
is the name of the prop being passed over,
you can see that not only does it not show up,
we also get a warning.
And it tells us that key is not a prop, "Trying to access it will result in an `undefined` being returned.
So if you need it, you should create the same value as a different prop.
And we can see this if we actually look inside the React Dev Tools.
If we look at our Card, we can see that out of all of the props that we're getting we don't see that
key prop.
And the reason is because as I mentioned, that key property for each React component is a special property.
And it's used to ensure the right order of items goes into the tree,
it's used so that it can render each of these components efficiently when they're being created from
a loop, but it is not something that we can tap into. If we actually wanted to show that id which comes
from contacts,
what we actually have to do is we have to create our own custom prop,
say for example id = contact.id.
And even though it seems a bit repetitive because it seems like we've already got this key called prop,
that is contact.id, but we have to remember that this is not for us to use.
So now if I go in here and I change that props to id then everything works fine
and I don't get any warnings anymore.
So Dev Tools is really, really useful for debugging problems like this, and I'm going to try and trip
you up a few times like this, just so that you get a chance to use it and get used to debugging your
code because bugs always happen. It happens to the best of us.
And there was a time when I thought I was only a programmer that could create bugs not code.
So it's perfectly normal,
and it's really important to get used to the tools. In the next lesson, you're going to be putting this
technique into action in a challenge
where are you going to map data to React
components and render everything from scratch yourself.
So for all of that and more, I'll see you there.