- Build Applications with Meteor
- Dobrin Ganev
- 605字
- 2021-07-09 19:48:56
The ProductsContainer
In the following figure, we have a ProductsContainer as the top-level parent component connected to the data source:

The functionality of the ProductsContainer is to load all the products from the ProductsCollection and render a Product presentational component for each product item. As always, we pass the data down as props.
To access the data, we need to import both the collections from the shared directory.
We will read the data from ProductsCollection and, on a user action, we will insert, update, or delete an item in the CartCollection:
import React from 'react';
import { createContainer } from 'meteor/react-meteor-data';
import {ProductsCollection} from '../../shared/collections/ProductsCollection';
import {CartCollection} from '../../shared/collections/CartCollection';
import Product from '../components/ProductComponent';
We also want to have a function for the user to add each product to the cart; the function is as follows:
class Products extends React.Component {
constructor(props) {
super(props);
this.onAddToCart = this.onAddToCart.bind(this);
}
Products is declared as a class component and, in its constructor method, we've added the onAddToCart function. The constructor is the best place where we can bind this event handler. Binding it there will bind it to this component's context. Anywhere in the component context, we can call it with this.onAddToCart.
When this function is called, we will insert the product passed as an argument to the CartCollection. Then, we simply alert the user that the product has been added to the cart. Note that the insert to the collection is synchronous:
onAddToCart(product){
CartCollection.insert({
'title' : product.title,
'price' : product.price,
'inventory' : product.inventory,
'quantity': 1
});
alert(product.title + ' added to your cart')
}
In the render() method, we render a child presentational component Product for each item in the array of products. We pass the data to each of the children as props so that each child can render it in the UI:
render() {
const { products } = this.props
return (
<div>
<h2>Product List</h2>
{products.map(product =>
<Product
title={product.title}
price={product.price}
quantity={product.inventory}
key={product._id}
onAddToCart={() => this.onAddToCart(product)}
/>
)}
</div>
)
}
The key={product._id} is an important part of React. The key is how React identifies which component has changes in order to re-render it. It is not optional if the component was generated from a list and should be unique for each item. In our case, we are getting the ID from the database collection. Each document of a collection has a unique ID ( _id).
onAddToCart={() => this.onAddToCart(product)}
Here, we passed a function to the child as a prop of type function. The presentational component is responsible for the user actions, such as clicking on a button, to add an item to the cart. The parent will take care of moving the data in and out of the database.
The separation of concerns in this example may seem like overkill, but it is important to understand how we can abstract components based on common functionality:
export default createContainer(() => {
return {
products: ProductsCollection.find({}).fetch()
};
}, Products);
At last, we export the Products component wrapped in a Meteor reactive container. Each time the data changes in the ProductsCollection, the ProductsContainer will re-render with the new prop's products.
All the Product component does is to display the data passed as props and render a button that has the onClick event. The onAddToCart function, which we also passed as a prop, will fire back each time users click on the button:
export default class Product extends React.Component {
render() {
const { price, inventory, title, onAddToCart } = this.props;
return (
<div>
<span> {title} - ${price} {inventory ? `Current inventory
${inventory}` : null} </span>
<button onClick={onAddToCart}>
Add To Cart
</button>
</div>)
}
}
Product.propTypes = {
price: PropTypes.number,
inventory: PropTypes.number,
title: PropTypes.string,
onAddToCart: PropTypes.func.isRequired
}
- Android Jetpack開發(fā):原理解析與應(yīng)用實(shí)戰(zhàn)
- 軟件測(cè)試項(xiàng)目實(shí)戰(zhàn)之性能測(cè)試篇
- 信息技術(shù)應(yīng)用基礎(chǔ)
- VMware虛擬化技術(shù)
- 軟件測(cè)試技術(shù)指南
- ASP.NET開發(fā)與應(yīng)用教程
- 零基礎(chǔ)Java學(xué)習(xí)筆記
- Creating Mobile Apps with jQuery Mobile(Second Edition)
- 微信小程序開發(fā)與實(shí)戰(zhàn)(微課版)
- Arduino可穿戴設(shè)備開發(fā)
- 寫給大家看的Midjourney設(shè)計(jì)書
- Mastering OAuth 2.0
- Practical Maya Programming with Python
- Python 快速入門(第3版)
- Applied Deep Learning with Python