mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
* docs: optimize route higtlight (#4520) * docs: optimize home display (#4519) * docs: optimize home display and route highlight * docs: optimize home display * fix(alert): propagate className (#4535) * fix(alert): propagate className * chore(alert): remove className from alert theme * fix(avatar): title type in Avatar (#4529) * fix(avatar): title type in Avatar * fix(alert): apply isEmpty check on title * fix(alert): alert interface props type * refactor: remove unnecessary props types (#4530) * refactor(docs): remove string type as it is included in ReactNode * refactor: remove unnecessary types * feat(changeset): add changeset * chore: remove changeset * refactor: remove null since ReactNode unions it already * fix(input): use onPress for wrapper click focus (#4483) * fix(input): use onPress for wrapper click focus * test(input): wrapper click focus test * chore(changeset): input onPress for wrapper click focus * chore(changeset): minor wording * Refactor/rebrand (#4532) * chore: rebrand in progress * chore: update docs to use heroui * chore: components renbranded * chore: figma moved to the docs files * fix: posthog config * fix(docs): extra classname in form example (#4465) * chore: clean git * chore: make heroui private * chore: new logo * chore: node env var renamed * chore: public robots txt deleted * chore: wrangler installed * chore: wrangler renamed * chore: cloudlfare workers removed * chore: force vercel deploy * refactor: first migration and provider * refactor: rename nextui plugin * refactor: rename github site * refactor: rename CONTRIBUTING * refactor: rename package name * refactor: nextjs image hostname * refactor: mdx repo nextui-org rename frontio-ai * refactor: nextui.org rename heroui.com * refactor: add heroui to missing places * fix: heroui plugin name * fix: update docs * docs: nextui to heroui add npmrc pnpm migratation * chore: rename all packages with new org name * chore: replace frontio-ai by frontioai * chore: revert previous changes * chore: small adjustment * chore: doc updated * feat: blog * chore: avatar updated * fix: url * chore: add new ogimage * fix: ogimage command * fix: heroui name and storybook welcome page * fix: og image url * feat: favicon and icon changed --------- Co-authored-by: աӄա <wingkwong.code@gmail.com> Co-authored-by: winches <329487092@qq.com> * fix: postbuild script * chore: core package updates * ci(changesets): version packages (#4569) Co-authored-by: Junior Garcia <jrgarciadev@gmail.com> * feat: contributors added to the blog --------- Co-authored-by: winches <329487092@qq.com> Co-authored-by: աӄա <wingkwong.code@gmail.com> Co-authored-by: Peterl561 <76144929+Peterl561@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
114 lines
2.7 KiB
TypeScript
114 lines
2.7 KiB
TypeScript
/* eslint-disable no-console */
|
|
"use client";
|
|
|
|
import {Select, SelectItem} from "@heroui/react";
|
|
import {useEffect, useState} from "react";
|
|
import {useInfiniteScroll} from "@heroui/use-infinite-scroll";
|
|
|
|
type Pokemon = {
|
|
name: string;
|
|
url: string;
|
|
};
|
|
|
|
type UsePokemonListProps = {
|
|
/** Delay to wait before fetching more items */
|
|
fetchDelay?: number;
|
|
};
|
|
|
|
function usePokemonList({fetchDelay = 0}: UsePokemonListProps = {}) {
|
|
const [items, setItems] = useState<Pokemon[]>([]);
|
|
const [hasMore, setHasMore] = useState(true);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [offset, setOffset] = 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) {
|
|
// @ts-ignore
|
|
if (error.name === "AbortError") {
|
|
console.log("Fetch aborted");
|
|
} else {
|
|
console.error("There was an error with the fetch operation:", error);
|
|
}
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
loadPokemon(offset);
|
|
}, []);
|
|
|
|
const onLoadMore = () => {
|
|
const newOffset = offset + limit;
|
|
|
|
setOffset(newOffset);
|
|
loadPokemon(newOffset);
|
|
};
|
|
|
|
return {
|
|
items,
|
|
hasMore,
|
|
isLoading,
|
|
onLoadMore,
|
|
};
|
|
}
|
|
|
|
export default function Page() {
|
|
const [isOpen, setIsOpen] = 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 (
|
|
<div className="p-6">
|
|
<Select
|
|
className="max-w-xs"
|
|
isLoading={isLoading}
|
|
items={items}
|
|
label="Pick a Pokemon"
|
|
placeholder="Select a Pokemon"
|
|
scrollRef={scrollerRef}
|
|
selectionMode="single"
|
|
onOpenChange={setIsOpen}
|
|
>
|
|
{(item) => (
|
|
<SelectItem key={item.name} className="capitalize">
|
|
{item.name}
|
|
</SelectItem>
|
|
)}
|
|
</Select>
|
|
</div>
|
|
);
|
|
}
|