'use server'
'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 Fungsi Server.
async function addToCart(data) {
'use server';
// ...
}
Saat memanggil Fungsi Server dari klien, 'use server'
akan melakukan permintaan jaringan (network request) ke server dan menyertakan salinan ter-serialisasi dari setiap argumen yang dikirim. Jika Fungsi 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 diekspor dalam file tersebut sebagai Fungsi Server yang dapat digunakan di mana saja, termasuk diimpor dalam kode klien.
Catatan penting
'use server'
harus berada di paling atas dari fungsi atau modul; di atas kode-kode lain termasuk impor (tidak apa-apa menambahkan komentar di atas direktif). Direktif harus diapit tanda kutip tunggal atau ganda, bukan tanda kutip terbalik.'use server'
hanya dapat digunakan dalam file sisi server. Fungsi Server yang dihasilkan dapat diteruskan ke Komponen Klien melalui props. Lihat tipe untuk serialisasi yang didukung.- Untuk mengimpor Fungsi Server dari kode klien, direktif harus digunakan pada tingkat modul.
- Karena panggilan jaringan (network call) yang mendasarinya selalu asinkron,
'use server'
hanya dapat digunakan pada fungsi async. - Selalu perlakukan argumen ke Fungsi Server sebagai masukan yang tidak tepercaya dan otorisasi setiap mutasi. Lihat pertimbangan keamanan.
- Fungsi Server harus dipanggil dalam Transisi. Fungsi Server yang diteruskan ke
<form action>
atauformAction
akan secara otomatis dipanggil dalam transisi. - Fungsi Server dirancang untuk mutasi yang memperbarui state di sisi server; fungsi ini tidak direkomendasikan untuk pengambilan data. Oleh karena itu, framework yang menerapkan Fungsi Server biasanya memproses satu aksi dalam satu waktu dan tidak memiliki cara untuk melakukan caching terhadap nilai yang dikembalikan.
Pertimbangan keamanan
Argumen untuk Fungsi 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 Funsi Server, pastikan untuk memvalidasi bahwa pengguna yang sedang masuk diizinkan untuk melakukan aksi tersebut.
Argumen yang dapat diserialisasi dan nilai kembalian
Karena kode klien memanggil Fungsi Server melalui jaringan, setiap argumen yang dikirim harus dapat diserialisasi.
Berikut adalah tipe data yang didukung untuk argumen Fungsi Server:
- Primitif
- Iterable yang berisi nilai yang dapat diserialkan
- Date
- Instance FormData
- Objek biasa: objek yang dibuat dengan object initializers, dengan properti yang dapat diserialisasi
- Fungsi yang merupakan Fungsi Server
- Promises
Yang tidak didukung, antara lain:
- Elemen React, atau JSX
- Fungsi komponen atau fungsi lainnya yang bukan Fungsi 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')
- Event dari event handler
Nilai kembali yang dapat diserialisasi mengikuti aturan yang sama dengan properti yang bisa diserialisasi untuk Komponen Klien yang menjadi pembatas.
Penggunaan
Server Functions in forms
Fungsi 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 Fungsi 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 Fungsi Server yang diteruskan ke sebuah formulir <form>.
Ketika pengguna mengirim formulir ini, akan ada permintaan jaringan ke fungsi server requestUsername
. Saat memanggil Fungsi Server lewat formulir, React akan mengirimkan FormData dari formulir sebagai argumen pertama ke Fungsi Server tersebut.
Dengan meneruskan Fungsi 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 Fungsi 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 Fungsi Server dari luar formulir <form>
Fungsi Server adalah endpoint di sisi server dan bisa dipanggil dari mana saja di dalam kode klien.
Jika Anda menggunakan Fungsi Server di luar formulir, panggillah Fungsi Server tersebut di dalam sebuah Transisi, yang memungkinkan Anda menampilkan indikator pemuatan, melakukan pembaruan status optimistis, dan menangani error yang tidak terduga. Formulir akan secara otomatis membungkus Fungsi 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 Fungsi Server, Anda perlu menunggu promise-nya dengan menggunakan await
.