Filter the orders table by customer
React · React · intermediate · greenfield
Adds the customer filter to the orders table. The visible rows are derived with `useMemo` keyed on the orders prop and the query, so parent re-renders don't re-run the 10k-row filter; the query is trimmed and lowercased once per recompute. Empty state included.
Requirements
- Add a customer filter box above the orders table: case-insensitive substring match on the order's `customer` field.
- An empty (or whitespace-only) query shows all orders; a query matching nothing shows an empty-state message.
- The component receives `orders` as a prop; accounts can have up to 10,000 orders, so memoize the derived rows to avoid re-running the filter as a performance optimization on ordinary re-renders where neither the orders reference nor the query changed.
- The input is controlled and labelled for assistive technology.
- Do not mutate the `orders` prop.
Files touched
- src/components/OrderList.jsx
--- src/components/OrderList.jsx
+import { useMemo, useState } from 'react';
+
+function OrderList({ orders }) {
+ const [query, setQuery] = useState('');
+
+ const visible = useMemo(() => {
+ const needle = query.trim().toLowerCase();
+ if (needle === '') {
+ return orders;
+ }
+ return orders.filter((order) =>
+ order.customer.toLowerCase().includes(needle),
+ );
+ }, [orders, query]);
+
+ return (
+ <div className="order-list">
+ <input
+ type="search"
+ value={query}
+ onChange={(event) => setQuery(event.target.value)}
+ aria-label="Filter orders by customer"
+ placeholder="Filter by customer"
+ />
+ <ul>
+ {visible.map((order) => (
+ <li key={order.id}>
+ {order.customer} — {order.itemCount} items
+ </li>