Props

So, this all looks good. However, in reality, since we have multiple products and not just one, we need a list of Card components, and not just one. It doesn't make sense to hardcode this component multiple times to correspond to each product. So, instead, we want to write the card component once. The CardContainer component we discussed in the React application design section should pass the product information to the Card component. So, we basically have a parent component that needs to pass some information to a child component.

You might wonder: why do we need the CardContainer component to pass data to the Card component, and not have the Card component look for its own data? The answer is simple: it was found that the best design for React applications is to have data state handled at the uppermost parent component where the data makes sense, then pieces of the data get passed down to smaller child components as needed. This design allows the child components to be in sync with one another, and in sync with their parents.

In our application, the uppermost component where all the product's information data should be handled is CardContainer, whereas the smaller child components that only need access to individual product information is handled in the Card components. In the world of React, this passing of data from parent component to child components is done using the props object. Props simply stands for properties. 

To access the properties within any React component, we just need to call this.props. Let's assume that the product information was already passed to our Card component using props. Here is how the Card code will now look:

import React from 'react';
class Card extends React.Component {
render() {
return (
<div className="col-md-6 col-lg-4 d-flex align-items-stretch">
<div className="card mb-3">
<img className="card-img-top" src={this.props.img} alt={this.props.imgalt} />
<div className="card-body">
<h4 className="card-title">{this.props.productname}</h4>
Price: <strong>{this.props.price}</strong>
<p className="card-text">{this.props.desc}</p>
<a href="#" className="btn btn-primary">Buy</a>
</div>
</div>
</div>
);
}
}

In the preceding code, we simply accessed the props object through this.props, and since we assumed that the product information was already passed to us through props, the props object had all the information that we needed.

So, now comes the important question: how was the information passed from the parent component (CardContainer, in our case) to the child components (Card, in our case) using props?

The answer is quite simple; since a component name becomes a DOM tag in JSX, we can simply represent a component in JSX, as follows:

 <Card img="img/strings.png" alt="strings" productName="Strings" price='100.0' desc="A very authentic and beautiful instrument!!" />

In the preceding code, we utilized JSX to create a React element that represents a single product card component. The element tag name is Card, whereas the props are passed as attributes in JSX. If you look at the Card component code that we covered right before this, you will find that the names of the props correspond to the attribute names we passed within the React element that we created previously. In other words, the props were img, alt, productName, price, and desc. Those were the same names as the attributes in the preceding React element.

So, let's create a very simple CardContainer component that hosts only two cards, and see how this looks. Based on what we know so far, to create a React component, you need to do the following:

  • Create a class that inherits from React.Component
  • Override the render() method of React.Component

Here is how the code looks:

class CardContainer extends React.Component{
render(){
return(
<div>
<Card key='1' img="img/strings.png" alt="strings" productName="Strings" price='100.0' desc="A very authentic and beautiful instrument!!" />
<Card key='2' img="img/redguitar.jpeg" alt="redg" productName="Red Guitar" price='299.0' desc="A really cool red guitar that can produce super cool music!!" />
</div>
);
}
}

There are two important things that we need to cover from the preceding code:

  • We put the two cards inside a parent div element. This is important because the render() method needs to return a single React element.
  • We added a key attribute, even though it was not part of the Card component. The key property is a reserved property in React. Keys are important to use when working with lists of elements. Keys must be unique for each item. A key only needs to be unique on an item, compared to its sibling items. In our case, we have a list of cards, so that's why we used the key prop. React uses keys to figure out which items would need to get re-rendered, and which items stayed the same. A React component cannot access the key property through the props object. React monitors whether keys get added, removed, or changed. Then, it makes decisions on which components need to get re-rendered, and which components don't need to be touched. 

The render() method in the preceding code can actually get refactored further:

render() {
//hardcoded card list
const cards = [{
"id" : 1,
"img" : "img/strings.png",
"imgalt":"string",
"desc":"A very authentic and beautiful instrument!!",
"price" : 100.0,
"productname" : "Strings"
}, {
"id" : 2,
"img" : "img/redguitar.jpeg",
"imgalt":"redg",
"desc":"A really cool red guitar that can produce super cool music!!",
"price" : 299.0,
"productname" : "Red Guitar"
}];
//get a list of JSX elements representing each card
const cardItems = cards.map(
card => <Card key={card.id} img={card.img} alt={card.imgalt} productName={card.productname} price={card.price} desc={card.desc} />
);
return (
<div>
{cardItems}
</div>
);
}

In the preceding code, we still hardcode the product card information for simplicity, but this time we use JavaScript's map() method to create a list of React elements. We then include our elements inside a parent div element, and return it as the result of our render() method.

The preceding code can actually get refactored even further, since it's a bit verbose to assign every single attribute with a value from a card item. Instead, React supports the following syntax:

const cardItems = cards.map(
card => <Card key={card.id} {...card} />
);

In the preceding syntax, we just used ... to pass all the properties of a card item to a Card component. This code works because the properties of the card object have the same names as the properties that are expected through the props object by the Card component. We still explicitly assigned the key attribute, because the Card object didn't have a key property—it had an id property instead.

The CardContainer component becomes the entry component to our product page, instead of the Card component. This means that we should render CardContainer instead of Card under the root div of our HTML document:

ReactDOM.render(
<CardContainer />,
document.getElementById('root')
);
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.78.136