Yamada UIにスターをあげる

スター
Yamada UIYamada UIv1.7.2

useInfiniteScroll

useInfiniteScrollは、無限スクロール機能を提供するカスタムフックです。

ソース@yamada-ui/use-infinite-scroll

インポート

import { useInfiniteScroll } from "@yamada-ui/react"
Copied!

使い方

編集可能な例

const [count, setCount] = useState<number>(50)
const { ref, isFinish } = useInfiniteScroll({
  onLoad: ({ index, finish }) => {
    console.log("onLoad", index)

    setCount((prev) => prev + 50)

    if (index >= 5) finish()
  },
})

return (
  <VStack>
    <For each={Array.from({ length: count })}>
      {(_, index) => (
        <Card key={index}>
          <CardHeader>
            <Heading size="md">俺を誰だと思っていやがるッ!!</Heading>
          </CardHeader>

          <CardBody>
            <Text>
              『天元突破グレンラガン』は、ガイナックス・アニプレックス・コナミデジタルエンタテインメント製作の日本のロボットアニメ作品。
            </Text>

            <Text>
              作品名の「天元」とは、万物生育の根源という意味があり、また囲碁の用語では碁盤の中央(中心)を指す。劇中のキーワードにも螺旋、ドリル、回転など、中央・中心に関連するものが多く見られ、中央突破、王道路線を念頭に置いた作品名といえる。
            </Text>
          </CardBody>
        </Card>
      )}
    </For>

    {!isFinish ? (
      <Center ref={ref} w="full">
        <Loading fontSize="2xl" />
      </Center>
    ) : null}
  </VStack>
)
Copied!

ビューポートを指定する

ビューポートを指定する場合は、rootRefrefを設定します。

編集可能な例

const rootRef = useRef<HTMLDivElement>(null)
const resetRef = useRef<() => void>(() => {})
const [count, setCount] = useState<number>(50)
const { ref, isFinish } = useInfiniteScroll({
  onLoad: ({ index, finish }) => {
    console.log("onLoad", index)

    setCount((prev) => prev + 50)

    if (index >= 5) finish()
  },
  rootRef,
  resetRef,
})

return (
  <VStack alignItems="flex-start" h="full">
    <Container
      ref={rootRef}
      flex="1"
      borderWidth="1px"
      rounded="md"
      p="md"
      overflowY="auto"
    >
      <For each={Array.from({ length: count })}>
        {(_, index) => (
          <Card key={index}>
            <CardHeader>
              <Heading size="md">俺を誰だと思っていやがるッ!!</Heading>
            </CardHeader>

            <CardBody>
              <Text>
                『天元突破グレンラガン』は、ガイナックス・アニプレックス・コナミデジタルエンタテインメント製作の日本のロボットアニメ作品。
              </Text>

              <Text>
                作品名の「天元」とは、万物生育の根源という意味があり、また囲碁の用語では碁盤の中央(中心)を指す。劇中のキーワードにも螺旋、ドリル、回転など、中央・中心に関連するものが多く見られ、中央突破、王道路線を念頭に置いた作品名といえる。
              </Text>
            </CardBody>
          </Card>
        )}
      </For>

      {!isFinish ? (
        <Center ref={ref} w="full">
          <Loading fontSize="2xl" />
        </Center>
      ) : null}
    </Container>

    <Button onClick={() => resetRef.current()}>Reset</Button>
  </VStack>
)
Copied!

rootMarginを設定する

rootMarginを設定する場合は、rootMarginに文字列を設定します。

編集可能な例

const [count, setCount] = useState<number>(50)
const { ref, isFinish } = useInfiniteScroll({
  onLoad: ({ index, finish }) => {
    console.log("onLoad", index)

    setCount((prev) => prev + 50)

    if (index >= 5) finish()
  },
  rootMargin: "300px 0px 0px 0px",
})

return (
  <VStack>
    <For each={Array.from({ length: count })}>
      {(_, index) => (
        <Card key={index}>
          <CardHeader>
            <Heading size="md">俺を誰だと思っていやがるッ!!</Heading>
          </CardHeader>

          <CardBody>
            <Text>
              『天元突破グレンラガン』は、ガイナックス・アニプレックス・コナミデジタルエンタテインメント製作の日本のロボットアニメ作品。
            </Text>

            <Text>
              作品名の「天元」とは、万物生育の根源という意味があり、また囲碁の用語では碁盤の中央(中心)を指す。劇中のキーワードにも螺旋、ドリル、回転など、中央・中心に関連するものが多く見られ、中央突破、王道路線を念頭に置いた作品名といえる。
            </Text>
          </CardBody>
        </Card>
      )}
    </For>

    {!isFinish ? (
      <Center ref={ref} w="full">
        <Loading fontSize="2xl" />
      </Center>
    ) : null}
  </VStack>
)
Copied!

thresholdを設定する

thresholdを設定する場合は、thresholdに数値を設定します。

編集可能な例

const [count, setCount] = useState<number>(50)
const { ref, isFinish } = useInfiniteScroll({
  onLoad: ({ index, finish }) => {
    console.log("onLoad", index)

    setCount((prev) => prev + 50)

    if (index >= 5) finish()
  },
  threshold: 1,
})

