const usePokemonListTs = `export type Pokemon = { name: string; url: string; }; export type UsePokemonListProps = { /** Delay to wait before fetching more items */ fetchDelay?: number; }; export function usePokemonList({fetchDelay = 0}: UsePokemonListProps = {}) { const [items, setItems] = React.useState([]); const [hasMore, setHasMore] = React.useState(true); const [isLoading, setIsLoading] = React.useState(false); const [offset, setOffset] = React.useState(0); const limit = 10; // Number of items per page, adjust as necessary const loadPokemon = async (currentOffset: number) => { const controller = new AbortController(); const {signal} = controller; try { setIsLoading(true); if (offset > 0) { // Delay to simulate network latency await new Promise((resolve) => setTimeout(resolve, fetchDelay)); } let res = await fetch( \`https://pokeapi.co/api/v2/pokemon?offset=\${currentOffset}&limit=\${limit}\`, {signal}, ); if (!res.ok) { throw new Error("Network response was not ok"); } let json = await res.json(); setHasMore(json.next !== null); // Append new results to existing ones setItems((prevItems) => [...prevItems, ...json.results]); } catch (error) { if (error.name === "AbortError") { console.log("Fetch aborted"); } else { console.error("There was an error with the fetch operation:", error); } } finally { setIsLoading(false); } }; React.useEffect(() => { loadPokemon(offset); }, []); const onLoadMore = () => { const newOffset = offset + limit; setOffset(newOffset); loadPokemon(newOffset); }; return { items, hasMore, isLoading, onLoadMore, }; } `; const usePokemonList = `export function usePokemonList({fetchDelay = 0} = {}) { const [items, setItems] = React.useState([]); const [hasMore, setHasMore] = React.useState(true); const [isLoading, setIsLoading] = React.useState(false); const [offset, setOffset] = React.useState(0); const limit = 10; // Number of items per page, adjust as necessary const loadPokemon = async (currentOffset) => { const controller = new AbortController(); const {signal} = controller; try { setIsLoading(true); if (offset > 0) { // Delay to simulate network latency await new Promise((resolve) => setTimeout(resolve, fetchDelay)); } let res = await fetch( \`https://pokeapi.co/api/v2/pokemon?offset=\${currentOffset}&limit=\${limit}\`, {signal}, ); if (!res.ok) { throw new Error("Network response was not ok"); } let json = await res.json(); setHasMore(json.next !== null); // Append new results to existing ones setItems((prevItems) => [...prevItems, ...json.results]); } catch (error) { if (error.name === "AbortError") { console.log("Fetch aborted"); } else { console.error("There was an error with the fetch operation:", error); } } finally { setIsLoading(false); } }; React.useEffect(() => { loadPokemon(offset); }, []); const onLoadMore = () => { const newOffset = offset + limit; setOffset(newOffset); loadPokemon(newOffset); }; return { items, hasMore, isLoading, onLoadMore, }; };`; const App = `import {Select, SelectItem} from "@nextui-org/react"; import {useInfiniteScroll} from "@nextui-org/use-infinity-scroll"; import {usePokemonList} from "./usePokemonList"; export default function App() { const [isOpen, setIsOpen] = React.useState(false); const {items, hasMore, isLoading, onLoadMore} = usePokemonList({fetchDelay: 1500}); const [, scrollerRef] = useInfiniteScroll({ hasMore, isEnabled: isOpen, shouldUseLoader: false, // We don't want to show the loader at the bottom of the list onLoadMore, }); return ( ); }`; const react = { "/App.jsx": App, "/usePokemonList.js": usePokemonList, }; const reactTs = { "/App.tsx": App, "/usePokemonList.ts": usePokemonListTs, }; export default { ...react, ...reactTs, };