Data Propagation

The ProductList component that we defined in the previous section is impractical. Let's take a look at it again:

import React from 'react';
import './ProductList.css';

class ProductList extends React.Component {
render() {
return <ul>
<li>
<h3>Traditional Merlot</h3>
<p>A bottle of middle weight wine, lower in tannins (smoother),
with a more red-fruited flavor profile.</p>
</li>
<li>
<h3>Classic Chianti</h3>
<p>A medium-bodied wine characterized by a marvelous freshness with
a lingering, fruity finish</p>
</li>
<li>
<h3>Chardonnay</h3>
<p>A dry full-bodied white wine with spicy, bourbon-y notes in an
elegant bottle</p>
</li>
<li>
<h3>Brunello di Montalcino</h3>
<p>A bottle of red wine with exceptionally bold fruit flavors, high
tannin, and high acidity</p>
</li>
</ul>;
}
}

export default ProductList;

The list items are all defined as JSX markup, so if you need to change the graphical appearance of the catalog's product, you need to change all of the occurrences of each <li> element.

We can make a better implementation by going further in the user interface decomposition. We can consider each list item as a component, and the Product component as the one defined by the following code:

import React from 'react';

class Product extends React.Component {
render() {
return <li>
<h3>Product name</h3>
<p>Product description</p>
</li>;
}
}

export default Product;

This code acts as a template for each list item, so that we can build our product list dynamically, as follows:

import React from 'react';
import './ProductList.css';
import Product from './Product';

class ProductList extends React.Component {
render() {
let products = [
{code:"P01", name: "Traditional Merlot", description: "A bottle
of middle weight wine, lower in tannins (smoother), with a
more red-fruited flavor profile."},
{code:"P02", name: "Classic Chianti", description: "A medium-bodied
wine characterized by a marvelous freshness with a lingering,
fruity finish"},
{code:"P03", name: "Chardonnay", description: "A dry full-bodied
white wine with spicy, bourbon-y notes in an elegant bottle"},
{code:"P04", name: "Brunello di Montalcino", description: "A bottle
of red wine with exceptionally bold fruit flavors, high tannin,
and high acidity"}
];
let productComponents = [];

for (let product of products) {
productComponents.push(<Product/>);
}

return <ul>{productComponents}</ul>;
}
}

export default ProductList;

We can see the definition of an array of objects, products, containing the relevant data for each product. The second array, productComponents, will contain the list of React components created by merging product data with the Product component's markup. The for loop is intended to perform such merging. Finally, the resulting productComponents array, surrounded by the <ul> element, will be returned.

Even if the code structure appears to be correct, the result will not be as expected. In fact, we will obtain a list of items with the fixed names and descriptions that we put in the Product component definition. In other words, the merge between data and component definition didn't happen.

Actually, we need a way to pass the data of each product to the Component class. Let's think of React components as plain JavaScript functions. They may be implemented as functions returning React elements, and, as with any function, components may have data input. Such data input is passed through JSX attributes, and is accessible inside of a component through a special object called props. Let's change the ProductList component's code in order to pass data through JSX attributes:


import React from 'react';
import Product from './Product';

class ProductList extends React.Component {
render() {
let products = [
{code:"P01", name: "Traditional Merlot", description: "A bottle
of middle weight wine, lower in tannins (smoother), with a
more red-fruited flavor profile."},
{code:"P02", name: "Classic Chianti", description: "A medium-bodied
wine characterized by a marvelous freshness with a lingering,
fruity finish"},
{code:"P03", name: "Chardonnay", description: "A dry full-bodied
white wine with spicy, bourbon-y notes in an elegant bottle"},
{code:"P04", name: "Brunello di Montalcino", description: "A bottle
of red wine with exceptionally bold fruit flavors, high tannin,
and high acidity"}
];

let productComponents = [];

for (let product of products) {
productComponents.push(<Product
item={product}/>);
}

return <ul>{productComponents}</ul>;
}
}

export default ProductList;

We added an item attribute to the <Product> tag and assigned a single object from the products array to it. This allows us to pass the data of each product to the Product component.

On the other hand, we modify the Product component's code in order to receive and manage the passed data:

import React from 'react';

class Product extends React.Component {
render() {
return <li>
<h3>{this.props.item.name}</h3>
<p>{this.props.item.description}</p>
</li>;
}
}

export default Product;

You can find a project ready in the my-shop-04 folder at Code/Chapter-2/.

Every React component has a props property. The purpose of this property is to collect data input passed to the component itself. Whenever a JSX attribute is attached to a React element, a property with the same name is attached to the props object. So, we can access the passed data by using the attached property. In our example, we found the product data passed via the item attribute mapped to the this.props.item property.


props are immutable; that is, they are read-only properties.

This new implementation allows the catalog to be shown as before, but makes graphical markup independent from a product's data.

In a component hierarchy, data propagation is very important. It allows us to think about components as functions with inputs and outputs. In addition, the immutability of props allows us to think of components as pure functions, which are functions that have no side effects (since they don't change their input data). We can think of data passing from one component to another as a unidirectional data flow, from the parent component toward the child components. This gives us a more controllable system.

The following diagram shows how we would imagine the data propagation in a component hierarchy, ideally:

A change in the state causes a data propagation toward the child components through the props property.

..................Content has been hidden....................

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