return (
  <VStack>
    <For each={Array.from({ length: count })}>
      {(_, index) => (
        <Card key={index}>
          <CardHeader>
            <Heading size="md">俺を誰だと思っていやがるッ!!</Heading>
          </CardHeader>

          <CardBody>
            <Text>
              『天元突破グレンラガン』は、ガイナックス・アニプレックス・コナミデジタルエンタテインメント製作の日本のロボットアニメ作品。
            </Text>

            <Text>
              作品名の「天元」とは、万物生育の根源という意味があり、また囲碁の用語では碁盤の中央(中心)を指す。劇中のキーワードにも螺旋、ドリル、回転など、中央・中心に関連するものが多く見られ、中央突破、王道路線を念頭に置いた作品名といえる。
            </Text>
          </CardBody>
        </Card>
      )}
    </For>

    {!isFinish ? (
      <Center ref={ref} w="full">
        <Loading fontSize="2xl" />
      </Center>
    ) : null}
  </VStack>
)
Copied!

初回に読み込む

初回に読み込む場合は、initialLoadtrueに設定します。デフォルトでは、initialLoadfalseに設定されており、初回(index=0)のonLoadは実行されません。

true: スクロール量に関わらず、初回のonLoadは実行され、提供されるindex0から始まります。
false: スクロールが一定に達するとonLoadが実行され、提供されるindex1から始まります。

編集可能な例

const [count, setCount] = useState<number>(0)
const { ref, isFinish } = useInfiniteScroll({
  onLoad: ({ index, finish }) => {
    console.log("onLoad", index)

    setCount((prev) => prev + 50)

    if (index >= 5) finish()
  },
  initialLoad: true,
})

return (
  <VStack>
    <For each={Array.from({ length: count })}>
      {(_, index) => (
        <Card key={index}>
          <CardHeader>
            <Heading size="md">俺を誰だと思っていやがるッ!!</Heading>
          </CardHeader>

          <CardBody>
            <Text>
              『天元突破グレンラガン』は、ガイナックス・アニプレックス・コナミデジタルエンタテインメント製作の日本のロボットアニメ作品。
            </Text>

            <Text>
              作品名の「天元」とは、万物生育の根源という意味があり、また囲碁の用語では碁盤の中央(中心)を指す。劇中のキーワードにも螺旋、ドリル、回転など、中央・中心に関連するものが多く見られ、中央突破、王道路線を念頭に置いた作品名といえる。
            </Text>
          </CardBody>
        </Card>
      )}
    </For>

    {!isFinish ? (
      <Center ref={ref} w="full">
        <Loading fontSize="2xl" />
      </Center>
    ) : null}
  </VStack>
)
Copied!

開始するindexを変更する

開始するindexを変更する場合は、startIndexに数値を設定します。デフォルトは、1です。

編集可能な例

const [count, setCount] = useState<number>(50)
const { ref, isFinish } = useInfiniteScroll({
  onLoad: async ({ index, finish }) => {
    console.log("onLoad", index)

    setCount((prev) => prev + 50)

    if (index >= 5) finish()
  },
  startIndex: 3,
})

return (
  <VStack>
    <For each={Array.from({ length: count })}>
      {(_, index) => (
        <Card key={index}>
          <CardHeader>
            <Heading size="md">俺を誰だと思っていやがるッ!!</Heading>
          </CardHeader>

          <CardBody>
            <Text>
              『天元突破グレンラガン』は、ガイナックス・アニプレックス・コナミデジタルエンタテインメント製作の日本のロボットアニメ作品。
            </Text>

            <Text>
              作品名の「天元」とは、万物生育の根源という意味があり、また囲碁の用語では碁盤の中央(中心)を指す。劇中のキーワードにも螺旋、ドリル、回転など、中央・中心に関連するものが多く見られ、中央突破、王道路線を念頭に置いた作品名といえる。
            </Text>
          </CardBody>
        </Card>
      )}
    </For>

    {!isFinish ? (
      <Center ref={ref} w="full">
        <Loading fontSize="2xl" />
      </Center>
    ) : null}
  </VStack>
)
Copied!

反転させる

反転させる場合は、isReversetrueに設定します。デフォルトは、falseです。

編集可能な例

const rootRef = useRef<HTMLDivElement>(null)
const [count, setCount] = useState<number>(50)
const { ref, isFinish } = useInfiniteScroll({
  onLoad: async ({ index, finish }) => {
    console.log("onLoad", index)

    setCount((prev) => prev + 50)

    if (index >= 5) finish()
  },
  rootRef,
  isReverse: true,
})

return (
  <VStack ref={rootRef} h="full" overflow="auto">
    {!isFinish ? (
      <Center ref={ref} w="full">
        <Loading fontSize="2xl" />
      </Center>
    ) : null}

    <For each={Array.from({ length: count })}>
      {(_, index) => (
        <Card key={index}>
          <CardHeader>
            <Heading size="md">俺を誰だと思っていやがるッ!!</Heading>
          </CardHeader>

          <CardBody>
            <Text>
              『天元突破グレンラガン』は、ガイナックス・アニプレックス・コナミデジタルエンタテインメント製作の日本のロボットアニメ作品。
            </Text>

            <Text>
              作品名の「天元」とは、万物生育の根源という意味があり、また囲碁の用語では碁盤の中央(中心)を指す。劇中のキーワードにも螺旋、ドリル、回転など、中央・中心に関連するものが多く見られ、中央突破、王道路線を念頭に置いた作品名といえる。
            </Text>
          </CardBody>
        </Card>
      )}
    </For>
  </VStack>
)
Copied!

GitHubでこのページを編集する

useIdleuseInterval