Skip to content

Instantly share code, notes, and snippets.

@jmcd
Created October 25, 2018 13:47
Show Gist options
  • Save jmcd/8ea093051da607421b254e82ab26bfca to your computer and use it in GitHub Desktop.
Save jmcd/8ea093051da607421b254e82ab26bfca to your computer and use it in GitHub Desktop.
My first react app - an implementation of https://reactjs.org/docs/thinking-in-react.html
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render() {
const unfilteredData = [
{ category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football" },
{ category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball" },
{ category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball" },
{ category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch" },
{ category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5" },
{ category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7" }
].map(p => {
p.rawPrice = parseFloat(p.price.replace('$', ''));
return p;
});
return (
<FilterableProductTable unfilteredData={unfilteredData} />
);
}
}
export default App;
class FilterableProductTable extends Component {
constructor(props) {
super(props);
this.handleTextChange = this.handleTextChange.bind(this);
this.handleInStockChange = this.handleInStockChange.bind(this);
this.state = {
filterText: '',
filterInStock: false,
};
}
handleTextChange(text) {
this.setState({ filterText: text });
}
handleInStockChange(flag) {
this.setState({ filterInStock: flag });
}
render() {
const unfilteredData = this.props.unfilteredData;
const filterText = this.state.filterText.toLocaleLowerCase();
const filterInStock = this.state.filterInStock;
const filteredData = unfilteredData.filter(item =>
item.name.toLocaleLowerCase().includes(filterText) && (!filterInStock || item.stocked === true)
);
return (
<div>
<SearchBar
text={this.state.filterText}
onTextChange={this.handleTextChange}
onInStockChange={this.handleInStockChange}
/>
<ProductTable data={filteredData} />
</div>
);
}
}
class SearchBar extends Component {
constructor(props) {
super(props);
this.handleTextChange = this.handleTextChange.bind(this);
this.handleInStockChange = this.handleInStockChange.bind(this);
}
handleTextChange(e) {
const text = e.target.value;
this.props.onTextChange(text);
}
handleInStockChange(e) {
this.props.onInStockChange(e.target.checked);
}
render() {
const text = this.props.text;
const inStock = this.props.inStock;
return (
<div>
<div>
<input type="text" value={text} onChange={this.handleTextChange} />
</div>
<div>
<input type="checkbox" value={inStock} onChange={this.handleInStockChange} /><label>Only show products in stock</label>
</div>
</div>
);
}
}
function ProductTable(props) {
const productsGroupedByCategory = props.data.reduce(function (acc, item) {
(acc[item.category] = acc[item.category] || []).push(item);
return acc;
}, {});
const productsGroupedByCategoryAndMaxPricesMarked = Object.keys(productsGroupedByCategory).reduce(function (acc, cat) {
const products = productsGroupedByCategory[cat];
const maxPrice = Math.max(...products.map(p => p.rawPrice), 0);
console.log(maxPrice);
const productsInCategory = products.map(p => {
return {
name: p.name,
price: p.price,
isMaxPrice: p.rawPrice === maxPrice,
};
});
acc[cat] = productsInCategory;
return acc;
}, {});
return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
{
Object.keys(productsGroupedByCategoryAndMaxPricesMarked).map(cat =>
<tbody key={cat}>
<ProductCategoryRow category={cat} />
{productsGroupedByCategoryAndMaxPricesMarked[cat].map(product => <ProductRow key={product.name} product={product} />)}
</tbody>
)
}
</table>
);
}
function ProductCategoryRow(props) {
const category = props.category;
return <tr><th colSpan="2">{category}</th></tr>
}
function ProductRow(props) {
const product = props.product;
return (
<tr>
{product.isMaxPrice ? <td style={{ color: "red" }}>{product.name}</td> : <td>{product.name}</td>}
<td>{product.price}</td>
</tr>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment