Resources
Learning React:
The Slide Deck -
Thinking in React Guide
React Hooks Intro
React Tutorials:
Detailed React Tutorial
Tic-Tac-Toe Tutorial
React Exercises
UI Libraries for Web:
Iman’s Guide To React (TypeScript)
Code Example:
import { useState } from "react";
import { Product, PRODUCTS } from "./constants";
import logo from "./logo.svg";
import "./App.css";
interface TableProps {
products: Product[];
}
interface RowProps {
product: Product;
}
interface ChangeSearchProps {
handleCheck: (e: any) => void;
handleFilter: (e: any) => void;
}
interface SearchProps {
stockedChecked: boolean;
filterText: string;
}
const ProductRow: React.FC<RowProps> = ({ product }) => {
const { name, price, category, stocked } = product;
const coloredName = stocked ? (
name
) : (
<span style={{ color: "red" }}>{name}</span>
);
return (
<tr>
<td>{coloredName}</td>
<td>{price}</td>
<td>{category}</td>
</tr>
);
};
const Table: React.FC<TableProps & SearchProps> = ({
products,
stockedChecked,
filterText,
}) => {
const headers = ["Name", "Price", "Category"];
const processProduct = (product: Product) => {
if (stockedChecked && !product.stocked) {
return null;
}
if (product.name.includes(filterText)) {
return <ProductRow product={product} />;
}
return null;
};
return (
<table>
<thead>
<tr>
{headers.map((header) => (
<th>{header}</th>
))}
</tr>
</thead>
<tbody>{products.map(processProduct)}</tbody>
</table>
);
};
const Search: React.FC<SearchProps & ChangeSearchProps> = ({
filterText,
stockedChecked,
handleCheck,
handleFilter,
}) => {
return (
<form>
<input
type="text"
placeholder="Search..."
value={filterText}
onChange={handleFilter}
/>
<p>
<input
type="checkbox"
checked={stockedChecked}
onChange={handleCheck}
/>
Only show products in stock
</p>
</form>
);
};
const FilterableProductTable: React.FC<TableProps> = ({ products }) => {
const [isChecked, setIsChecked] = useState(false);
const [filterText, setFilterText] = useState("");
const handleCheck = (e: any) => {
setIsChecked(e.target.checked);
};
const handleFilter = (e: any) => {
setFilterText(e.target.value);
};
return (
<div>
<Search
stockedChecked={isChecked}
filterText={filterText}
handleCheck={handleCheck}
handleFilter={handleFilter}
/>
<Table
products={products}
stockedChecked={isChecked}
filterText={filterText}
/>
</div>
);
};
function App() {
return <FilterableProductTable products={PRODUCTS} />;
}
export default App;
constants.ts
file:
export interface Product {
category: "Sporting Goods" | "Electronics";
price: string;
stocked: boolean;
name: string;
}
export const PRODUCTS: Product[] = [
{
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" },
];