> ## Documentation Index
> Fetch the complete documentation index at: https://inertiajs-vi.tuantq.online/llms.txt
> Use this file to discover all available pages before exploring further.

# Tải khi hiển thị

<Warning>Bạn đang xem tài liệu Inertia.js v2. Inertia.js v3 đã được phát hành và hiện là phiên bản mặc định. Hãy xem [hướng dẫn nâng cấp](/v3/getting-started/upgrade-guide) để bắt đầu.</Warning>

Inertia hỗ trợ lazy-load dữ liệu khi cuộn bằng Intersection Observer API. Framework cung cấp component `WhenVisible` như một cách thuận tiện để tải dữ liệu khi một phần tử xuất hiện trong viewport.

Component `WhenVisible` nhận prop `data` để chỉ định key của prop cần tải. Component cũng nhận prop `fallback` để chỉ định component được render trong lúc dữ liệu đang tải. `WhenVisible` nên bao bọc component phụ thuộc vào dữ liệu đó.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  <script setup>
  import { WhenVisible } from '@inertiajs/vue3'
  </script>

  <template>
      <WhenVisible data="permissions">
          <template #fallback>
              <div>Loading...</div>
          </template>

          <div v-for="permission in permissions">
              <!-- ... -->
          </div>
      </WhenVisible>
  </template>
  ```

  ```jsx React icon="react" theme={null}
  import { WhenVisible } from '@inertiajs/react'

  export default () => (
      <WhenVisible data="permissions" fallback={() => <div>Loading...</div>}>
          <PermissionsChildComponent />
      </WhenVisible>
  )
  ```

  ```svelte Svelte 4 icon="s" theme={null}
  <script>
      import { WhenVisible } from '@inertiajs/svelte'

      export let permissions
  </script>

  <WhenVisible data="permissions">
      <svelte:fragment slot="fallback">
          <div>Loading...</div>
      </svelte:fragment>

      {#each permissions as permission}
          <!-- ... -->
      {/each}
  </WhenVisible>
  ```

  ```svelte Svelte 5 icon="s" theme={null}
  <script>
      import { WhenVisible } from '@inertiajs/svelte'

      let { permissions } = $props()
  </script>

  <WhenVisible data="permissions">
      {#snippet fallback()}
          <div>Loading...</div>
      {/snippet}

      {#each permissions as permission}
          <!-- ... -->
      {/each}
  </WhenVisible>
  ```
</CodeGroup>

Nếu muốn tải nhiều prop khi một phần tử trở nên hiển thị, bạn có thể truyền một mảng vào prop `data`.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  <script setup>
  import { WhenVisible } from '@inertiajs/vue3'
  </script>

  <template>
      <WhenVisible :data="['teams', 'users']">
          <template #fallback>
              <div>Loading...</div>
          </template>

          <!-- Props are now loaded -->
      </WhenVisible>
  </template>
  ```

  ```jsx React icon="react" theme={null}
  import { WhenVisible } from '@inertiajs/react'

  export default () => (
      <WhenVisible data={['teams', 'users']} fallback={() => <div>Loading...</div>}>
          <ChildComponent />
      </WhenVisible>
  )
  ```

  ```svelte Svelte 4 icon="s" theme={null}
  <script>
      import { WhenVisible } from '@inertiajs/svelte'

      export let teams
      export let users
  </script>

  <WhenVisible data={['teams', 'users']}>
      <svelte:fragment slot="fallback">
          <div>Loading...</div>
      </svelte:fragment>

      <!-- Props are now loaded -->
  </WhenVisible>
  ```

  ```svelte Svelte 5 icon="s" theme={null}
  <script>
      import { WhenVisible } from '@inertiajs/svelte'

      let { teams, users } = $props()
  </script>

  <WhenVisible data={['teams', 'users']}>
      {#snippet fallback()}
          <div>Loading...</div>
      {/snippet}

      <!-- Props are now loaded -->
  </WhenVisible>
  ```
</CodeGroup>

## Tải trước khi phần tử hiển thị

Nếu muốn bắt đầu tải dữ liệu trước khi phần tử thực sự hiển thị, bạn có thể truyền giá trị cho prop `buffer`. Giá trị buffer là số pixel tính từ thời điểm trước khi phần tử đi vào viewport.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  <script setup>
  import { WhenVisible } from '@inertiajs/vue3'
  </script>

  <template>
      <WhenVisible data="permissions" :buffer="500">
          <template #fallback>
              <div>Loading...</div>
          </template>

          <div v-for="permission in permissions">
              <!-- ... -->
          </div>
      </WhenVisible>
  </template>
  ```

  ```jsx React icon="react" theme={null}
  import { WhenVisible } from '@inertiajs/react'

  export default () => (
      <WhenVisible data="permissions" buffer={500} fallback={() => <div>Loading...</div>}>
          <PermissionsChildComponent />
      </WhenVisible>
  )
  ```

  ```svelte Svelte 4 icon="s" theme={null}
  <script>
      import { WhenVisible } from '@inertiajs/svelte'

      export let permissions
  </script>

  <WhenVisible data="permissions" buffer={500}>
      <svelte:fragment slot="fallback">
          <div>Loading...</div>
      </svelte:fragment>

      {#each permissions as permission}
          <!-- ... -->
      {/each}
  </WhenVisible>
  ```

  ```svelte Svelte 5 icon="s" theme={null}
  <script>
      import { WhenVisible } from '@inertiajs/svelte'

      let { permissions } = $props()
  </script>

  <WhenVisible data="permissions" buffer={500}>
      {#snippet fallback()}
          <div>Loading...</div>
      {/snippet}

      {#each permissions as permission}
          <!-- ... -->
      {/each}
  </WhenVisible>
  ```
</CodeGroup>

Trong ví dụ trên, dữ liệu sẽ bắt đầu được tải khi phần tử còn cách thời điểm hiển thị 500 pixel.

Mặc định, component `WhenVisible` bao bọc fallback template bằng phần tử `div` để có thể xác định phần tử có hiển thị trong viewport hay không. Nếu muốn tùy chỉnh phần tử bao bọc, hãy truyền prop `as`.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  <script setup>
  import { WhenVisible } from '@inertiajs/vue3'
  </script>

  <template>
      <WhenVisible data="products" as="span">
          <!-- ... -->
      </WhenVisible>
  </template>
  ```

  ```jsx React icon="react" theme={null}
  import { WhenVisible } from '@inertiajs/react'

  export default () => (
      <WhenVisible data="products" as="span">
          <ProductsChildComponent />
      </WhenVisible>
  )
  ```

  ```svelte Svelte 4 icon="s" theme={null}
  <script>
      import { WhenVisible } from '@inertiajs/svelte'

      export let products
  </script>

  <WhenVisible data="products" as="span">
      <!-- ... -->
  </WhenVisible>
  ```

  ```svelte Svelte 5 icon="s" theme={null}
  <script>
      import { WhenVisible } from '@inertiajs/svelte'

      let { products } = $props()
  </script>

  <WhenVisible data="products" as="span">
      <!-- ... -->
  </WhenVisible>
  ```
</CodeGroup>

## Luôn kích hoạt

Mặc định, component `WhenVisible` chỉ kích hoạt một lần khi phần tử xuất hiện. Nếu muốn luôn kích hoạt việc tải dữ liệu mỗi khi phần tử hiển thị, bạn có thể truyền prop `always`.

Điều này hữu ích khi bạn muốn tải dữ liệu mỗi lần phần tử xuất hiện, chẳng hạn phần tử nằm cuối danh sách infinite scroll và bạn muốn tải thêm dữ liệu. Ngoài ra, bạn có thể dùng component [Infinite scroll](/v2/data-props/infinite-scroll), vốn đã xử lý sẵn trường hợp này.

Lưu ý rằng nếu request tải dữ liệu vẫn đang được xử lý, component sẽ đợi request đó hoàn tất rồi mới bắt đầu request tiếp theo nếu phần tử vẫn còn hiển thị trong viewport.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  <script setup>
  import { WhenVisible } from '@inertiajs/vue3'
  </script>

  <template>
      <WhenVisible data="products" always>
          <!-- ... -->
      </WhenVisible>
  </template>
  ```

  ```jsx React icon="react" theme={null}
  import { WhenVisible } from '@inertiajs/react'

  export default () => (
      <WhenVisible data="products" always>
          <ProductsChildComponent />
      </WhenVisible>
  )
  ```

  ```svelte Svelte 4 icon="s" theme={null}
  <script>
      import { WhenVisible } from '@inertiajs/svelte'

      export let products
  </script>

  <WhenVisible data="products" always>
      <!-- ... -->
  </WhenVisible>
  ```

  ```svelte Svelte 5 icon="s" theme={null}
  <script>
      import { WhenVisible } from '@inertiajs/svelte'

      let { products } = $props()
  </script>

  <WhenVisible data="products" always>
      <!-- ... -->
  </WhenVisible>
  ```
</CodeGroup>

### Trạng thái fetching

Component `WhenVisible` cung cấp slot prop `fetching` để bạn hiển thị chỉ báo đang tải trong các request tiếp theo. Điều này hữu ích vì `fallback` chỉ được hiển thị ở lần tải đầu tiên, còn `fetching` cho phép cho biết dữ liệu đang được làm mới ở những lần tải sau.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  <script setup>
  import { WhenVisible } from '@inertiajs/vue3'
  </script>

  <template>
      <WhenVisible data="permissions" always>
          <template #default="{ fetching }">
              <PermissionsChildComponent />
              <div v-if="fetching">Refreshing...</div>
          </template>

          <template #fallback>
              <div>Loading...</div>
          </template>
      </WhenVisible>
  </template>
  ```

  ```jsx React icon="react" theme={null}
  import { WhenVisible } from '@inertiajs/react'

  export default () => (
      <WhenVisible data="permissions" always fallback={() => <div>Loading...</div>}>
          {({ fetching }) => (
              <>
                  <PermissionsChildComponent />
                  {fetching && <div>Refreshing...</div>}
              </>
          )}
      </WhenVisible>
  )
  ```

  ```svelte Svelte 4 icon="s" theme={null}
  <script>
      import { WhenVisible } from '@inertiajs/svelte'

      export let permissions
  </script>

  <WhenVisible data="permissions" always let:fetching>
      <PermissionsChildComponent />
      {#if fetching}
          <div>Refreshing...</div>
      {/if}

      <svelte:fragment slot="fallback">
          <div>Loading...</div>
      </svelte:fragment>
  </WhenVisible>
  ```

  ```svelte Svelte 5 icon="s" theme={null}
  <script>
      import { WhenVisible } from '@inertiajs/svelte'

      let { permissions } = $props()
  </script>

  <WhenVisible data="permissions" always let:fetching>
      <PermissionsChildComponent />
      {#if fetching}
          <div>Refreshing...</div>
      {/if}

      {#snippet fallback()}
          <div>Loading...</div>
      {/snippet}
  </WhenVisible>
  ```
</CodeGroup>

## Gửi form

Khi gửi form, bạn có thể muốn dùng tùy chọn `except` để loại trừ các prop đang được component `WhenVisible` sử dụng. Cách này tránh việc các prop bị tải lại khi bạn được redirect trở về trang hiện tại do lỗi validation.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  <script setup>
  import { useForm, WhenVisible } from '@inertiajs/vue3'

  const form = useForm({
      name: '',
      email: '',
  })

  function submit() {
      form.post('/users', {
          except: ['permissions'],
      })
  }
  </script>

  <template>
      <form @submit.prevent="submit">
          <!-- ... -->
      </form>

      <WhenVisible data="permissions">
          <!-- ... -->
      </WhenVisible>
  </template>
  ```

  ```jsx React icon="react" theme={null}
  import { useForm, WhenVisible } from '@inertiajs/react'

  export default function CreateUser() {
      const { data, setData, post } = useForm({
          name: '',
          email: '',
      })

      function submit(e) {
          e.preventDefault()
          post('/users', {
              except: ['permissions'],
          })
      }

      return (
          <>
              <form onSubmit={submit}>
                  {/* ... */}
              </form>

              <WhenVisible data="permissions">
                  {/* ... */}
              </WhenVisible>
          </>
      )
  }
  ```

  ```svelte Svelte 4 icon="s" theme={null}
  <script>
      import { useForm, WhenVisible } from '@inertiajs/svelte'

      const form = useForm({
          name: '',
          email: '',
      })

      function submit() {
          $form.post('/users', {
              except: ['permissions'],
          })
      }
  </script>

  <form on:submit|preventDefault={submit}>
      <!-- ... -->
  </form>

  <WhenVisible data="permissions">
      <!-- ... -->
  </WhenVisible>
  ```

  ```svelte Svelte 5 icon="s" theme={null}
  <script>
      import { useForm, WhenVisible } from '@inertiajs/svelte'

      const form = useForm({
          name: '',
          email: '',
      })

      function submit() {
          form.post('/users', {
              except: ['permissions'],
          })
      }
  </script>

  <form onsubmit={submit}>
      <!-- ... -->
  </form>

  <WhenVisible data="permissions">
      <!-- ... -->
  </WhenVisible>
  ```
</CodeGroup>

***

## Tài liệu chính thức

Bài dịch này được đối chiếu từ [tài liệu Inertia.js v2 chính thức](https://inertiajs.com/docs/v2/data-props/load-when-visible). Nếu có khác biệt do phiên bản hoặc cập nhật mới, hãy ưu tiên tài liệu chính thức làm nguồn tham chiếu.
