Leave Yamada UI a star

Star
Yamada UIYamada UIv1.7.2

InfiniteScrollArea

InfiniteScrollArea is a component that provides infinite scrolling functionality. This component offers a smooth scrolling experience by automatically loading and displaying the next dataset when the end of the component is reached.

Source@yamada-ui/infinite-scroll-area

Import

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

Usage

Editable example

const [count, setCount] = useState<number>(50)

return (
  <InfiniteScrollArea
    onLoad={({ index, finish }) => {
      console.log("load", index)

      setCount((prev) => prev + 50)

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

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

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

Specify the Viewport

To specify the viewport, set a ref to rootRef.

Editable example

const rootRef = useRef<HTMLDivElement>(null)
const [count, setCount] = useState<number>(50)
const resetRef = useRef<() => void>(() => {})

return (
  <VStack alignItems="flex-start" h="full">
    <Container
      ref={rootRef}
      flex="1"
      borderWidth="1px"
      rounded="md"
      p="md"
      overflowY="auto"
    >
      <InfiniteScrollArea
        rootRef={rootRef}
        resetRef={resetRef}
        onLoad={({ index, finish }) => {
          console.log("load", index)

          setCount((prev) => prev + 50)

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

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

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

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

Set rootMargin

To set rootMargin, assign a string to rootMargin.

Editable example

const [count, setCount] = useState<number>(50)

return (
  <InfiniteScrollArea
    onLoad={({ index, finish }) => {
      console.log("load", index)

      setCount((prev) => prev + 50)

      if (index >= 5) finish()
    }}
    loading={<Loading fontSize="2xl" />}
    rootMargin="300px 0px 0px 0px"
  >
    <For each={Array.from({ length: count })}>
      {(_, index) => (
        <Card key={index}>
          <CardHeader>
            <Heading size="md">俺を誰だと思っていやがるッ!!</Heading>
          </CardHeader>

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

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

Set threshold

To set threshold, assign a number to threshold.

Editable example

const [count, setCount] = useState<number>(50)

return (
  <InfiniteScrollArea
    onLoad={({ index, finish }) => {
      console.log("load", index)

      setCount((prev) => prev + 50)

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

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

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

Initial Load

To load initially, set initialLoad to true. By default, initialLoad is set to false, and the initial (index=0) onLoad is not executed.

true: The first onLoad is executed regardless of the scroll amount, and the provided index starts from 0.
false: onLoad is executed when a certain scroll is reached, and the provided index starts from 1.

Editable example

const [count, setCount] = useState<number>(0)

return (
  <InfiniteScrollArea
    initialLoad
    onLoad={async ({ index, finish }) => {
      console.log("load", index)

      await wait(1000)

      setCount((prev) => prev + 50)

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

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

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

Change the Starting index

To change the starting index, set a number to startIndex. The default is 1.

Editable example

const [count, setCount] = useState<number>(50)

return (
  <InfiniteScrollArea
    onLoad={async ({ index, finish }) => {
      console.log("load", index)

      setCount((prev) => prev + 50)

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

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

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

Change the Orientation

To change the orientation, set orientation to either vertical or horizontal. The default is vertical.

Editable example

const [count, setCount] = useState<number>(50)

return (
  <InfiniteScrollArea
    orientation="horizontal"
    h="full"
    onLoad={({ index, finish }) => {
      setCount((prev) => prev + 50)

      if (index >= 5) finish()
    }}
    loading={<Loading fontSize="2xl" />}
  >
    <For each={Array.from({ length: count })}>
      {(_, index) => (
        <Card key={index} minW="sm" h="full">
          <CardHeader>
            <Heading size="md">『天元突破グレンラガン』</Heading>
          </CardHeader>

          <CardBody>
            <Image
              src="https://www.gurren-lagann.net/tv/images/kv.jpg"
              w="full"
            />
          </CardBody>
        </Card>
      )}
    </For>
  </InfiniteScrollArea>
)
Copied!

Reverse

To reverse, set isReverse to true. The default is false.

Editable example

const rootRef = useRef<HTMLDivElement>(null)
const [count, setCount] = useState<number>(50)

return (
  <Box ref={rootRef} h="full" overflow="auto">
    <InfiniteScrollArea
      onLoad={({ index, finish }) => {
        console.log("load", index)

        setCount((prev) => prev + 50)

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

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

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

Disable

To disable, set isDisabled to true. This is useful when you do not want to execute onLoad in response to scrolling under certain conditions.

Editable example

const [isDisabled, setIsDisabled] = useState<boolean>(false)
const [count, setCount] = useState<number>(50)

return (
  <VStack alignItems="flex-start" h="full">
    <InfiniteScrollArea
      flex="1"
      borderWidth="1px"
      rounded="md"
      p="md"
      overflowY="auto"
      onLoad={async ({ index, finish }) => {
        console.log("load", index)

        setCount((prev) => prev + 50)

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

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

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

    <Button
      colorScheme={isDisabled ? "success" : "danger"}
      onClick={() => setIsDisabled((prev) => !prev)}
    >
      {isDisabled ? "Enable" : "Disabled"}
    </Button>
  </VStack>
)
Copied!

Reset

To reset the index, set a ref to resetRef. A callback function is attached to the set ref, so execute it.

Editable example

const resetRef = useRef<() => void>(() => {})
const [count, setCount] = useState<number>(50)

return (
  <VStack alignItems="flex-start" h="full">
    <InfiniteScrollArea
      flex="1"
      borderWidth="1px"
      rounded="md"
      p="md"
      overflowY="auto"
      onLoad={async ({ index, finish }) => {
        console.log("load", index)

        setCount((prev) => prev + 50)

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

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

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

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

Display an Element at the End of the Scroll

To display an element at the end of the scroll, set a ReactNode to finish.

Editable example

const [count, setCount] = useState<number>(50)

return (
  <InfiniteScrollArea
    onLoad={({ index, finish }) => {
      console.log("load", index)

      setCount((prev) => prev + 50)

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

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

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

Customize the Trigger

To customize the trigger, set props to triggerProps.

Editable example

const [count, setCount] = useState<number>(50)

return (
  <InfiniteScrollArea
    onLoad={async ({ index, finish }) => {
      console.log("load", index)

      await wait(5000)

      setCount((prev) => prev + 50)

      if (index >= 5) finish()
    }}
    loading={<Loading fontSize="2xl" />}
    triggerProps={{ bg: "primary.50", p: "md", rounded: "md" }}
  >
    <For each={Array.from({ length: count })}>
      {(_, index) => (
        <Card key={index}>
          <CardHeader>
            <Heading size="md">俺を誰だと思っていやがるッ!!</Heading>
          </CardHeader>

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

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

Customize the Loading

To customize the loading, set a ReactNode to loading.

Editable example

const [count, setCount] = useState<number>(50)

return (
  <InfiniteScrollArea
    onLoad={async ({ index, finish }) => {
      console.log("load", index)

      await wait(5000)

      setCount((prev) => prev + 50)

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

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

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

Edit this page on GitHub

PreviousScrollAreaNextColorSwatch