Different ways to passing props and mapping in Reactjs - Day 3
We will learn how we can map over data to create components of our choice. Then we will check some ways to pass or receive props.
Props are a great way on react to deal with data to make our component reusable. In our previous article, we have learned how to pass and receive props. Today we will learn how to map over data to make our component dynamic and our code more self-sustaining.
The problem of creating components manually
We had created a card component on our previous blog. Here is the code of App.js file where we were using Card component.
import './App.css';
import Card from './card'
import data from './data.js'
function App() {
let firstData = data[0]
let secondData = data[1]
let thirdData = data[2]
return (
<div className="App">
<Card
name = {firstData.name}
pic = {firstData.profilePic}
title = {firstData.title}
email = {firstData.email}
about = {firstData.about}
/>
<Card
name = {secondData.name}
pic = {secondData.profilePic}
title = {secondData.title}
email = {secondData.email}
about = {secondData.about}
/>
<Card
name = {thirdData.name}
pic = {thirdData.profilePic}
title = {thirdData.title}
email = {thirdData.email}
about = {thirdData.about}
/>
</div>
);
}
export default App;
Here we have a problem with our code. Our component is manually used and data are also passed manually. What if new data is added to data.js file? Will it automatically form a new Card component? No. We are manually accessing data from data.js file and passing them by calling Card manually. Our code isn't self-sustaining. To solve this issue map comes to the rescue.
Mapping over Data to create the component
Now instead of manually passing data, we will now use the map to go through an array of data and pass the props into our component. Here is how we will do that.
import './App.css';
import Card from './card'
import data from './data.js'
function App() {
let profileCard = data.map((el)=>{
return <Card
name = {el.name}
pic = {el.profilePic}
title = {el.title}
email = {el.email}
about = {el.about}
/>
})
return (
<div className="App">
{profileCard}
</div>
);
}
export default App;
We have mapped over data and we know that data is an array of objects. So el is an object of a specific index starting from 0 to the length of the array and we access data in the format of objectName.keyname like we did on our code. Then we saved it in a profileCard variable which will now contain jsx element returned by the card. Then we used the profileCard variable in div with curly braces.
Fix warning: Each child in a list should have a unique "key" prop.
If you open dev tools on your browser, you will see this error on your console. This means that you need to pass a key prop with a unique value each time you are passing props on a component. In our cases when we are passing props on Card component, we must pass additional props called keyswith unique values. So, how to pass unique values to the key? Well, there are certain ways but for now, we will just add an id field to data.js file with a unique value for data and pass it to the key.
Here is how our data.js file look now
const data = [
{
id: 1,
name: "Roshan K.C",
title: "Software engineer | Cybersecurity enthusiast",
profilePic: "https://avatars.githubusercontent.com/u/83297534?v=4",
email: "admin@roshankc.info.np",
about: "I am a computer science student from Pokhara Nepal who is interested in software engineering, Cybersecurity research, and blogging."
},
{
id: 2,
name: "Yagami light",
title: "Software engineer",
profilePic: "https://avatars.githubusercontent.com/u/83297534?v=4",
email: "test1@gmail.com",
about: "I am kira."
},
{
id: 3,
name: "James bond",
title: "007",
profilePic: "https://avatars.githubusercontent.com/u/83297534?v=4",
email: "007@gmail.com",
about: "Name is enough."
}
]
export default data
Here is how you pass a key prop.
import './App.css';
import Card from './card'
import data from './data.js'
function App() {
let profileCard = data.map((el)=>{
return <Card
key={el.id}
name = {el.name}
pic = {el.profilePic}
title = {el.title}
email = {el.email}
about = {el.about}
/>
})
return (
<div className="App">
{profileCard}
</div>
);
}
export default App;
Now the warning should be gone.
Pass object as props
Here we are passing our props individually. What if there are more props? It would be a hassle to pass all items individually. Why not pass the whole object as props? Yes, we can do that.
import './App.css'; import Card from './card' import data from './data.js'
function App() { let profileCard = data.map((el)=>{ return }) return (
export default App;
I have passed all el objects as data props. Now we need to go back to our card component and fix some issues. Now try to console.log(props) in Card.js file. We will see that props object has another object named data inside it whose value is the object we passed. So like we access and object inside the object in normal javascript, we do same here. Here is how our Card component looks now.
import './card.css'
export default function Card(props) {
console.log(props)
return (
<div className="card">
<img src={props.data.profilePic} className="pp-img" alt="profile" />
<div className="bio">
<h2 className="name">{props.data.name}</h2>
<p className="title">{props.data.title}</p>
<a href={`mailto:${props.data.email}`} className='email'>Email</a>
</div>
<div className='about'>
<h2>About</h2>
<p>{props.data.about}</p>
</div>
</div>
)
}
Spread Object while passing
Instead of a directly passing object, we can also use a spread operator to spread our data before passing. This is how our App component looks now. We have spread the object el, which will pull out all values of the object and spread them out, which will be similar to before when we passed individually.
import './App.css';
import Card from './card'
import data from './data.js'
function App() {
let profileCard = data.map((el)=>{
return <Card
key={el.id}
{...el}
/>
})
return (
<div className="App">
{profileCard}
</div>
);
}
export default App;
Now the last thing is to fix our Card component because it is receiving the properties of objects directly. You can console.log(props) and see so that you know how to fix it. Here is how I have fixed it.
import './card.css'
export default function Card(props) {
console.log(props)
return (
<div className="card">
<img src={props.profilePic} className="pp-img" alt="profile" />
<div className="bio">
<h2 className="name">{props.name}</h2>
<p className="title">{props.title}</p>
<a href={`mailto:${props.email}`} className='email'>Email</a>
</div>
<div className='about'>
<h2>About</h2>
<p>{props.about}</p>
</div>
</div>
)
}
What we learned
We have learned how to map over data to create self-sustaining code. We learned how to pass objects as props and use of spread operator to make our life easier.