const handleSearch = (e) => {
setQuery(e.target.value);
// products can be 1000000s of records
setFilteredProducts(
products.filter((p) => p.includes(e.target.value))
);
};
import React, { useState, render } from "react";
const products = Array.from(
{ length: 5000000 },
(_, i) => `Product ${i + 1}`
);
function ProductList() {
const [query, setQuery] = useState("");
const [filteredProducts, setFilteredProducts] =
useState(products);
const handleSearch = (e) => {
setQuery(e.target.value);
setFilteredProducts(
products.filter((p) => p.includes(e.target.value))
);
};
return (
<div>
<input
type="text"
value={query}
onChange={handleSearch}
placeholder="Search..." />
<ul>
{filteredProducts.slice(0,20).map((product) => (
<li key={product}>{product}</li>
))}
</ul>
</div>
);
}
render(<ProductList />)
body {
padding: 16px;
font-size: 24px;
}
h1 {
font-size: 32px;
}
import React, { useState, render, useTransition } from "react";
const products = Array.from(
{ length: 5000000 },
(_, i) => `Product ${i + 1}`
);
function ProductList() {
const [query, setQuery] = useState("");
const [filteredProducts, setFilteredProducts] =
useState(products);
const [isPending, startTransition] = useTransition();
const handleSearch = (e) => {
setQuery(e.target.value);
startTransition(() => {
setFilteredProducts(
products.filter((p) => p.includes(e.target.value))
);
});
};
return (
<div>
<input
type="text"
value={query}
onChange={handleSearch}
placeholder="Search..." />
{isPending && <p>Loading...</p>}
<ul>
{filteredProducts.slice(0, 20).map((product) => (
<li key={product}>{product}</li>
))}
</ul>
</div>
);
}
render(<ProductList />)
body {
padding: 16px;
font-size: 24px;
}
h1 {
font-size: 32px;
}
const [isPending, startTransition] = useTransition();
const handleSearch = (e) => {
setQuery(e.target.value); // important
startTransition(() => { // not important
setFilteredProducts(
products.filter((p) => p.includes(e.target.value))
);
});
};
return isPending ? "Loading ..." : null;
âś… Best Use Cases
❌ Avoid When