> ## 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.

# Truy cập thủ công

<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>

Ngoài việc [tạo liên kết](/v2/the-basics/links), bạn cũng có thể chủ động thực hiện Inertia visit / request bằng JavaScript thông qua phương thức `router.visit()`.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.visit(url, {
      method: 'get',
      data: {},
      replace: false,
      preserveState: false,
      preserveScroll: false,
      only: [],
      except: [],
      headers: {},
      errorBag: null,
      forceFormData: false,
      queryStringArrayFormat: 'brackets',
      async: false,
      showProgress: true,
      fresh: false,
      reset: [],
      preserveUrl: false,
      prefetch: false,
      viewTransition: false,
      onCancelToken: cancelToken => {},
      onCancel: () => {},
      onBefore: visit => {},
      onStart: visit => {},
      onProgress: progress => {},
      onSuccess: page => {},
      onError: errors => {},
      onFinish: visit => {},
      onPrefetching: () => {},
      onPrefetched: () => {},
  })
  ```

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

  router.visit(url, {
      method: 'get',
      data: {},
      replace: false,
      preserveState: false,
      preserveScroll: false,
      only: [],
      except: [],
      headers: {},
      errorBag: null,
      forceFormData: false,
      queryStringArrayFormat: 'brackets',
      async: false,
      showProgress: true,
      fresh: false,
      reset: [],
      preserveUrl: false,
      prefetch: false,
      viewTransition: false,
      onCancelToken: cancelToken => {},
      onCancel: () => {},
      onBefore: visit => {},
      onStart: visit => {},
      onProgress: progress => {},
      onSuccess: page => {},
      onError: errors => {},
      onFinish: visit => {},
      onPrefetching: () => {},
      onPrefetched: () => {},
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.visit(url, {
      method: 'get',
      data: {},
      replace: false,
      preserveState: false,
      preserveScroll: false,
      only: [],
      except: [],
      headers: {},
      errorBag: null,
      forceFormData: false,
      queryStringArrayFormat: 'brackets',
      async: false,
      showProgress: true,
      fresh: false,
      reset: [],
      preserveUrl: false,
      prefetch: false,
      viewTransition: false,
      onCancelToken: cancelToken => {},
      onCancel: () => {},
      onBefore: visit => {},
      onStart: visit => {},
      onProgress: progress => {},
      onSuccess: page => {},
      onError: errors => {},
      onFinish: visit => {},
      onPrefetching: () => {},
      onPrefetched: () => {},
  })
  ```
</CodeGroup>

Tuy nhiên, nhìn chung sẽ thuận tiện hơn khi sử dụng một trong các phương thức request rút gọn của Inertia. Những phương thức này hỗ trợ đầy đủ các tùy chọn giống `router.visit()`.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.get(url, data, options)
  router.post(url, data, options)
  router.put(url, data, options)
  router.patch(url, data, options)
  router.delete(url, options)
  router.reload(options) // Uses the current URL
  ```

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

  router.get(url, data, options)
  router.post(url, data, options)
  router.put(url, data, options)
  router.patch(url, data, options)
  router.delete(url, options)
  router.reload(options) // Uses the current URL
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.get(url, data, options)
  router.post(url, data, options)
  router.put(url, data, options)
  router.patch(url, data, options)
  router.delete(url, options)
  router.reload(options) // Uses the current URL
  ```
</CodeGroup>

Phương thức `reload()` là cách viết tắt tiện lợi, tự động truy cập lại trang hiện tại với cả `preserveState` và `preserveScroll` đều được đặt thành `true`, vì vậy rất phù hợp khi bạn chỉ muốn tải lại dữ liệu của trang hiện tại.

## Phương thức

Khi thực hiện truy cập thủ công, bạn có thể dùng tùy chọn `method` để đặt HTTP method của request thành `get`, `post`, `put`, `patch` hoặc `delete`. Method mặc định là `get`.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.visit(url, { method: 'post' })
  ```

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

  router.visit(url, { method: 'post' })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.visit(url, { method: 'post' })
  ```
