'use server' - This feature is available in the latest Canary

Canary

'use server' hanya diperlukan jika Anda menggunakan Komponen Server React atau sedang membangun library yang kompatibel dengan fitur tersebut.

'use server' menandai fungsi-fungsi sisi server yang dapat dipanggil dari kode sisi klien.


Referensi

'use server'

Tambahkan 'use server' di bagian atas fungsi async untuk menandai bahwa fungsi tersebut dapat dipanggil oleh klien. Kami menyebut fungsi-fungsi ini sebagai Aksi Server.

async function addToCart(data) {
'use server';
// ...
}

Saat memanggil Aksi Server dari klien, 'use server' akan melakukan permintaan jaringan (network request) ke server dan menyertakan salinan ter-serialisasi dari setiap argumen yang dikirim. Jika Aksi Server mengembalikan sebuah nilai, nilai tersebut akan di-serialisasi dan dikembalikan ke klien.

Daripada menandai fungsi satu per satu dengan 'use server', Anda bisa menambahkan Direktif ini di bagian paling atas file untuk menandai semua fungsi yang di ekspor dalam file tersebut sebagai Aksi Server nantinya semua fungsi yang di ekspor pada file tersebut bisa digunakan di mana saja, termasuk diimpor dalam kode klien.

Peringatan

  • Untuk mengimpor Aksi Server dari kode klien, direktif harus digunakan pada level modul.
  • Karena pemanggilan jaringan yang mendasarinya bersifat asinkron, 'use server' hanya boleh digunakan pada fungsi asinkron.
  • Selalu perlakukan argumen yang diterima Aksi Server sebagai input yang tidak terpercaya, dan pastikan semua perubahan (mutasi) telah diautorisasi. Lihat pertimbangan keamanan.
  • Aksi Server sebaiknya dipanggil dalam sebuah Transisi. Aksi Server yang diteruskan ke <form action> atau formAction akan secara otomatis dipanggil dalam sebuah transisi.
  • Aksi Server dirancang untuk melakukan mutasi yang memperbarui data di sisi server; Sehingga Aksi Server tidak disarankan untuk pengambilan data. Oleh karena itu, framework yang mengimplementasikan Aksi Server umumnya memproses satu aksi dalam satu waktu dan tidak menyediakan mekanisme untuk melakukan caching terhadap nilai yang dikembalikan.

Pertimbangan keamanan

Argumen untuk Aksi Server sepenuhnya dikendalikan oleh klien. Demi keamanan, selalu perlakukan argumen tersebut sebagai masukan yang tidak tepercaya, dan pastikan untuk memvalidasi serta menyaring argumen sesuai kebutuhan.

Dalam setiap Aksi Server, pastikan untuk memvalidasi bahwa pengguna yang sedang masuk diizinkan untuk melakukan aksi tersebut.

Dalam Pengembangan

Untuk mencegah pengiriman data sensitif dari Aksi Server, terdapat API taint eksperimental untuk mencegah nilai dan objek unik diteruskan ke kode klien.

Lihat experimental_taintUniqueValue dan experimental_taintObjectReference.

Argumen yang dapat diserialisasi dan nilai kembalian

Karena kode klien memanggil Aksi Server melalui jaringan, setiap argumen yang dikirim harus dapat diserialisasi.

Berikut adalah tipe data yang didukung untuk argumen Aksi Server:

Yang tidak didukung, antara lain:

  • Elemen React, atau JSX
  • Fungsi komponen atau fungsi lainnya yang bukan Aksi Server
  • Kelas
  • Objek yang merupakan instance dari kelas apa pun (selain bawaan seperti yang telah disebutkan) atau objek dengan null prototype
  • Simbol yang tidak didaftarkan secara global, misalnya Symbol('my new symbol')

Nilai kembali yang dapat diserialisasi mengikuti aturan yang sama dengan properti yang bisa diserialisasi untuk Komponen Klien yang menjadi pembatas.

Penggunaan

Aksi Server dalam formulir

Aksi Server biasanya digunakan untuk memanggil fungsi di server yang mengubah data. Di peramban, pengguna umumnya mengirimkan perubahan data lewat elemen formulir HTML. Dengan komponen server React, React kini mendukung Aksi Server secara langsung di dalam formulir.

Contoh di bawah ini menunjukkan formulir yang meminta nama pengguna.

// App.js

async function requestUsername(formData) {
'use server';
const username = formData.get('username');
// ...
}

export default function App() {
return (
<form action={requestUsername}>
<input type="text" name="username" />
<button type="submit">Meminta</button>
</form>
);
}

Dalam contoh ini, requestUsername adalah sebuah Aksi Server yang diteruskan ke sebuah formulir <form>. Ketika pengguna mengirim formulir ini, akan ada permintaan jaringan ke fungsi server requestUsername. Saat memanggil Aksi Server lewat formulir, React akan mengirimkan FormData dari formulir sebagai argumen pertama ke Aksi Server tersebut.

Dengan meneruskan Aksi Server ke action formulir, React bisa meningkatkan fungsionalitas formulir secara progresif. Artinya, formulir tetap bisa dikirimkan meskipun bundel JavaScript belum dimuat sepenuhnya.

Menangani nilai kembali dari formulir

Dalam formulir diatas, ada kemungkinan nama pengguna yang diminta tidak tersedia. requestUsername harus memberi tahu apakah permintaan tersebut berhasil atau gagal.

Untuk memperbarui antarmuka pengguna berdasarkan hasil dari Aksi Server sambil tetap mendukung peningkatan progresif gunakan useActionState.

// requestUsername.js
'use server';

export default async function requestUsername(formData) {
const username = formData.get('username');
if (canRequest(username)) {
// ...
return 'successful';
}
return 'failed';
}
// UsernameForm.js
'use client';

import { useActionState } from 'react';
import requestUsername from './requestUsername';

function UsernameForm() {
const [state, action] = useActionState(requestUsername, null, 'n/a');

return (
<>
<form action={action}>
<input type="text" name="username" />
<button type="submit">Meminta</button>
</form>
<p>Respon dari pengiriman terakhir: {state}</p>
</>
);
}

Perlu diingat bahwa seperti Hook lainnya, useActionState hanya bisa dipanggil di kode klien.

Memanggil sebuah Aksi Server dari luar formulir <form>

Aksi Server adalah endpoint di sisi server dan bisa dipanggil dari mana saja di dalam kode klien.

Jika Anda menggunakan Aksi server di luar formulir, panggillah fungsi tersebut di dalam sebuah Transisi. Dengan begitu, Anda bisa menampilkan indikator pemuatan, melakukan pembaruan status optimistis, dan menangani error yang tidak terduga. Formulir akan secara otomatis membungkus Aksi Server di dalam transisi.

import incrementLike from './actions';
import { useState, useTransition } from 'react';

function LikeButton() {
const [isPending, startTransition] = useTransition();
const [likeCount, setLikeCount] = useState(0);

const onClick = () => {
startTransition(async () => {
const currentCount = await incrementLike();
setLikeCount(currentCount);
});
};

return (
<>
<p>Total Suka: {likeCount}</p>
<button onClick={onClick} disabled={isPending}>Suka</button>;
</>
);
}
// actions.js
'use server';

let likeCount = 0;
export default async function incrementLike() {
likeCount++;
return likeCount;
}

Untuk mendapatkan hasil dari Aksi Server, Anda perlu menunggu promise-nya dengan menggunakan await.