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

# Once Props

Một số dữ liệu hiếm khi thay đổi, tốn chi phí tính toán hoặc đơn giản là rất lớn. Thay vì đưa dữ liệu đó vào mọi response, bạn có thể dùng once props. Các prop này được client ghi nhớ và tái sử dụng ở những page sau có cùng prop. Điều này đặc biệt phù hợp cho [shared data](/v3/data-props/shared-data).

## Tạo once props

Để tạo once prop, dùng method `Inertia::once()` khi trả response. Method nhận callback trả về dữ liệu prop.

```php theme={null}
return Inertia::render('Billing', [
    'plans' => Inertia::once(fn () => Plan::all()),
]);
```

Sau khi client nhận prop này, các request tiếp theo sẽ bỏ qua việc resolve callback và loại prop khỏi response. Client chỉ ghi nhớ once props khi điều hướng giữa các trang có chứa chúng.

Điều hướng đến trang không có once prop sẽ làm quên giá trị đã nhớ; prop sẽ được resolve lại ở trang kế tiếp có nó. Trong thực tế, đây hiếm khi là vấn đề vì once props thường được dùng làm dữ liệu dùng chung hoặc trong một khu vực cụ thể của ứng dụng.

## Buộc refresh

Bạn có thể buộc once prop refresh bằng method `fresh()`.

```php theme={null}
return Inertia::render('Billing', [
    'plans' => Inertia::once(fn () => Plan::all())->fresh(),
]);
```

Method này cũng nhận boolean, cho phép refresh prop có điều kiện.

```php theme={null}
return Inertia::render('Billing', [
    'plans' => Inertia::once(fn () => Plan::all())->fresh($condition),
]);
```

## Refresh từ client

Bạn có thể refresh once prop từ phía client bằng [partial reload](/v3/data-props/partial-reloads). Server luôn resolve once prop khi nó được yêu cầu rõ ràng.

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

  router.reload({ only: ["plans"] });
  ```

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

  router.reload({ only: ["plans"] });
  ```

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

  router.reload({ only: ["plans"] });
  ```
</CodeGroup>

## Thời gian hết hạn

Bạn có thể đặt thời gian hết hạn bằng method `until()`. Method nhận `DateTimeInterface`, `DateInterval` hoặc integer (giây). Prop sẽ được refresh trong một visit tiếp theo sau khi thời gian hết hạn đã qua.

```php theme={null}
return Inertia::render('Dashboard', [
    'rates' => Inertia::once(fn () => ExchangeRate::all())->until(now()->addDay()),
]);
```

## Custom key

Bạn có thể gán custom key cho prop bằng method `as()`. Điều này hữu ích khi muốn chia sẻ dữ liệu qua nhiều trang nhưng dùng tên prop khác nhau.

```php theme={null}
// Team member list...
return Inertia::render('Team/Index', [
    'memberRoles' => Inertia::once(fn () => Role::all())->as('roles'),
]);

// Invite form...
return Inertia::render('Team/Invite', [
    'availableRoles' => Inertia::once(fn () => Role::all())->as('roles'),
]);
```

Cả hai trang chia sẻ cùng dữ liệu bên dưới vì dùng chung custom key, vì vậy prop chỉ được resolve cho trang bạn truy cập đầu tiên.

## Chia sẻ once props

Bạn có thể chia sẻ once props toàn cục bằng method `Inertia::share()`.

```php theme={null}
Inertia::share('countries', Inertia::once(fn () => Country::all()));
```

Hoặc để thuận tiện, dùng method `shareOnce()`.

```php theme={null}
Inertia::shareOnce('countries', fn () => Country::all());
```

Bạn cũng có thể chain `as()`, `fresh()` và `until()` vào method `shareOnce`.

```php theme={null}
Inertia::shareOnce('countries', fn () => Country::all())->until(now()->addDay());
```

Ngoài ra, bạn có thể định nghĩa method `shareOnce()` chuyên biệt trong middleware. Middleware sẽ evaluate cả `share()` và `shareOnce()`, sau đó merge kết quả.

```php theme={null}
class HandleInertiaRequests extends Middleware
{
    public function shareOnce(Request $request): array
    {
        return array_merge(parent::shareOnce($request), [
            'countries' => fn () => Country::all(),
        ]);
    }
}
```

## Once props có điều kiện

Một số shared data hầu như ổn định nhưng thay đổi ở thời điểm cụ thể, chẳng hạn authenticated user. Bạn có thể trả once prop khi user đã đăng nhập và `null` nếu chưa. Đăng nhập và đăng xuất thường kết thúc bằng redirect tới page không yêu cầu rõ prop `auth`, nên once value đã nhớ có thể bị stale.

Trả `null` ở request khi đã đăng xuất sẽ ghi đè user đã nhớ trong mọi response, còn trả once prop khi đã xác thực cho phép client ghi nhớ user qua các visit.

```php theme={null}
class HandleInertiaRequests extends Middleware
{
    public function share(Request $request): array
    {
        return [
            ...parent::share($request),
            'auth' => $request->user()
                ? Inertia::once(fn () => $request->user())
                : null,
        ];
    }
}
```

## Prefetch

Once props tương thích với [prefetching](/v3/data-props/prefetching). Client tự động đưa once props đã nhớ vào prefetched response, nên khi điều hướng tới page đã prefetch, once props đã sẵn sàng.

Trang prefetch chứa once prop đã hết hạn sẽ bị invalid khỏi cache.

## Kết hợp với loại prop khác

Modifier `once()` có thể nối vào [deferred](/v3/data-props/deferred-props), [merge](/v3/data-props/merging-props) và [optional](/v3/data-props/partial-reloads#lazy-data-evaluation) props.

```php theme={null}
return Inertia::render('Dashboard', [
    'permissions' => Inertia::defer(fn () => Permission::all())->once(),
    'activity' => Inertia::merge(fn () => $user->recentActivity())->once(),
    'categories' => Inertia::optional(fn () => Category::all())->once(),
]);
```

***

## 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 v3 chính thức](https://inertiajs.com/docs/v3/data-props/once-props). 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.
