Reusable components with Props in Reactjs | Props passing - Day2

Reusable components with Props in Reactjs | Props passing - Day2

We will learn, what are props, different ways of passing props, and how they help to make reusable components.

·

8 min read

In our previous article, we learned how to create custom components. It made our codes more composable. In this article, we will learn how to make a component reusable. If you don't know about jsx, and custom components then check my previous article.

Custom Component for Card

Let us start with an example. Suppose you have a card component. To create that you can create a new file called card.js and export the following code from it just like you did to create the navbar component on our previous blog.

cardcompo.jpg

Card.js

import './card.css'

export default function Card() {
    return (
        <div className="card">
            <img src="https://avatars.githubusercontent.com/u/83297534?v=4" className="pp-img" alt="profile" />
            <div className="bio">
                <h2 className="name">Roshan K.C</h2>
                <p className="title">Software engineer | Cybersecurity enthusiast</p>
                <a href="mailto:admin@roshankc.info.np" className='email'>Email</a>
            </div>
            <div className='about'>
            <h2>About</h2>
            <p>I am a computer science student from Pokhara Nepal who is interested in software engineering, Cybersecurity research, and blogging.</p>
            </div>
        </div>
    )
}

Here in this code, we have imported CSS from a new file called card.css. You can create a file called card.css which will contain normal CSS code to style jsx returned from card.js.

.card{
    width: 250px;
    height: auto;
    display: flex;
    flex-direction: column;
    border-radius: 10px;
    background: #1A1B21;
    overflow: hidden;
    color: #F5F5F5;
    margin: 1em;
}
.pp-img{
    width: 100%;

}
.bio{
    display: flex;
    flex-direction: column;
    padding: 1em;
    text-align: center;
}
.name{
    font-weight: 700;
    font-size: 1.5rem;
    color: #FFFFFF;
    margin: 0;
}
.title{
    font-weight: 400;
    font-size: 0.9rem;
    color: #e1e0d9;
    letter-spacing: 0.4px;
    margin-bottom: 0;
}
.about{
    padding:0 1em 1em 1em; 
    text-align: left;
}
.about h2{
    margin: 0;

}
.about p{
    font-weight: 400;
    font-size: 0.9rem;
    color: #DCDCDC;
}
.email{
    text-decoration: none;
    color: #374151;
    padding: 0.5em 0.7em 0.5em 0.6em;
    margin: 0.4em;
    background: #FFFFFF;
    border: 1px solid #D1D5DB;
    box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.05);
    border-radius: 6px;
}
.email:hover{
    filter: brightness(0.8);
}

Now you can import the Card component on the App.js file. Remember how you call a custom component function to get returned value where we need it. We call custom components like we call a normal function. In our case, if we need to call the card function which is returning jsx( Html like code for card component) then we say card(). But inside jsx we call it by saying . Below is an example of using it inside App.js component.

import './App.css';
import Card from './card'
function App() {
  return (
    <div className="App">
      <Card/>
    </div>
  );
}

export default App;

Here the jsx returned from the Card component will be placed inside a div with the class name called App which will eventually get utilized to render through index.js file where the App component is called to render. This is how we utilize react to create a custom component that we can use anywhere just by importing and calling it in the place where we need it.

Problem with our Card component

But we have an issue with this method. We aren't making our component dynamic. Whenever we call it, it will return a component with static values. We might need a card for another person with different values. Our card component is not data-driven which means for every new type of card we need to again create a new card component. This means the component isn't generated as per data but by manually putting data inside it.

Let's take an example of the amazon products page. Here you can see every card contains details of the different products but the layout of the cards are same. Which means they are the same component with different data. But when a new product is added, a new card with details of the new product is automatically formed. Does that mean there is a person who updates the product card component with all the new data and makes a new card? Of course not. The card is updated with new data and generated accordingly when we add a new product.

reusable.jpg But in our profile card, there is a need for a person who will update the card values as per new data. How can we make our component dynamic so that we can make it return with data as per our need? This is where props come into saving.

Props in Reactjs

Let's understand the concept of props and u can define yourself what are props. Let's start with this example. Here you have a function named squareNum to return the square of a number.