</CodeGroup>

Laravel không hỗ trợ tải file qua `put` hoặc `patch`. Thay vào đó, hãy gửi request bằng `post`, kèm field `_method` đặt thành `put` hoặc `patch`. Kỹ thuật này gọi là [form method spoofing](https://laravel.com/docs/routing#form-method-spoofing).

## Wayfinder

<Badge>v2.1.2+</Badge>

Khi sử dụng [Wayfinder](https://github.com/laravel/wayfinder), bạn có thể truyền object kết quả trực tiếp vào bất kỳ phương thức router nào. Router sẽ tự suy ra HTTP method và URL từ object Wayfinder.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'
  import { show } from 'App/Http/Controllers/UserController'

  router.visit(show(1))
  router.post(store())
  router.delete(destroy(1))
  ```

  ```js React icon="react" theme={null}
  import { router } from '@inertiajs/react'
  import { show } from 'App/Http/Controllers/UserController'

  router.visit(show(1))
  router.post(store())
  router.delete(destroy(1))
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'
  import { show } from 'App/Http/Controllers/UserController'

  router.visit(show(1))
  router.post(store())
  router.delete(destroy(1))
  ```
</CodeGroup>

Nếu vừa cung cấp object Wayfinder vừa chỉ định tùy chọn `method`, tùy chọn `method` được ưu tiên.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'
  import { update } from 'App/Http/Controllers/UserController'

  router.visit(update(1), { method: 'patch' })
  ```

  ```js React icon="react" theme={null}
  import { router } from '@inertiajs/react'
  import { update } from 'App/Http/Controllers/UserController'

  router.visit(update(1), { method: 'patch' })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'
  import { update } from 'App/Http/Controllers/UserController'

  router.visit(update(1), { method: 'patch' })
  ```
</CodeGroup>

## Dữ liệu

Bạn có thể dùng tùy chọn `data` để thêm dữ liệu vào request.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.visit('/users', {
      method: 'post',
      data: {
          name: 'John Doe',
          email: 'john.doe@example.com',
      },
  })
  ```

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

  router.visit('/users', {
      method: 'post',
      data: {
          name: 'John Doe',
          email: 'john.doe@example.com',
      },
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.visit('/users', {
      method: 'post',
      data: {
          name: 'John Doe',
          email: 'john.doe@example.com',
      },
  })
  ```
</CodeGroup>

Để thuận tiện, các phương thức `get()`, `post()`, `put()` và `patch()` đều nhận `data` làm đối số thứ hai.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.post('/users', {
      name: 'John Doe',
      email: 'john.doe@example.com',
  })
  ```

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

  router.post('/users', {
      name: 'John Doe',
      email: 'john.doe@example.com',
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.post('/users', {
      name: 'John Doe',
      email: 'john.doe@example.com',
  })
  ```
</CodeGroup>

## Header tùy chỉnh

Tùy chọn `headers` cho phép bạn thêm header tùy chỉnh vào request.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.post('/users', data, {
      headers: {
          'Custom-Header': 'value',
      },
  })
  ```

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

  router.post('/users', data, {
      headers: {
          'Custom-Header': 'value',
      },
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.post('/users', data, {
      headers: {
          'Custom-Header': 'value',
      },
  })
  ```
</CodeGroup>

Các header mà Inertia sử dụng nội bộ để truyền trạng thái của nó tới máy chủ có độ ưu tiên cao hơn và vì vậy không thể bị ghi đè.

## Tùy chọn visit toàn cục

Bạn có thể cấu hình callback `visitOptions` khi [khởi tạo ứng dụng Inertia](/v2/installation/client-side-setup#configuring-defaults) để sửa các tùy chọn visit trên toàn cục cho mọi request. Callback nhận URL đích và các tùy chọn visit hiện tại, sau đó cần trả về object chứa những tùy chọn bạn muốn ghi đè.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { createApp, h } from 'vue'
  import { createInertiaApp } from '@inertiajs/vue3'

  createInertiaApp({
      // ...
      defaults: {
          visitOptions: (href, options) => {
              return {
                  headers: {
                      ...options.headers,
                      'X-Custom-Header': 'value',
                  },
              }
          },
      },
  })
  ```

  ```jsx React icon="react" theme={null}
  import { createInertiaApp } from '@inertiajs/react'
  import { createRoot } from 'react-dom/client'

  createInertiaApp({
      // ...
      defaults: {
          visitOptions: (href, options) => {
              return {
                  headers: {
                      ...options.headers,
                      'X-Custom-Header': 'value',
                  },
              }
          },
      },
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { createInertiaApp } from '@inertiajs/svelte'

  createInertiaApp({
      // ...
      defaults: {
          visitOptions: (href, options) => {
              return {
                  headers: {
                      ...options.headers,
                      'X-Custom-Header': 'value',
                  },
              }
          },
      },
  })
  ```
</CodeGroup>

## Tải file lên

Khi thực hiện lần truy cập / request có chứa file, Inertia sẽ tự động chuyển dữ liệu request thành object `FormData`. Nếu muốn request luôn dùng object `FormData`, bạn có thể sử dụng tùy chọn `forceFormData`.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.post('/companies', data, {
      forceFormData: true,
  })
  ```

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

  router.post('/companies', data, {
      forceFormData: true,
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.post('/companies', data, {
      forceFormData: true,
  })
  ```
</CodeGroup>

Để biết thêm về tải file, hãy xem tài liệu chuyên biệt về [tải file](/v2/the-basics/file-uploads).

## Lịch sử trình duyệt

Khi thực hiện các lần truy cập, Inertia tự động thêm một entry mới vào lịch sử trình duyệt. Tuy nhiên, bạn cũng có thể thay thế entry lịch sử hiện tại bằng cách đặt tùy chọn `replace` thành `true`.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.get('/users', { search: 'John' }, { replace: true })
  ```

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

  router.get('/users', { search: 'John' }, { replace: true })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.get('/users', { search: 'John' }, { replace: true })
  ```
</CodeGroup>

Các lần truy cập đến cùng một URL sẽ tự động đặt `replace` thành `true`.

## Visit phía client

Bạn có thể dùng các phương thức `router.push` và `router.replace` để thực hiện visit hoàn toàn phía client. Các phương thức này hữu ích khi muốn cập nhật history của trình duyệt mà không gửi request đến máy chủ.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.push({
      url: '/users',
      component: 'Users',
      props: { search: 'John' },
      clearHistory: false,
      encryptHistory: false,
      preserveScroll: false,
      preserveState: false,
      errorBag: null,
      onSuccess: (page) => {},
      onError: (errors) => {},
      onFinish: (visit) => {},
  })
  ```

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

  router.push({
      url: '/users',
      component: 'Users',
      props: { search: 'John' },
      clearHistory: false,
      encryptHistory: false,
      preserveScroll: false,
      preserveState: false,
      errorBag: null,
      onSuccess: (page) => {},
      onError: (errors) => {},
      onFinish: (visit) => {},
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.push({
      url: '/users',
      component: 'Users',
      props: { search: 'John' },
      clearHistory: false,
      encryptHistory: false,
      preserveScroll: false,
      preserveState: false,
      errorBag: null,
      onSuccess: (page) => {},
      onError: (errors) => {},
      onFinish: (visit) => {},
  })
  ```
</CodeGroup>

Mọi tham số đều là tùy chọn. Mặc định, tất cả tham số được truyền vào (trừ `errorBag`) sẽ được merge với trang hiện tại. Điều này có nghĩa bạn chịu trách nhiệm ghi đè URL, component và props của trang hiện tại khi cần.

Nếu cần truy cập props của trang hiện tại, bạn có thể truyền một function vào tùy chọn `props`. Function này nhận props hiện tại (bao gồm mọi [once props](/v2/data-props/once-props)) và cần trả về props mới.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.push({ url: '/users', component: 'Users' })

  router.replace({
      props: (currentProps) => ({ ...currentProps, search: 'John' })
  })
  ```

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

  router.push({ url: '/users', component: 'Users' })

  router.replace({
      props: (currentProps) => ({ ...currentProps, search: 'John' })
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.push({ url: '/users', component: 'Users' })

  router.replace({
      props: (currentProps) => ({ ...currentProps, search: 'John' })
  })
  ```
</CodeGroup>

Function cũng nhận [once props](/v2/data-props/once-props) làm đối số thứ hai. Điều này hữu ích khi bạn muốn thay thế toàn bộ props thông thường nhưng vẫn giữ once props.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.replace({
      props: (currentProps, onceProps) => ({ ...onceProps, search: 'John' })
  })
  ```

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

  router.replace({
      props: (currentProps, onceProps) => ({ ...onceProps, search: 'John' })
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.replace({
      props: (currentProps, onceProps) => ({ ...onceProps, search: 'John' })
  })
  ```
</CodeGroup>

Tùy chọn `errorBag` cho phép chỉ định error bag dùng khi xử lý lỗi validation trong callback `onError`.

Hãy đảm bảo mọi route bạn push ở phía client cũng được định nghĩa ở phía máy chủ. Nếu người dùng refresh trang, máy chủ cần biết cách render trang đó.

<Warning>
  Một số trình duyệt giới hạn số lần gọi `history.pushState()` và `history.replaceState()` trong một khoảng thời gian ngắn. Inertia bắt lỗi này và ghi vào console, nhưng việc cập nhật state sẽ bị mất. Hãy tránh gọi `router.push()` hoặc `router.replace()` quá thường xuyên, đồng thời cân nhắc debounce hoặc batch các update trong tình huống tần suất cao.
</Warning>

### Prop helper

Inertia cung cấp ba phương thức helper để cập nhật page props mà không gửi request đến máy chủ. Đây là các cách viết tắt của `router.replace()` và tự động đặt `preserveScroll` cùng `preserveState` thành `true`.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  // Replace a prop value...
  router.replaceProp('user.name', 'Jane Smith')

  // Append to an array prop...
  router.appendToProp('messages', { id: 4, text: 'New message' })

  // Prepend to an array prop...
  router.prependToProp('tags', 'urgent')
  ```

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

  // Replace a prop value...
  router.replaceProp('user.name', 'Jane Smith')

  // Append to an array prop...
  router.appendToProp('messages', { id: 4, text: 'New message' })

  // Prepend to an array prop...
  router.prependToProp('tags', 'urgent')
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  // Replace a prop value...
  router.replaceProp('user.name', 'Jane Smith')

  // Append to an array prop...
  router.appendToProp('messages', { id: 4, text: 'New message' })

  // Prepend to an array prop...
  router.prependToProp('tags', 'urgent')
  ```
</CodeGroup>

Cả ba phương thức đều hỗ trợ dot notation cho prop lồng nhau và có thể nhận callback function, trong đó đối số đầu tiên là giá trị hiện tại và đối số thứ hai là props của trang hiện tại.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.prependToProp('notifications', (current, props) => {
      return {
          id: Date.now(),
          message: `Hello ${props.user.name}`,
      }
  })
  ```

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

  router.prependToProp('notifications', (current, props) => {
      return {
          id: Date.now(),
          message: `Hello ${props.user.name}`,
      }
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.prependToProp('notifications', (current, props) => {
      return {
          id: Date.now(),
          message: `Hello ${props.user.name}`,
      }
  })
  ```
</CodeGroup>

## Giữ lại state

Mặc định, các lần truy cập lại cùng một trang sẽ tạo một instance page component mới. Điều này khiến các state cục bộ như input của form, vị trí cuộn và trạng thái focus bị mất.

Tuy nhiên, trong một số tình huống, cần giữ lại state của page component. Ví dụ, khi submit form, bạn cần giữ dữ liệu form nếu validation form thất bại ở phía máy chủ.

Vì lý do này, các phương thức `post`, `put`, `patch`, `delete` và `reload` đều đặt tùy chọn `preserveState` thành `true` theo mặc định.

Bạn có thể yêu cầu Inertia giữ state của component khi sử dụng phương thức `get` bằng cách đặt tùy chọn `preserveState` thành `true`.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.get('/users', { search: 'John' }, { preserveState: true })
  ```

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

  router.get('/users', { search: 'John' }, { preserveState: true })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.get('/users', { search: 'John' }, { preserveState: true })
  ```
</CodeGroup>

Nếu chỉ muốn giữ state khi response có chứa lỗi validation, hãy đặt tùy chọn `preserveState` thành "errors".

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.get('/users', { search: 'John' }, { preserveState: 'errors' })
  ```

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

  router.get('/users', { search: 'John' }, { preserveState: 'errors' })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.get('/users', { search: 'John' }, { preserveState: 'errors' })
  ```
</CodeGroup>

Bạn cũng có thể đánh giá trì hoãn tùy chọn `preserveState` dựa trên response bằng cách cung cấp một callback.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.post('/users', data, {
      preserveState: (page) => page.props.someProp === 'value',
  })
  ```

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

  router.post('/users', data, {
      preserveState: (page) => page.props.someProp === 'value',
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.post('/users', data, {
      preserveState: (page) => page.props.someProp === 'value',
  })
  ```
</CodeGroup>

## Giữ vị trí cuộn

Khi điều hướng giữa các trang, Inertia mô phỏng hành vi mặc định của trình duyệt bằng cách tự động đưa vị trí cuộn của document body (cũng như mọi [vùng cuộn](/v2/advanced/scroll-management#scroll-regions) đã định nghĩa) trở lại đầu trang.

Bạn có thể tắt hành vi này bằng cách đặt tùy chọn `preserveScroll` thành `true`.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.visit(url, { preserveScroll: true })
  ```

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

  router.visit(url, { preserveScroll: true })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.visit(url, { preserveScroll: true })
  ```
</CodeGroup>

Nếu chỉ muốn giữ vị trí cuộn khi response có lỗi validation, hãy đặt tùy chọn `preserveScroll` thành "errors".

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.visit(url, { preserveScroll: 'errors' })
  ```

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

  router.visit(url, { preserveScroll: 'errors' })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.visit(url, { preserveScroll: 'errors' })
  ```
</CodeGroup>

Bạn cũng có thể đánh giá trì hoãn tùy chọn `preserveScroll` dựa trên response bằng cách cung cấp một callback.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.post('/users', data, {
      preserveScroll: (page) => page.props.someProp === 'value',
  })
  ```

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

  router.post('/users', data, {
      preserveScroll: (page) => page.props.someProp === 'value',
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.post('/users', data, {
      preserveScroll: (page) => page.props.someProp === 'value',
  })
  ```
</CodeGroup>

Để biết thêm về tính năng này, hãy xem tài liệu [quản lý cuộn](/v2/advanced/scroll-management).

## Tải lại một phần

Tùy chọn `only` cho phép bạn chỉ yêu cầu một tập con props (dữ liệu) từ máy chủ trong các lần truy cập tiếp theo đến cùng một trang, qua đó giúp ứng dụng hiệu quả hơn vì không cần truy xuất dữ liệu mà trang không có nhu cầu làm mới.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.get('/users', { search: 'John' }, { only: ['users'] })
  ```

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

  router.get('/users', { search: 'John' }, { only: ['users'] })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.get('/users', { search: 'John' }, { only: ['users'] })
  ```
</CodeGroup>

Để biết thêm về tính năng này, hãy xem tài liệu [partial reload](/v2/data-props/partial-reloads).

## View Transition

Bạn có thể bật [View transition](/v2/the-basics/view-transitions) cho một visit bằng cách đặt tùy chọn `viewTransition` thành `true`. Khi đó Inertia sử dụng View Transitions API của trình duyệt để tạo hiệu ứng chuyển trang.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.visit('/another-page', { viewTransition: true })
  ```

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

  router.visit('/another-page', { viewTransition: true })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.visit('/another-page', { viewTransition: true })
  ```
</CodeGroup>

## Hủy lần truy cập

Bạn có thể hủy một lần truy cập bằng cancel token mà Inertia tự động tạo và cung cấp thông qua callback `onCancelToken()` trước khi thực hiện truy cập.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.post('/users', data, {
      onCancelToken: (cancelToken) => (this.cancelToken = cancelToken),
  })

  // Cancel the visit...
  this.cancelToken.cancel()
  ```

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

  router.post('/users', data, {
      onCancelToken: (cancelToken) => (this.cancelToken = cancelToken),
  })

  // Cancel the visit...
  this.cancelToken.cancel()
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.post('/users', data, {
      onCancelToken: (cancelToken) => (this.cancelToken = cancelToken),
  })

  // Cancel the visit...
  this.cancelToken.cancel()
  ```
</CodeGroup>

Các callback sự kiện `onCancel()` và `onFinish()` sẽ được thực thi khi một lần truy cập bị hủy.

## Callback sự kiện

Ngoài [sự kiện toàn cục](/v2/advanced/events) của Inertia, Inertia còn cung cấp nhiều callback sự kiện cho từng visit.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.post('/users', data, {
      onBefore: (visit) => {},
      onStart: (visit) => {},
      onProgress: (progress) => {},
      onSuccess: (page) => {},
      onError: (errors) => {},
      onCancel: () => {},
      onFinish: visit => {},
      onPrefetching: () => {},
      onPrefetched: () => {},
  })
  ```

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

  router.post('/users', data, {
      onBefore: (visit) => {},
      onStart: (visit) => {},
      onProgress: (progress) => {},
      onSuccess: (page) => {},
      onError: (errors) => {},
      onCancel: () => {},
      onFinish: visit => {},
      onPrefetching: () => {},
      onPrefetched: () => {},
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.post('/users', data, {
      onBefore: (visit) => {},
      onStart: (visit) => {},
      onProgress: (progress) => {},
      onSuccess: (page) => {},
      onError: (errors) => {},
      onCancel: () => {},
      onFinish: visit => {},
      onPrefetching: () => {},
      onPrefetched: () => {},
  })
  ```
</CodeGroup>

Trả về `false` từ callback `onBefore()` sẽ khiến lần truy cập bị hủy.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.delete(`/users/${user.id}`, {
      onBefore: () => confirm('Are you sure you want to delete this user?'),
  })
  ```

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

  router.delete(`/users/${user.id}`, {
      onBefore: () => confirm('Are you sure you want to delete this user?'),
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.delete(`/users/${user.id}`, {
      onBefore: () => confirm('Are you sure you want to delete this user?'),
  })
  ```
</CodeGroup>

Bạn cũng có thể trả về promise từ các callback `onSuccess()` và `onError()`. Khi làm vậy, sự kiện "finish" sẽ được trì hoãn cho đến khi promise được resolve.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.post(url, {
      onSuccess: () => {
          return Promise.all([
              this.firstTask(),
              this.secondTask()
          ])
      }
      onFinish: visit => {
          // Not called until firstTask() and secondTask() have finished
      },
  })
  ```

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

  router.post(url, {
      onSuccess: () => {
          return Promise.all([
              this.firstTask(),
              this.secondTask()
          ])
      }
      onFinish: visit => {
          // Not called until firstTask() and secondTask() have finished
      },
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.post(url, {
      onSuccess: () => {
          return Promise.all([
              this.firstTask(),
              this.secondTask()
          ])
      }
      onFinish: visit => {
          // Not called until firstTask() and secondTask() have finished
      },
  })
  ```
</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/the-basics/manual-visits). 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.