function squareNum()
{
    return a*a
}

Now you can see every time you call this function, you will only get the square value of a. This function isn't returning dynamic values. So, how do you make this function return different values as per your data? Yes by setting parameters and passing your data through arguments. Now see the function given below.

  function squareNum(num)
{
    return num*num
}

squareNum(2)
squareNum(5)

Now you can see your function will return values as per the data you pass. Setting a parameter called num made your function reusable and dynamic. This is what the concept of props is. It is just a value you pass in your function/component and which value you will pass while calling/using your component. And the passing of value you do while calling method is passing props.

How to pass Props

As you know in real-world apps, data are fetched from api/db. In our case, we will create a file called data.js inside src directory where we will upload all our data in form of objects. Here is an example of data.js file from where we have exported an array of objects containing card component data.

datajs.jpg

const  data = [
    {
        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."
    },
    {
        name: "Yagami light",
        title: "Software engineer",
        profilePic: "https://avatars.githubusercontent.com/u/83297534?v=4",
        email: "test1@gmail.com",
        about: "I am kira."
    },
    {
        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

Let's see how we add a variable inside jsx.

function Title()
{
    let name = "Roshan K.C"
    return <h1>{name}</h1>
}

So you basically put them inside curly braces.

Now import the data on Card.js file. Then when you call the Card component you can pass props in form of the following format in App.js file.

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;

As you can see I have stored the objects at the different indexes of the array(data) in 3 different variables (firstData, secondData, thirdData). Then while calling , I passed the props in this format name = {firstData.profilePic}. Here, name will be now passed just like an argument to the function Card() in card.js file.

{firstData.profilePic} is just a way to get value from the object and as you can see it is an expression so we put it inside curly braces to use its value in jsx. So like that you pass each data with a different name as I did. I have called three different times and passed different values, so this means we will get card component called three times and we will have three html for card component.

Receiving props in Reactjs

Now just like passing argument, props are also passed into their main function. Here our function is Card(). So to receive props, we need to set a parameter in function. Which we will set as props. So this parameter named props will receive all the values we pass as an object which you can verify by doing console.log(props) inside the function.

import './card.css'

export default function Card(props) {
    console.log(props)
    return (
        <div className="card">
            <img src="https://avatars.githubusercontent.com/u/83297534?v=4" className="pp-img" alt="profile" />
            <div className="bio">
                <h2 className="name">Roshan K.C</h2>
                <p className="title">Software engineer | Cybersecurity enthusiast</p>
                <a href="mailto:admin@roshankc.info.np" className='email'>Email</a>
            </div>
            <div className='about'>
            <h2>About</h2>
            <p>I am a computer science student from Pokhara Nepal who is interested in software engineering, Cybersecurity research, and blogging.</p>
            </div>
        </div>
    )
}

You will get 3 objects logged on console with keyname as the props key you set and value as the value you had set. You get 3 object because card component is called three times on App component. Now how to use the value we received as props in our html? Remember, the props parameter is just receiving values as an object. So, how do we extract values from an object? Obviously with the help of key. Here is an example of using props.

import './card.css'

export default function Card(props) {
    console.log(props)
    return (
        <div className="card">
            <img src={props.pic} 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>
    )
}

Here you just need to wrap your javascript expression inside curly braces to use in jsx(Jsx is just a javascript that looks like html). Now your card component will return value as per the data your pass in your props. This makes our code more reusable.

Important Note

You must always remember that you can only pass props on to the custom components. You cannot pass props as "<h1 name="Roshan" " on a html component. It is because h1 tag doesn't have any attribute known as a name. You should always remember that your custom component will at last get converted into html component that dom understands. Passing custom attributes on already existing tags like h1 will break your app and cause errors.

To summarize

Props are just values that are passed through custom components. They are given specific names and values. Props are received through a parameter set in the component it is passed at. The value received is an object which is in form of {keyName: value}. We can use this as a normal object with curly braces inside jsx.

What we learned

  • What are props
  • Passing props to custom components
  • Receiving and using props
  • Things to consider while passing props.

Tomorrow we will learn how to use maps to dynamically render cards as data gets updated, various ways to receive and pass props and have a sneak peek at conditional rendering.